Issues (44)

src/Adapter/BinaryReader.php (1 issue)

Severity
1
<?php
2
/**
3
 * This file contains the BinaryReader class.
4
 * For more information see the class description below.
5
 *
6
 * @author Peter Bathory <[email protected]>
7
 * @since 2016-02-18
8
 *
9
 * This code is open-source and licenced under the Modified BSD License.
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
namespace geoPHP\Adapter;
14
15
/**
16
 * Helper class BinaryReader
17
 *
18
 * A simple binary reader supporting both byte orders
19
 */
20
class BinaryReader extends BinaryAdapter
21
{
22
23
    /**
24
     * @var resource file pointer
25
     */
26
    private $buffer;
27
    
28
    /**
29
     * Opens a memory buffer with the given input
30
     *
31
     * @param string $input
32
     */
33
    public function __construct(string $input)
34
    {
35
        $this->open($input);
36
    }
37
38
    /**
39
     * Opens the memory buffer
40
     *
41
     * @param string $input
42
     * @throws \Exception
43
     * @return void
44
     */
45
    public function open(string $input)
46
    {
47
        $stream = fopen('php://memory', 'x+');
48
        if ($stream === false) {
49
            throw new \Exception("Error. Could not open PHP memory for writing.");
50
        }
51
        $this->buffer = $stream;
52
        fwrite($this->buffer, $input);
53
        fseek($this->buffer, 0);
54
    }
55
    
56
    /**
57
     * Closes the memory buffer
58
     * @return void
59
     */
60
    public function close()
61
    {
62
        if (isset($this->buffer) && is_resource($this->buffer)) {
63
            fclose($this->buffer);
64
        }
65
        unset($this->buffer);
66
    }
67
68
    /**
69
     * @return void
70
     */
71
    public function __destruct()
72
    {
73
        $this->close();
74
    }
75
    
76
    /**
77
     * Reads a signed 8-bit integer from the buffer
78
     *
79
     * @return int|null
80
     */
81
    public function readSInt8()
82
    {
83
        $char = fread($this->buffer, 1);
84
        $data = !empty($char) ? unpack("c", $char) : [];
85
        return !empty($data) ? current($data) : null;
86
    }
87
88
    /**
89
     * Reads an unsigned 8-bit integer from the buffer
90
     *
91
     * @return int|null
92
     */
93
    public function readUInt8()
94
    {
95
        $char = fread($this->buffer, 1);
96
        $data = !empty($char) ? unpack("C", $char) : [];
97
        return !empty($data) ? current($data) : null;
98
    }
99
100
    /**
101
     * Reads an unsigned 32-bit integer from the buffer
102
     *
103
     * @return int|null
104
     */
105
    public function readUInt32()
106
    {
107
        $int32 = fread($this->buffer, 4);
108
        $data = !empty($int32) ? unpack($this->isLittleEndian() ? 'V' : 'N', $int32) : [];
109
        return !empty($data) ? current($data) : null;
110
    }
111
112
    /**
113
     * Reads one or more double values from the buffer
114
     * @param int $length How many double values to read. Default is 1
115
     *
116
     * @return float[]
117
     */
118
    public function readDoubles($length = 1): array
119
    {
120
        $bin = fread($this->buffer, $length);
121
        $data = !empty($bin) ? ($this->isLittleEndian() ? unpack("d*", $bin) : unpack("d*", strrev($bin))) : [];
122
        return is_array($data) ? array_values($data) : [];
0 ignored issues
show
The condition is_array($data) is always true.
Loading history...
123
    }
124
125
    /**
126
     * Reads an unsigned base-128 varint from the buffer
127
     * Ported from https://github.com/cschwarz/wkx/blob/master/lib/binaryreader.js
128
     *
129
     * @return int
130
     */
131
    public function readUVarInt(): int
132
    {
133
        $result = 0;
134
        $bytesRead = 0;
135
136
        do {
137
            $nextByte = $this->readUInt8();
138
            $result += ($nextByte & 0x7F) << (7 * $bytesRead);
139
            ++$bytesRead;
140
        } while ($nextByte >= 0x80);
141
        return $result;
142
    }
143
144
    /**
145
     * Reads a signed base-128 varint from the buffer
146
     *
147
     * @return int
148
     */
149
    public function readSVarInt(): int
150
    {
151
        return self::zigZagDecode($this->readUVarInt());
152
    }
153
154
    /**
155
     * ZigZag decoding maps unsigned integers to signed integers
156
     *
157
     * @param int $value Encrypted positive integer value
158
     * @return int Decoded signed integer
159
     */
160
    public static function zigZagDecode($value): int
161
    {
162
        return ($value & 1) === 0 ? $value >> 1 : -($value >> 1) - 1;
163
    }
164
}
165