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