Commit d1fde361 authored by Bo Yang's avatar Bo Yang

Fix int64 decoding on 32-bit machines.

parent c871ce6e
...@@ -43,8 +43,15 @@ class GPBUtil ...@@ -43,8 +43,15 @@ class GPBUtil
if ($isNeg) { if ($isNeg) {
$value = bcsub(0, $value); $value = bcsub(0, $value);
} }
$high = (int) bcdiv(bcadd($value, 1), 4294967296); $high = (int) bcdiv(bcadd($value, 1), 4294967296);
$low = (int) bcmod($value, 4294967296); $low = bcmod($value, 4294967296);
if (bccomp($low, 2147483647) > 0) {
$low = (int) bcsub($low, 4294967296);
} else {
$low = (int) $low;
}
if ($isNeg) { if ($isNeg) {
$high = ~$high; $high = ~$high;
$low = ~$low; $low = ~$low;
......
...@@ -437,6 +437,36 @@ class GPBWire ...@@ -437,6 +437,36 @@ class GPBWire
public static function varint64Size($value) public static function varint64Size($value)
{ {
if (PHP_INT_SIZE == 4) {
if (bccomp($value, 0) < 0) {
return 10;
}
if (bccomp($value, 1 << 7) < 0) {
return 1;
}
if (bccomp($value, 1 << 14) < 0) {
return 2;
}
if (bccomp($value, 1 << 21) < 0) {
return 3;
}
if (bccomp($value, 1 << 28) < 0) {
return 4;
}
if (bccomp($value, '34359738368') < 0) {
return 5;
}
if (bccomp($value, '4398046511104') < 0) {
return 6;
}
if (bccomp($value, '562949953421312') < 0) {
return 7;
}
if (bccomp($value, '72057594037927936') < 0) {
return 8;
}
return 9;
} else {
if ($value < 0) { if ($value < 0) {
return 10; return 10;
} }
...@@ -466,6 +496,7 @@ class GPBWire ...@@ -466,6 +496,7 @@ class GPBWire
} }
return 9; return 9;
} }
}
public static function serializeFieldToStream( public static function serializeFieldToStream(
$value, $value,
......
...@@ -46,6 +46,9 @@ function combineInt32ToInt64($high, $low) ...@@ -46,6 +46,9 @@ function combineInt32ToInt64($high, $low)
} }
} }
$result = bcadd(bcmul($high, 4294967296), $low); $result = bcadd(bcmul($high, 4294967296), $low);
if ($low < 0) {
$result = bcadd($result, 4294967296);
}
if ($isNeg) { if ($isNeg) {
$result = bcsub(0, $result); $result = bcsub(0, $result);
} }
...@@ -179,9 +182,9 @@ class InputStream ...@@ -179,9 +182,9 @@ class InputStream
if ($bits >= 32) { if ($bits >= 32) {
$high |= (($b & 0x7F) << ($bits - 32)); $high |= (($b & 0x7F) << ($bits - 32));
} else if ($bits > 25){ } else if ($bits > 25){
$high_bits = $bits - 25; // $bits is 28 in this case.
$low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF; $low |= (($b & 0x7F) << 28);
$high = $b & ((0x1 << $high_bits) -1); $high = ($b & 0x7F) >> 4;
} else { } else {
$low |= (($b & 0x7F) << $bits); $low |= (($b & 0x7F) << $bits);
} }
......
...@@ -175,17 +175,22 @@ class Message ...@@ -175,17 +175,22 @@ class Message
case GPBType::FLOAT: case GPBType::FLOAT:
return 0.0; return 0.0;
case GPBType::UINT32: case GPBType::UINT32:
case GPBType::UINT64:
case GPBType::INT32: case GPBType::INT32:
case GPBType::INT64:
case GPBType::FIXED32: case GPBType::FIXED32:
case GPBType::FIXED64:
case GPBType::SFIXED32: case GPBType::SFIXED32:
case GPBType::SFIXED64:
case GPBType::SINT32: case GPBType::SINT32:
case GPBType::SINT64:
case GPBType::ENUM: case GPBType::ENUM:
return 0; return 0;
case GPBType::INT64:
case GPBType::UINT64:
case GPBType::FIXED64:
case GPBType::SFIXED64:
case GPBType::SINT64:
if (PHP_INT_SIZE === 4) {
return '0';
} else {
return 0;
}
case GPBType::BOOL: case GPBType::BOOL:
return false; return false;
case GPBType::STRING: case GPBType::STRING:
......
...@@ -132,4 +132,39 @@ class EncodeDecodeTest extends TestBase ...@@ -132,4 +132,39 @@ class EncodeDecodeTest extends TestBase
$to->decode(TestUtil::getGoldenTestUnpackedMessage()); $to->decode(TestUtil::getGoldenTestUnpackedMessage());
TestUtil::assertTestPackedMessage($to); TestUtil::assertTestPackedMessage($to);
} }
public function testDecodeInt64()
{
// Read 64 testing
$testVals = array(
'10' => '100a',
'100' => '1064',
'800' => '10a006',
'6400' => '108032',
'70400' => '1080a604',
'774400' => '1080a22f',
'9292800' => '108098b704',
'74342400' => '1080c0b923',
'743424000' => '108080bfe202',
'8177664000' => '108080b5bb1e',
'65421312000' => '108080a8dbf301',
'785055744000' => '108080e0c7ec16',
'9420668928000' => '10808080dd969202',
'103627358208000' => '10808080fff9c717',
'1139900940288000' => '10808080f5bd978302',
'13678811283456000' => '10808080fce699a618',
'109430490267648000' => '10808080e0b7ceb1c201',
'984874412408832000' => '10808080e0f5c1bed50d',
);
$msg = new TestMessage();
foreach ($testVals as $original => $encoded) {
$msg->setOptionalInt64($original);
$data = $msg->encode();
$this->assertSame($encoded, bin2hex($data));
$msg->setOptionalInt64(0);
$msg->decode($data);
$this->assertEquals($original, $msg->getOptionalInt64());
}
}
} }
...@@ -368,7 +368,6 @@ class ImplementationTest extends TestBase ...@@ -368,7 +368,6 @@ class ImplementationTest extends TestBase
$this->assertFalse($input->readVarint64($var)); $this->assertFalse($input->readVarint64($var));
// Read 64 testing // Read 64 testing
if (PHP_INT_SIZE > 4) {
$testVals = array( $testVals = array(
'10' => '0a000000000000000000', '10' => '0a000000000000000000',
'100' => '64000000000000000000', '100' => '64000000000000000000',
...@@ -393,8 +392,7 @@ class ImplementationTest extends TestBase ...@@ -393,8 +392,7 @@ class ImplementationTest extends TestBase
foreach ($testVals as $original => $encoded) { foreach ($testVals as $original => $encoded) {
$input = new InputStream(hex2bin($encoded)); $input = new InputStream(hex2bin($encoded));
$this->assertTrue($input->readVarint64($var)); $this->assertTrue($input->readVarint64($var));
$this->assertSame($original, $var); $this->assertEquals($original, $var);
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment