PHP fix int64 decoding (#2516)

* fix int64 decoding

* fix int64 decoding + tests
pull/2569/head
Sufir 8 years ago committed by Paul Yang
parent 2c16f6979a
commit 2bddffc993
  1. 75
      php/src/Google/Protobuf/Internal/InputStream.php
  2. 30
      php/tests/php_implementation_test.php

@ -160,40 +160,59 @@ class InputStream
*/
public function readVarint64(&$var)
{
$high = 0;
$low = 0;
$count = 0;
$b = 0;
do {
if ($this->current === $this->buffer_end) {
return false;
}
if ($count === self::MAX_VARINT_BYTES) {
return false;
}
$b = ord($this->buffer[$this->current]);
$bits = 7 * $count;
if ($bits >= 32) {
$high |= (($b & 0x7F) << ($bits - 32));
} else if ($bits > 25){
$high_bits = $bits - 25;
$low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
$high = $b & ((0x1 << $high_bits) -1);
} else {
$low |= (($b & 0x7F) << $bits);
}
$this->advance(1);
$count += 1;
} while ($b & 0x80);
if (PHP_INT_SIZE == 4) {
$high = 0;
$low = 0;
$b = 0;
do {
if ($this->current === $this->buffer_end) {
return false;
}
if ($count === self::MAX_VARINT_BYTES) {
return false;
}
$b = ord($this->buffer[$this->current]);
$bits = 7 * $count;
if ($bits >= 32) {
$high |= (($b & 0x7F) << ($bits - 32));
} else if ($bits > 25){
$high_bits = $bits - 25;
$low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
$high = $b & ((0x1 << $high_bits) -1);
} else {
$low |= (($b & 0x7F) << $bits);
}
$this->advance(1);
$count += 1;
} while ($b & 0x80);
$var = combineInt32ToInt64($high, $low);
} else {
$var = ($high & 0xFFFFFFFF) << 32 |
($low & 0xFFFFFFFF);
$result = 0;
$shift = 0;
do {
if ($this->current === $this->buffer_end) {
return false;
}
if ($count === self::MAX_VARINT_BYTES) {
return false;
}
$byte = ord($this->buffer[$this->current]);
$result |= ($byte & 0x7f) << $shift;
$shift += 7;
$this->advance(1);
$count += 1;
} while ($byte > 0x7f);
$var = $result;
}
return true;
}

@ -366,6 +366,36 @@ class ImplementationTest extends TestBase
$this->assertSame(32768, $var);
}
$this->assertFalse($input->readVarint64($var));
// Read 64 testing
if (PHP_INT_SIZE > 4) {
$testVals = array(
'10' => '0a000000000000000000',
'100' => '64000000000000000000',
'800' => 'a0060000000000000000',
'6400' => '80320000000000000000',
'70400' => '80a60400000000000000',
'774400' => '80a22f00000000000000',
'9292800' => '8098b704000000000000',
'74342400' => '80c0b923000000000000',
'743424000' => '8080bfe2020000000000',
'8177664000' => '8080b5bb1e0000000000',
'65421312000' => '8080a8dbf30100000000',
'785055744000' => '8080e0c7ec1600000000',
'9420668928000' => '808080dd969202000000',
'103627358208000' => '808080fff9c717000000',
'1139900940288000' => '808080f5bd9783020000',
'13678811283456000' => '808080fce699a6180000',
'109430490267648000' => '808080e0b7ceb1c20100',
'984874412408832000' => '808080e0f5c1bed50d00',
);
foreach ($testVals as $original => $encoded) {
$input = new InputStream(hex2bin($encoded));
$this->assertTrue($input->readVarint64($var));
$this->assertSame($original, $var);
}
}
}
public function testReadVarint32()

Loading…
Cancel
Save