aboutsummaryrefslogtreecommitdiff
path: root/php/src/Google/Protobuf/Internal
diff options
context:
space:
mode:
Diffstat (limited to 'php/src/Google/Protobuf/Internal')
-rw-r--r--php/src/Google/Protobuf/Internal/DescriptorPool.php2
-rw-r--r--php/src/Google/Protobuf/Internal/GPBUtil.php9
-rw-r--r--php/src/Google/Protobuf/Internal/GPBWire.php85
-rw-r--r--php/src/Google/Protobuf/Internal/InputStream.php9
-rw-r--r--php/src/Google/Protobuf/Internal/Message.php218
5 files changed, 282 insertions, 41 deletions
diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php
index 23b304ac..1ef403cf 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorPool.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php
@@ -58,7 +58,7 @@ class DescriptorPool
public function internalAddGeneratedFile($data)
{
$files = new FileDescriptorSet();
- $files->decode($data);
+ $files->mergeFromString($data);
$file = FileDescriptor::buildFromProto($files->getFile()[0]);
foreach ($file->getMessageType() as &$desc) {
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index 30d7350f..ba1d2eb3 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -43,8 +43,15 @@ class GPBUtil
if ($isNeg) {
$value = bcsub(0, $value);
}
+
$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) {
$high = ~$high;
$low = ~$low;
diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php
index 7e2c124f..f75e0861 100644
--- a/php/src/Google/Protobuf/Internal/GPBWire.php
+++ b/php/src/Google/Protobuf/Internal/GPBWire.php
@@ -437,34 +437,65 @@ class GPBWire
public static function varint64Size($value)
{
- if ($value < 0) {
- return 10;
- }
- if ($value < (1 << 7)) {
- return 1;
- }
- if ($value < (1 << 14)) {
- return 2;
- }
- if ($value < (1 << 21)) {
- return 3;
- }
- if ($value < (1 << 28)) {
- return 4;
- }
- if ($value < (1 << 35)) {
- return 5;
- }
- if ($value < (1 << 42)) {
- return 6;
- }
- if ($value < (1 << 49)) {
- return 7;
- }
- if ($value < (1 << 56)) {
- return 8;
+ 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) {
+ return 10;
+ }
+ if ($value < (1 << 7)) {
+ return 1;
+ }
+ if ($value < (1 << 14)) {
+ return 2;
+ }
+ if ($value < (1 << 21)) {
+ return 3;
+ }
+ if ($value < (1 << 28)) {
+ return 4;
+ }
+ if ($value < (1 << 35)) {
+ return 5;
+ }
+ if ($value < (1 << 42)) {
+ return 6;
+ }
+ if ($value < (1 << 49)) {
+ return 7;
+ }
+ if ($value < (1 << 56)) {
+ return 8;
+ }
+ return 9;
}
- return 9;
}
public static function serializeFieldToStream(
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/InputStream.php
index c5a76d5d..bf052c2f 100644
--- a/php/src/Google/Protobuf/Internal/InputStream.php
+++ b/php/src/Google/Protobuf/Internal/InputStream.php
@@ -46,6 +46,9 @@ function combineInt32ToInt64($high, $low)
}
}
$result = bcadd(bcmul($high, 4294967296), $low);
+ if ($low < 0) {
+ $result = bcadd($result, 4294967296);
+ }
if ($isNeg) {
$result = bcsub(0, $result);
}
@@ -179,9 +182,9 @@ class InputStream
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);
+ // $bits is 28 in this case.
+ $low |= (($b & 0x7F) << 28);
+ $high = ($b & 0x7F) >> 4;
} else {
$low |= (($b & 0x7F) << $bits);
}
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 3d1f1598..ca4fde02 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -125,7 +125,7 @@ class Message
$oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
$oneof_name = $oneof->getName();
$this->$oneof_name = new OneofField($oneof);
- } else if ($field->getLabel() === GPBLabel::OPTIONAL &&
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL &&
PHP_INT_SIZE == 4) {
switch ($field->getType()) {
case GPBType::INT64:
@@ -163,6 +163,17 @@ class Message
$oneof_field->setNumber($number);
}
+ protected function whichOneof($oneof_name)
+ {
+ $oneof_field = $this->$oneof_name;
+ $number = $oneof_field->getNumber();
+ if ($number == 0) {
+ return "";
+ }
+ $field = $this->desc->getFieldByNumber($number);
+ return $field->getName();
+ }
+
/**
* @ignore
*/
@@ -175,17 +186,22 @@ class Message
case GPBType::FLOAT:
return 0.0;
case GPBType::UINT32:
- case GPBType::UINT64:
case GPBType::INT32:
- case GPBType::INT64:
case GPBType::FIXED32:
- case GPBType::FIXED64:
case GPBType::SFIXED32:
- case GPBType::SFIXED64:
case GPBType::SINT32:
- case GPBType::SINT64:
case GPBType::ENUM:
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:
return false;
case GPBType::STRING:
@@ -366,15 +382,194 @@ class Message
}
/**
+ * Clear all containing fields.
+ * @return null.
+ */
+ public function clear()
+ {
+ foreach ($this->desc->getField() as $field) {
+ $setter = $field->getSetter();
+ if ($field->isMap()) {
+ $message_type = $field->getMessageType();
+ $key_field = $message_type->getFieldByNumber(1);
+ $value_field = $message_type->getFieldByNumber(2);
+ switch ($value_field->getType()) {
+ case GPBType::MESSAGE:
+ case GPBType::GROUP:
+ $map_field = new MapField(
+ $key_field->getType(),
+ $value_field->getType(),
+ $value_field->getMessageType()->getClass());
+ $this->$setter($map_field);
+ break;
+ case GPBType::ENUM:
+ $map_field = new MapField(
+ $key_field->getType(),
+ $value_field->getType(),
+ $value_field->getEnumType()->getClass());
+ $this->$setter($map_field);
+ break;
+ default:
+ $map_field = new MapField(
+ $key_field->getType(),
+ $value_field->getType());
+ $this->$setter($map_field);
+ break;
+ }
+ } else if ($field->getLabel() === GPBLabel::REPEATED) {
+ switch ($field->getType()) {
+ case GPBType::MESSAGE:
+ case GPBType::GROUP:
+ $repeated_field = new RepeatedField(
+ $field->getType(),
+ $field->getMessageType()->getClass());
+ $this->$setter($repeated_field);
+ break;
+ case GPBType::ENUM:
+ $repeated_field = new RepeatedField(
+ $field->getType(),
+ $field->getEnumType()->getClass());
+ $this->$setter($repeated_field);
+ break;
+ default:
+ $repeated_field = new RepeatedField($field->getType());
+ $this->$setter($repeated_field);
+ break;
+ }
+ } else if ($field->getOneofIndex() !== -1) {
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+ $oneof_name = $oneof->getName();
+ $this->$oneof_name = new OneofField($oneof);
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
+ switch ($field->getType()) {
+ case GPBType::DOUBLE :
+ case GPBType::FLOAT :
+ $this->$setter(0.0);
+ break;
+ case GPBType::INT32 :
+ case GPBType::FIXED32 :
+ case GPBType::UINT32 :
+ case GPBType::SFIXED32 :
+ case GPBType::SINT32 :
+ case GPBType::ENUM :
+ $this->$setter(0);
+ break;
+ case GPBType::BOOL :
+ $this->$setter(false);
+ break;
+ case GPBType::STRING :
+ case GPBType::BYTES :
+ $this->$setter("");
+ break;
+ case GPBType::GROUP :
+ case GPBType::MESSAGE :
+ $null = null;
+ $this->$setter($null);
+ break;
+ }
+ if (PHP_INT_SIZE == 4) {
+ switch ($field->getType()) {
+ case GPBType::INT64:
+ case GPBType::UINT64:
+ case GPBType::FIXED64:
+ case GPBType::SFIXED64:
+ case GPBType::SINT64:
+ $this->$setter("0");
+ }
+ } else {
+ switch ($field->getType()) {
+ case GPBType::INT64:
+ case GPBType::UINT64:
+ case GPBType::FIXED64:
+ case GPBType::SFIXED64:
+ case GPBType::SINT64:
+ $this->$setter(0);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Merges the contents of the specified message into current message.
+ *
+ * This method merges the contents of the specified message into the
+ * current message. Singular fields that are set in the specified message
+ * overwrite the corresponding fields in the current message. Repeated
+ * fields are appended. Map fields key-value pairs are overritten.
+ * Singular/Oneof sub-messages are recursively merged. All overritten
+ * sub-messages are deep-copied.
+ *
+ * @param object $msg Protobuf message to be merged from.
+ * @return null.
+ */
+ public function mergeFrom($msg)
+ {
+ if (get_class($this) !== get_class($msg)) {
+ user_error("Cannot merge messages with different class.");
+ return;
+ }
+
+ foreach ($this->desc->getField() as $field) {
+ $setter = $field->getSetter();
+ $getter = $field->getGetter();
+ if ($field->isMap()) {
+ if (count($msg->$getter()) != 0) {
+ $value_field = $field->getMessageType()->getFieldByNumber(2);
+ foreach ($msg->$getter() as $key => $value) {
+ if ($value_field->getType() == GPBType::MESSAGE) {
+ $klass = $value_field->getMessageType()->getClass();
+ $copy = new $klass;
+ $copy->mergeFrom($value);
+ $this->$getter()[$key] = $copy;
+ } else {
+ $this->$getter()[$key] = $value;
+ }
+ }
+ }
+ } else if ($field->getLabel() === GPBLabel::REPEATED) {
+ if (count($msg->$getter()) != 0) {
+ foreach ($msg->$getter() as $tmp) {
+ if ($field->getType() == GPBType::MESSAGE) {
+ $klass = $field->getMessageType()->getClass();
+ $copy = new $klass;
+ $copy->mergeFrom($tmp);
+ $this->$getter()[] = $copy;
+ } else {
+ $this->$getter()[] = $tmp;
+ }
+ }
+ }
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
+ if($msg->$getter() !== $this->defaultValue($field)) {
+ $tmp = $msg->$getter();
+ if ($field->getType() == GPBType::MESSAGE) {
+ if (is_null($this->$getter())) {
+ $klass = $field->getMessageType()->getClass();
+ $new_msg = new $klass;
+ $this->$setter($new_msg);
+ }
+ $this->$getter()->mergeFrom($tmp);
+ } else {
+ $this->$setter($tmp);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Parses a protocol buffer contained in a string.
*
* This function takes a string in the (non-human-readable) binary wire
- * format, matching the encoding output by encode().
+ * format, matching the encoding output by serializeToString().
+ * See mergeFrom() for merging behavior, if the field is already set in the
+ * specified message.
*
* @param string $data Binary protobuf data.
* @return bool Return true on success.
*/
- public function decode($data)
+ public function mergeFromString($data)
{
$input = new InputStream($data);
$this->parseFromStream($input);
@@ -395,6 +590,11 @@ class Message
$number = GPBWire::getTagFieldNumber($tag);
$field = $this->desc->getFieldByNumber($number);
+ // Check whether we retrieved a known field
+ if ($field === NULL) {
+ continue;
+ }
+
if (!$this->parseFieldFromStream($tag, $input, $field)) {
return false;
}
@@ -516,7 +716,7 @@ class Message
* Serialize the message to string.
* @return string Serialized binary protobuf data.
*/
- public function encode()
+ public function serializeToString()
{
$output = new OutputStream($this->byteSize());
$this->serializeToStream($output);