xref: /aosp_15_r20/external/flatbuffers/php/ByteBuffer.php (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker<?php
2*890232f2SAndroid Build Coastguard Worker/*
3*890232f2SAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
4*890232f2SAndroid Build Coastguard Worker *
5*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*890232f2SAndroid Build Coastguard Worker *
9*890232f2SAndroid Build Coastguard Worker *     http://www.apache.org/licenses/LICENSE-2.0
10*890232f2SAndroid Build Coastguard Worker *
11*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*890232f2SAndroid Build Coastguard Worker * limitations under the License.
16*890232f2SAndroid Build Coastguard Worker */
17*890232f2SAndroid Build Coastguard Worker
18*890232f2SAndroid Build Coastguard Workernamespace Google\FlatBuffers;
19*890232f2SAndroid Build Coastguard Worker
20*890232f2SAndroid Build Coastguard Workerclass ByteBuffer
21*890232f2SAndroid Build Coastguard Worker{
22*890232f2SAndroid Build Coastguard Worker    /**
23*890232f2SAndroid Build Coastguard Worker     * @var string $_buffer;
24*890232f2SAndroid Build Coastguard Worker     */
25*890232f2SAndroid Build Coastguard Worker    public $_buffer;
26*890232f2SAndroid Build Coastguard Worker
27*890232f2SAndroid Build Coastguard Worker    /**
28*890232f2SAndroid Build Coastguard Worker     * @var int $_pos;
29*890232f2SAndroid Build Coastguard Worker     */
30*890232f2SAndroid Build Coastguard Worker    private $_pos;
31*890232f2SAndroid Build Coastguard Worker
32*890232f2SAndroid Build Coastguard Worker    /**
33*890232f2SAndroid Build Coastguard Worker     * @var bool $_is_little_endian
34*890232f2SAndroid Build Coastguard Worker     */
35*890232f2SAndroid Build Coastguard Worker    private static $_is_little_endian = null;
36*890232f2SAndroid Build Coastguard Worker
37*890232f2SAndroid Build Coastguard Worker    public static function wrap($bytes)
38*890232f2SAndroid Build Coastguard Worker    {
39*890232f2SAndroid Build Coastguard Worker        $bb = new ByteBuffer(0);
40*890232f2SAndroid Build Coastguard Worker        $bb->_buffer = $bytes;
41*890232f2SAndroid Build Coastguard Worker
42*890232f2SAndroid Build Coastguard Worker        return $bb;
43*890232f2SAndroid Build Coastguard Worker    }
44*890232f2SAndroid Build Coastguard Worker
45*890232f2SAndroid Build Coastguard Worker    /**
46*890232f2SAndroid Build Coastguard Worker     * @param $size
47*890232f2SAndroid Build Coastguard Worker     */
48*890232f2SAndroid Build Coastguard Worker    public function __construct($size)
49*890232f2SAndroid Build Coastguard Worker    {
50*890232f2SAndroid Build Coastguard Worker        $this->_buffer = str_repeat("\0", $size);
51*890232f2SAndroid Build Coastguard Worker    }
52*890232f2SAndroid Build Coastguard Worker
53*890232f2SAndroid Build Coastguard Worker    /**
54*890232f2SAndroid Build Coastguard Worker     * @return int
55*890232f2SAndroid Build Coastguard Worker     */
56*890232f2SAndroid Build Coastguard Worker    public function capacity()
57*890232f2SAndroid Build Coastguard Worker    {
58*890232f2SAndroid Build Coastguard Worker        return strlen($this->_buffer);
59*890232f2SAndroid Build Coastguard Worker    }
60*890232f2SAndroid Build Coastguard Worker
61*890232f2SAndroid Build Coastguard Worker    /**
62*890232f2SAndroid Build Coastguard Worker     * @return int
63*890232f2SAndroid Build Coastguard Worker     */
64*890232f2SAndroid Build Coastguard Worker    public function getPosition()
65*890232f2SAndroid Build Coastguard Worker    {
66*890232f2SAndroid Build Coastguard Worker        return $this->_pos;
67*890232f2SAndroid Build Coastguard Worker    }
68*890232f2SAndroid Build Coastguard Worker
69*890232f2SAndroid Build Coastguard Worker    /**
70*890232f2SAndroid Build Coastguard Worker     * @param $pos
71*890232f2SAndroid Build Coastguard Worker     */
72*890232f2SAndroid Build Coastguard Worker    public function setPosition($pos)
73*890232f2SAndroid Build Coastguard Worker    {
74*890232f2SAndroid Build Coastguard Worker        $this->_pos = $pos;
75*890232f2SAndroid Build Coastguard Worker    }
76*890232f2SAndroid Build Coastguard Worker
77*890232f2SAndroid Build Coastguard Worker    /**
78*890232f2SAndroid Build Coastguard Worker     *
79*890232f2SAndroid Build Coastguard Worker     */
80*890232f2SAndroid Build Coastguard Worker    public function reset()
81*890232f2SAndroid Build Coastguard Worker    {
82*890232f2SAndroid Build Coastguard Worker        $this->_pos = 0;
83*890232f2SAndroid Build Coastguard Worker    }
84*890232f2SAndroid Build Coastguard Worker
85*890232f2SAndroid Build Coastguard Worker    /**
86*890232f2SAndroid Build Coastguard Worker     * @return int
87*890232f2SAndroid Build Coastguard Worker     */
88*890232f2SAndroid Build Coastguard Worker    public function length()
89*890232f2SAndroid Build Coastguard Worker    {
90*890232f2SAndroid Build Coastguard Worker        return strlen($this->_buffer);
91*890232f2SAndroid Build Coastguard Worker    }
92*890232f2SAndroid Build Coastguard Worker
93*890232f2SAndroid Build Coastguard Worker    /**
94*890232f2SAndroid Build Coastguard Worker     * @return string
95*890232f2SAndroid Build Coastguard Worker     */
96*890232f2SAndroid Build Coastguard Worker    public function data()
97*890232f2SAndroid Build Coastguard Worker    {
98*890232f2SAndroid Build Coastguard Worker        return substr($this->_buffer, $this->_pos);
99*890232f2SAndroid Build Coastguard Worker    }
100*890232f2SAndroid Build Coastguard Worker
101*890232f2SAndroid Build Coastguard Worker    /**
102*890232f2SAndroid Build Coastguard Worker     * @return bool
103*890232f2SAndroid Build Coastguard Worker     */
104*890232f2SAndroid Build Coastguard Worker    public static function isLittleEndian()
105*890232f2SAndroid Build Coastguard Worker    {
106*890232f2SAndroid Build Coastguard Worker        if (ByteBuffer::$_is_little_endian === null) {
107*890232f2SAndroid Build Coastguard Worker            ByteBuffer::$_is_little_endian = unpack('S', "\x01\x00")[1] === 1;
108*890232f2SAndroid Build Coastguard Worker        }
109*890232f2SAndroid Build Coastguard Worker
110*890232f2SAndroid Build Coastguard Worker        return ByteBuffer::$_is_little_endian;
111*890232f2SAndroid Build Coastguard Worker    }
112*890232f2SAndroid Build Coastguard Worker
113*890232f2SAndroid Build Coastguard Worker    /**
114*890232f2SAndroid Build Coastguard Worker     * write little endian value to the buffer.
115*890232f2SAndroid Build Coastguard Worker     *
116*890232f2SAndroid Build Coastguard Worker     * @param $offset
117*890232f2SAndroid Build Coastguard Worker     * @param $count byte length
118*890232f2SAndroid Build Coastguard Worker     * @param $data actual values
119*890232f2SAndroid Build Coastguard Worker     */
120*890232f2SAndroid Build Coastguard Worker    public function writeLittleEndian($offset, $count, $data)
121*890232f2SAndroid Build Coastguard Worker    {
122*890232f2SAndroid Build Coastguard Worker        if (ByteBuffer::isLittleEndian()) {
123*890232f2SAndroid Build Coastguard Worker            for ($i = 0; $i < $count; $i++) {
124*890232f2SAndroid Build Coastguard Worker                $this->_buffer[$offset + $i] = chr($data >> $i * 8);
125*890232f2SAndroid Build Coastguard Worker            }
126*890232f2SAndroid Build Coastguard Worker        } else {
127*890232f2SAndroid Build Coastguard Worker            for ($i = 0; $i < $count; $i++) {
128*890232f2SAndroid Build Coastguard Worker                $this->_buffer[$offset + $count - 1 - $i] = chr($data >> $i * 8);
129*890232f2SAndroid Build Coastguard Worker            }
130*890232f2SAndroid Build Coastguard Worker        }
131*890232f2SAndroid Build Coastguard Worker    }
132*890232f2SAndroid Build Coastguard Worker
133*890232f2SAndroid Build Coastguard Worker    /**
134*890232f2SAndroid Build Coastguard Worker     * read little endian value from the buffer
135*890232f2SAndroid Build Coastguard Worker     *
136*890232f2SAndroid Build Coastguard Worker     * @param $offset
137*890232f2SAndroid Build Coastguard Worker     * @param $count acutal size
138*890232f2SAndroid Build Coastguard Worker     * @return int
139*890232f2SAndroid Build Coastguard Worker     */
140*890232f2SAndroid Build Coastguard Worker    public function readLittleEndian($offset, $count, $force_bigendian = false)
141*890232f2SAndroid Build Coastguard Worker    {
142*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, $count);
143*890232f2SAndroid Build Coastguard Worker        $r = 0;
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard Worker        if (ByteBuffer::isLittleEndian() && $force_bigendian == false) {
146*890232f2SAndroid Build Coastguard Worker            for ($i = 0; $i < $count; $i++) {
147*890232f2SAndroid Build Coastguard Worker                $r |= ord($this->_buffer[$offset + $i]) << $i * 8;
148*890232f2SAndroid Build Coastguard Worker            }
149*890232f2SAndroid Build Coastguard Worker        } else {
150*890232f2SAndroid Build Coastguard Worker            for ($i = 0; $i < $count; $i++) {
151*890232f2SAndroid Build Coastguard Worker                $r |= ord($this->_buffer[$offset + $count -1 - $i]) << $i * 8;
152*890232f2SAndroid Build Coastguard Worker            }
153*890232f2SAndroid Build Coastguard Worker        }
154*890232f2SAndroid Build Coastguard Worker
155*890232f2SAndroid Build Coastguard Worker        return $r;
156*890232f2SAndroid Build Coastguard Worker    }
157*890232f2SAndroid Build Coastguard Worker
158*890232f2SAndroid Build Coastguard Worker    /**
159*890232f2SAndroid Build Coastguard Worker     * @param $offset
160*890232f2SAndroid Build Coastguard Worker     * @param $length
161*890232f2SAndroid Build Coastguard Worker     */
162*890232f2SAndroid Build Coastguard Worker    public function assertOffsetAndLength($offset, $length)
163*890232f2SAndroid Build Coastguard Worker    {
164*890232f2SAndroid Build Coastguard Worker        if ($offset < 0 ||
165*890232f2SAndroid Build Coastguard Worker            $offset >= strlen($this->_buffer) ||
166*890232f2SAndroid Build Coastguard Worker            $offset + $length > strlen($this->_buffer)) {
167*890232f2SAndroid Build Coastguard Worker            throw new \OutOfRangeException(sprintf("offset: %d, length: %d, buffer; %d", $offset, $length, strlen($this->_buffer)));
168*890232f2SAndroid Build Coastguard Worker        }
169*890232f2SAndroid Build Coastguard Worker    }
170*890232f2SAndroid Build Coastguard Worker
171*890232f2SAndroid Build Coastguard Worker    /**
172*890232f2SAndroid Build Coastguard Worker     * @param $offset
173*890232f2SAndroid Build Coastguard Worker     * @param $value
174*890232f2SAndroid Build Coastguard Worker     * @return mixed
175*890232f2SAndroid Build Coastguard Worker     */
176*890232f2SAndroid Build Coastguard Worker    public function putSbyte($offset, $value)
177*890232f2SAndroid Build Coastguard Worker    {
178*890232f2SAndroid Build Coastguard Worker        self::validateValue(-128, 127, $value, "sbyte");
179*890232f2SAndroid Build Coastguard Worker
180*890232f2SAndroid Build Coastguard Worker        $length = strlen($value);
181*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, $length);
182*890232f2SAndroid Build Coastguard Worker        return $this->_buffer[$offset] = $value;
183*890232f2SAndroid Build Coastguard Worker    }
184*890232f2SAndroid Build Coastguard Worker
185*890232f2SAndroid Build Coastguard Worker    /**
186*890232f2SAndroid Build Coastguard Worker     * @param $offset
187*890232f2SAndroid Build Coastguard Worker     * @param $value
188*890232f2SAndroid Build Coastguard Worker     * @return mixed
189*890232f2SAndroid Build Coastguard Worker     */
190*890232f2SAndroid Build Coastguard Worker    public function putByte($offset, $value)
191*890232f2SAndroid Build Coastguard Worker    {
192*890232f2SAndroid Build Coastguard Worker        self::validateValue(0, 255, $value, "byte");
193*890232f2SAndroid Build Coastguard Worker
194*890232f2SAndroid Build Coastguard Worker        $length = strlen($value);
195*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, $length);
196*890232f2SAndroid Build Coastguard Worker        return $this->_buffer[$offset] = $value;
197*890232f2SAndroid Build Coastguard Worker    }
198*890232f2SAndroid Build Coastguard Worker
199*890232f2SAndroid Build Coastguard Worker    /**
200*890232f2SAndroid Build Coastguard Worker     * @param $offset
201*890232f2SAndroid Build Coastguard Worker     * @param $value
202*890232f2SAndroid Build Coastguard Worker     */
203*890232f2SAndroid Build Coastguard Worker    public function put($offset, $value)
204*890232f2SAndroid Build Coastguard Worker    {
205*890232f2SAndroid Build Coastguard Worker        $length = strlen($value);
206*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, $length);
207*890232f2SAndroid Build Coastguard Worker        for ($i = 0; $i < $length; $i++) {
208*890232f2SAndroid Build Coastguard Worker            $this->_buffer[$offset + $i] = $value[$i];
209*890232f2SAndroid Build Coastguard Worker        }
210*890232f2SAndroid Build Coastguard Worker    }
211*890232f2SAndroid Build Coastguard Worker
212*890232f2SAndroid Build Coastguard Worker    /**
213*890232f2SAndroid Build Coastguard Worker     * @param $offset
214*890232f2SAndroid Build Coastguard Worker     * @param $value
215*890232f2SAndroid Build Coastguard Worker     */
216*890232f2SAndroid Build Coastguard Worker    public function putShort($offset, $value)
217*890232f2SAndroid Build Coastguard Worker    {
218*890232f2SAndroid Build Coastguard Worker        self::validateValue(-32768, 32767, $value, "short");
219*890232f2SAndroid Build Coastguard Worker
220*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 2);
221*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 2, $value);
222*890232f2SAndroid Build Coastguard Worker    }
223*890232f2SAndroid Build Coastguard Worker
224*890232f2SAndroid Build Coastguard Worker    /**
225*890232f2SAndroid Build Coastguard Worker     * @param $offset
226*890232f2SAndroid Build Coastguard Worker     * @param $value
227*890232f2SAndroid Build Coastguard Worker     */
228*890232f2SAndroid Build Coastguard Worker    public function putUshort($offset, $value)
229*890232f2SAndroid Build Coastguard Worker    {
230*890232f2SAndroid Build Coastguard Worker        self::validateValue(0, 65535, $value, "short");
231*890232f2SAndroid Build Coastguard Worker
232*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 2);
233*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 2, $value);
234*890232f2SAndroid Build Coastguard Worker    }
235*890232f2SAndroid Build Coastguard Worker
236*890232f2SAndroid Build Coastguard Worker    /**
237*890232f2SAndroid Build Coastguard Worker     * @param $offset
238*890232f2SAndroid Build Coastguard Worker     * @param $value
239*890232f2SAndroid Build Coastguard Worker     */
240*890232f2SAndroid Build Coastguard Worker    public function putInt($offset, $value)
241*890232f2SAndroid Build Coastguard Worker    {
242*890232f2SAndroid Build Coastguard Worker        // 2147483647 = (1 << 31) -1 = Maximum signed 32-bit int
243*890232f2SAndroid Build Coastguard Worker        // -2147483648 = -1 << 31 = Minimum signed 32-bit int
244*890232f2SAndroid Build Coastguard Worker        self::validateValue(-2147483648, 2147483647, $value, "int");
245*890232f2SAndroid Build Coastguard Worker
246*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 4);
247*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 4, $value);
248*890232f2SAndroid Build Coastguard Worker    }
249*890232f2SAndroid Build Coastguard Worker
250*890232f2SAndroid Build Coastguard Worker    /**
251*890232f2SAndroid Build Coastguard Worker     * @param $offset
252*890232f2SAndroid Build Coastguard Worker     * @param $value
253*890232f2SAndroid Build Coastguard Worker     */
254*890232f2SAndroid Build Coastguard Worker    public function putUint($offset, $value)
255*890232f2SAndroid Build Coastguard Worker    {
256*890232f2SAndroid Build Coastguard Worker        // NOTE: We can't put big integer value. this is PHP limitation.
257*890232f2SAndroid Build Coastguard Worker        // 4294967295 = (1 << 32) -1 = Maximum unsigned 32-bin int
258*890232f2SAndroid Build Coastguard Worker        self::validateValue(0, 4294967295, $value, "uint",  " php has big numbers limitation. check your PHP_INT_MAX");
259*890232f2SAndroid Build Coastguard Worker
260*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 4);
261*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 4, $value);
262*890232f2SAndroid Build Coastguard Worker    }
263*890232f2SAndroid Build Coastguard Worker
264*890232f2SAndroid Build Coastguard Worker    /**
265*890232f2SAndroid Build Coastguard Worker     * @param $offset
266*890232f2SAndroid Build Coastguard Worker     * @param $value
267*890232f2SAndroid Build Coastguard Worker     */
268*890232f2SAndroid Build Coastguard Worker    public function putLong($offset, $value)
269*890232f2SAndroid Build Coastguard Worker    {
270*890232f2SAndroid Build Coastguard Worker        // NOTE: We can't put big integer value. this is PHP limitation.
271*890232f2SAndroid Build Coastguard Worker        self::validateValue(~PHP_INT_MAX, PHP_INT_MAX, $value, "long",  " php has big numbers limitation. check your PHP_INT_MAX");
272*890232f2SAndroid Build Coastguard Worker
273*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 8);
274*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 8, $value);
275*890232f2SAndroid Build Coastguard Worker    }
276*890232f2SAndroid Build Coastguard Worker
277*890232f2SAndroid Build Coastguard Worker    /**
278*890232f2SAndroid Build Coastguard Worker     * @param $offset
279*890232f2SAndroid Build Coastguard Worker     * @param $value
280*890232f2SAndroid Build Coastguard Worker     */
281*890232f2SAndroid Build Coastguard Worker    public function putUlong($offset, $value)
282*890232f2SAndroid Build Coastguard Worker    {
283*890232f2SAndroid Build Coastguard Worker        // NOTE: We can't put big integer value. this is PHP limitation.
284*890232f2SAndroid Build Coastguard Worker        self::validateValue(0, PHP_INT_MAX, $value, "long", " php has big numbers limitation. check your PHP_INT_MAX");
285*890232f2SAndroid Build Coastguard Worker
286*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 8);
287*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 8, $value);
288*890232f2SAndroid Build Coastguard Worker    }
289*890232f2SAndroid Build Coastguard Worker
290*890232f2SAndroid Build Coastguard Worker    /**
291*890232f2SAndroid Build Coastguard Worker     * @param $offset
292*890232f2SAndroid Build Coastguard Worker     * @param $value
293*890232f2SAndroid Build Coastguard Worker     */
294*890232f2SAndroid Build Coastguard Worker    public function putFloat($offset, $value)
295*890232f2SAndroid Build Coastguard Worker    {
296*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 4);
297*890232f2SAndroid Build Coastguard Worker
298*890232f2SAndroid Build Coastguard Worker        $floathelper = pack("f", $value);
299*890232f2SAndroid Build Coastguard Worker        $v = unpack("V", $floathelper);
300*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 4, $v[1]);
301*890232f2SAndroid Build Coastguard Worker    }
302*890232f2SAndroid Build Coastguard Worker
303*890232f2SAndroid Build Coastguard Worker    /**
304*890232f2SAndroid Build Coastguard Worker     * @param $offset
305*890232f2SAndroid Build Coastguard Worker     * @param $value
306*890232f2SAndroid Build Coastguard Worker     */
307*890232f2SAndroid Build Coastguard Worker    public function putDouble($offset, $value)
308*890232f2SAndroid Build Coastguard Worker    {
309*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($offset, 8);
310*890232f2SAndroid Build Coastguard Worker
311*890232f2SAndroid Build Coastguard Worker        $floathelper = pack("d", $value);
312*890232f2SAndroid Build Coastguard Worker        $v = unpack("V*", $floathelper);
313*890232f2SAndroid Build Coastguard Worker
314*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset, 4, $v[1]);
315*890232f2SAndroid Build Coastguard Worker        $this->writeLittleEndian($offset + 4, 4, $v[2]);
316*890232f2SAndroid Build Coastguard Worker    }
317*890232f2SAndroid Build Coastguard Worker
318*890232f2SAndroid Build Coastguard Worker    /**
319*890232f2SAndroid Build Coastguard Worker     * @param $index
320*890232f2SAndroid Build Coastguard Worker     * @return mixed
321*890232f2SAndroid Build Coastguard Worker     */
322*890232f2SAndroid Build Coastguard Worker    public function getByte($index)
323*890232f2SAndroid Build Coastguard Worker    {
324*890232f2SAndroid Build Coastguard Worker        return ord($this->_buffer[$index]);
325*890232f2SAndroid Build Coastguard Worker    }
326*890232f2SAndroid Build Coastguard Worker
327*890232f2SAndroid Build Coastguard Worker    /**
328*890232f2SAndroid Build Coastguard Worker     * @param $index
329*890232f2SAndroid Build Coastguard Worker     * @return mixed
330*890232f2SAndroid Build Coastguard Worker     */
331*890232f2SAndroid Build Coastguard Worker    public function getSbyte($index)
332*890232f2SAndroid Build Coastguard Worker    {
333*890232f2SAndroid Build Coastguard Worker        $v = unpack("c", $this->_buffer[$index]);
334*890232f2SAndroid Build Coastguard Worker        return $v[1];
335*890232f2SAndroid Build Coastguard Worker    }
336*890232f2SAndroid Build Coastguard Worker
337*890232f2SAndroid Build Coastguard Worker    /**
338*890232f2SAndroid Build Coastguard Worker     * @param $buffer
339*890232f2SAndroid Build Coastguard Worker     */
340*890232f2SAndroid Build Coastguard Worker    public function getX(&$buffer)
341*890232f2SAndroid Build Coastguard Worker    {
342*890232f2SAndroid Build Coastguard Worker        for ($i = $this->_pos, $j = 0; $j < strlen($buffer); $i++, $j++) {
343*890232f2SAndroid Build Coastguard Worker            $buffer[$j] = $this->_buffer[$i];
344*890232f2SAndroid Build Coastguard Worker        }
345*890232f2SAndroid Build Coastguard Worker    }
346*890232f2SAndroid Build Coastguard Worker
347*890232f2SAndroid Build Coastguard Worker    /**
348*890232f2SAndroid Build Coastguard Worker     * @param $index
349*890232f2SAndroid Build Coastguard Worker     * @return mixed
350*890232f2SAndroid Build Coastguard Worker     */
351*890232f2SAndroid Build Coastguard Worker    public function get($index)
352*890232f2SAndroid Build Coastguard Worker    {
353*890232f2SAndroid Build Coastguard Worker        $this->assertOffsetAndLength($index, 1);
354*890232f2SAndroid Build Coastguard Worker        return $this->_buffer[$index];
355*890232f2SAndroid Build Coastguard Worker    }
356*890232f2SAndroid Build Coastguard Worker
357*890232f2SAndroid Build Coastguard Worker
358*890232f2SAndroid Build Coastguard Worker    /**
359*890232f2SAndroid Build Coastguard Worker     * @param $index
360*890232f2SAndroid Build Coastguard Worker     * @return mixed
361*890232f2SAndroid Build Coastguard Worker     */
362*890232f2SAndroid Build Coastguard Worker    public function getBool($index)
363*890232f2SAndroid Build Coastguard Worker    {
364*890232f2SAndroid Build Coastguard Worker        return (bool)ord($this->_buffer[$index]);
365*890232f2SAndroid Build Coastguard Worker    }
366*890232f2SAndroid Build Coastguard Worker
367*890232f2SAndroid Build Coastguard Worker    /**
368*890232f2SAndroid Build Coastguard Worker     * @param $index
369*890232f2SAndroid Build Coastguard Worker     * @return int
370*890232f2SAndroid Build Coastguard Worker     */
371*890232f2SAndroid Build Coastguard Worker    public function getShort($index)
372*890232f2SAndroid Build Coastguard Worker    {
373*890232f2SAndroid Build Coastguard Worker        $result = $this->readLittleEndian($index, 2);
374*890232f2SAndroid Build Coastguard Worker
375*890232f2SAndroid Build Coastguard Worker        $sign = $index + (ByteBuffer::isLittleEndian() ? 1 : 0);
376*890232f2SAndroid Build Coastguard Worker        $issigned = isset($this->_buffer[$sign]) && ord($this->_buffer[$sign]) & 0x80;
377*890232f2SAndroid Build Coastguard Worker
378*890232f2SAndroid Build Coastguard Worker        // 65536 = 1 << 16 = Maximum unsigned 16-bit int
379*890232f2SAndroid Build Coastguard Worker        return $issigned ? $result - 65536 : $result;
380*890232f2SAndroid Build Coastguard Worker    }
381*890232f2SAndroid Build Coastguard Worker
382*890232f2SAndroid Build Coastguard Worker    /**
383*890232f2SAndroid Build Coastguard Worker     * @param $index
384*890232f2SAndroid Build Coastguard Worker     * @return int
385*890232f2SAndroid Build Coastguard Worker     */
386*890232f2SAndroid Build Coastguard Worker    public function getUShort($index)
387*890232f2SAndroid Build Coastguard Worker    {
388*890232f2SAndroid Build Coastguard Worker        return $this->readLittleEndian($index, 2);
389*890232f2SAndroid Build Coastguard Worker    }
390*890232f2SAndroid Build Coastguard Worker
391*890232f2SAndroid Build Coastguard Worker    /**
392*890232f2SAndroid Build Coastguard Worker     * @param $index
393*890232f2SAndroid Build Coastguard Worker     * @return int
394*890232f2SAndroid Build Coastguard Worker     */
395*890232f2SAndroid Build Coastguard Worker    public function getInt($index)
396*890232f2SAndroid Build Coastguard Worker    {
397*890232f2SAndroid Build Coastguard Worker        $result = $this->readLittleEndian($index, 4);
398*890232f2SAndroid Build Coastguard Worker
399*890232f2SAndroid Build Coastguard Worker        $sign = $index + (ByteBuffer::isLittleEndian() ? 3 : 0);
400*890232f2SAndroid Build Coastguard Worker        $issigned = isset($this->_buffer[$sign]) && ord($this->_buffer[$sign]) & 0x80;
401*890232f2SAndroid Build Coastguard Worker
402*890232f2SAndroid Build Coastguard Worker        if (PHP_INT_SIZE > 4) {
403*890232f2SAndroid Build Coastguard Worker            // 4294967296 = 1 << 32 = Maximum unsigned 32-bit int
404*890232f2SAndroid Build Coastguard Worker            return $issigned ? $result - 4294967296 : $result;
405*890232f2SAndroid Build Coastguard Worker        } else {
406*890232f2SAndroid Build Coastguard Worker            // 32bit / Windows treated number as signed integer.
407*890232f2SAndroid Build Coastguard Worker            return $result;
408*890232f2SAndroid Build Coastguard Worker        }
409*890232f2SAndroid Build Coastguard Worker    }
410*890232f2SAndroid Build Coastguard Worker
411*890232f2SAndroid Build Coastguard Worker    /**
412*890232f2SAndroid Build Coastguard Worker     * @param $index
413*890232f2SAndroid Build Coastguard Worker     * @return int
414*890232f2SAndroid Build Coastguard Worker     */
415*890232f2SAndroid Build Coastguard Worker    public function getUint($index)
416*890232f2SAndroid Build Coastguard Worker    {
417*890232f2SAndroid Build Coastguard Worker        return $this->readLittleEndian($index, 4);
418*890232f2SAndroid Build Coastguard Worker    }
419*890232f2SAndroid Build Coastguard Worker
420*890232f2SAndroid Build Coastguard Worker    /**
421*890232f2SAndroid Build Coastguard Worker     * @param $index
422*890232f2SAndroid Build Coastguard Worker     * @return int
423*890232f2SAndroid Build Coastguard Worker     */
424*890232f2SAndroid Build Coastguard Worker    public function getLong($index)
425*890232f2SAndroid Build Coastguard Worker    {
426*890232f2SAndroid Build Coastguard Worker        return $this->readLittleEndian($index, 8);
427*890232f2SAndroid Build Coastguard Worker    }
428*890232f2SAndroid Build Coastguard Worker
429*890232f2SAndroid Build Coastguard Worker    /**
430*890232f2SAndroid Build Coastguard Worker     * @param $index
431*890232f2SAndroid Build Coastguard Worker     * @return int
432*890232f2SAndroid Build Coastguard Worker     */
433*890232f2SAndroid Build Coastguard Worker    public function getUlong($index)
434*890232f2SAndroid Build Coastguard Worker    {
435*890232f2SAndroid Build Coastguard Worker        return $this->readLittleEndian($index, 8);
436*890232f2SAndroid Build Coastguard Worker    }
437*890232f2SAndroid Build Coastguard Worker
438*890232f2SAndroid Build Coastguard Worker    /**
439*890232f2SAndroid Build Coastguard Worker     * @param $index
440*890232f2SAndroid Build Coastguard Worker     * @return mixed
441*890232f2SAndroid Build Coastguard Worker     */
442*890232f2SAndroid Build Coastguard Worker    public function getFloat($index)
443*890232f2SAndroid Build Coastguard Worker    {
444*890232f2SAndroid Build Coastguard Worker        $i = $this->readLittleEndian($index, 4);
445*890232f2SAndroid Build Coastguard Worker
446*890232f2SAndroid Build Coastguard Worker        return self::convertHelper(self::__FLOAT, $i);
447*890232f2SAndroid Build Coastguard Worker    }
448*890232f2SAndroid Build Coastguard Worker
449*890232f2SAndroid Build Coastguard Worker    /**
450*890232f2SAndroid Build Coastguard Worker     * @param $index
451*890232f2SAndroid Build Coastguard Worker     * @return float
452*890232f2SAndroid Build Coastguard Worker     */
453*890232f2SAndroid Build Coastguard Worker    public function getDouble($index)
454*890232f2SAndroid Build Coastguard Worker    {
455*890232f2SAndroid Build Coastguard Worker        $i = $this->readLittleEndian($index, 4);
456*890232f2SAndroid Build Coastguard Worker        $i2 = $this->readLittleEndian($index + 4, 4);
457*890232f2SAndroid Build Coastguard Worker
458*890232f2SAndroid Build Coastguard Worker        return self::convertHelper(self::__DOUBLE, $i, $i2);
459*890232f2SAndroid Build Coastguard Worker    }
460*890232f2SAndroid Build Coastguard Worker
461*890232f2SAndroid Build Coastguard Worker    const __SHORT = 1;
462*890232f2SAndroid Build Coastguard Worker    const __INT = 2;
463*890232f2SAndroid Build Coastguard Worker    const __LONG = 3;
464*890232f2SAndroid Build Coastguard Worker    const __FLOAT = 4;
465*890232f2SAndroid Build Coastguard Worker    const __DOUBLE = 5;
466*890232f2SAndroid Build Coastguard Worker    private static function convertHelper($type, $value, $value2 = null) {
467*890232f2SAndroid Build Coastguard Worker        // readLittleEndian construct unsigned integer value from bytes. we have to encode this value to
468*890232f2SAndroid Build Coastguard Worker        // correct bytes, and decode as expected types with `unpack` function.
469*890232f2SAndroid Build Coastguard Worker        // then it returns correct type value.
470*890232f2SAndroid Build Coastguard Worker        // see also: http://php.net/manual/en/function.pack.php
471*890232f2SAndroid Build Coastguard Worker
472*890232f2SAndroid Build Coastguard Worker        switch ($type) {
473*890232f2SAndroid Build Coastguard Worker            case self::__FLOAT:
474*890232f2SAndroid Build Coastguard Worker                $inthelper = pack("V", $value);
475*890232f2SAndroid Build Coastguard Worker                $v = unpack("f", $inthelper);
476*890232f2SAndroid Build Coastguard Worker                return $v[1];
477*890232f2SAndroid Build Coastguard Worker                break;
478*890232f2SAndroid Build Coastguard Worker            case self::__DOUBLE:
479*890232f2SAndroid Build Coastguard Worker                $inthelper = pack("VV", $value, $value2);
480*890232f2SAndroid Build Coastguard Worker                $v = unpack("d", $inthelper);
481*890232f2SAndroid Build Coastguard Worker                return $v[1];
482*890232f2SAndroid Build Coastguard Worker                break;
483*890232f2SAndroid Build Coastguard Worker            default:
484*890232f2SAndroid Build Coastguard Worker                throw new \Exception(sprintf("unexpected type %d specified", $type));
485*890232f2SAndroid Build Coastguard Worker        }
486*890232f2SAndroid Build Coastguard Worker    }
487*890232f2SAndroid Build Coastguard Worker
488*890232f2SAndroid Build Coastguard Worker    private static function validateValue($min, $max, $value, $type, $additional_notes = "") {
489*890232f2SAndroid Build Coastguard Worker        if(!($min <= $value && $value <= $max)) {
490*890232f2SAndroid Build Coastguard Worker            throw new \InvalidArgumentException(sprintf("bad number %s for type %s.%s", $value, $type, $additional_notes));
491*890232f2SAndroid Build Coastguard Worker        }
492*890232f2SAndroid Build Coastguard Worker    }
493*890232f2SAndroid Build Coastguard Worker}
494