From 28a3c939e7f2083b79254ff90cfde77e51908bc8 Mon Sep 17 00:00:00 2001 From: Armen Baghumian Date: Mon, 14 Mar 2016 17:37:22 +1100 Subject: [PATCH] Implement __vector_as_bytes and methods to get [ubyte] efficiently Currently in order to get a value type of [ubyte] in PHP, iteration is necessary which is not efficient. Helper __vector_as_bytes has been implemented in order to return the byte arrays in PHP efficiently. Appropriate methods also been added to use aforementioned method to return the byte array. (e.g. get*Bytes()). The reason the methods are named get*Bytes() and not for instance get*ByteArray() is the fact that PHP doesn't support byte arrays and the binary safe string implementation in PHP is used to simulate byte arrays and since there is chance for PHP users to confuse this with PHP arrays the name get*Bytes() has been chosen. In the future __vector_as_bytebuffer() method can also be implemented to return PHP implementation of ByteBuffer. --- php/Table.php | 12 +++++++++--- src/idl_gen_php.cpp | 21 ++++++++++++++++++++- tests/MyGame/Example/Monster.php | 16 ++++++++++++++++ tests/phpTest.php | 1 + 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/php/Table.php b/php/Table.php index 7f6114560..6f917c1af 100644 --- a/php/Table.php +++ b/php/Table.php @@ -89,9 +89,15 @@ abstract class Table return $offset + $this->bb->getInt($offset) + Constants::SIZEOF_INT; } -// protected function __vector_as_bytebuffer($vector_offset, $elem_size) -// { -// } + protected function __vector_as_bytes($vector_offset, $elem_size=1) + { + $o = $this->__offset($vector_offset); + if ($o == 0) { + return null; + } + + return substr($this->bb->_buffer, $this->__vector($o), $this->__vector_len($o) * $elem_size); + } /** * @param Table $table diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 2488b1d18..5b904a077 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -165,6 +165,22 @@ namespace php { code += Indent + "}\n\n"; } + // Get a [ubyte] vector as a byte array. + static void GetUByte(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + + code += Indent + "/**\n"; + code += Indent + " * @return string\n"; + code += Indent + " */\n"; + code += Indent + "public function get"; + code += MakeCamel(field.name) + "Bytes()\n"; + code += Indent + "{\n"; + code += Indent + Indent + "return $this->__vector_as_bytes("; + code += NumToString(field.value.offset) + ");\n"; + code += Indent + "}\n\n"; + } + // Get the value of a struct's scalar. static void GetScalarFieldOfStruct(const FieldDef &field, std::string *code_ptr) { @@ -250,7 +266,7 @@ namespace php { ");\n"; code += Indent + Indent; code += "return $o != 0 ? $obj->init("; - if (field.value.type.struct_def->fixed) + if (field.value.type.struct_def->fixed) { code += "$o + $this->bb_pos, $this->bb) : "; } else { @@ -690,6 +706,9 @@ namespace php { } if (field.value.type.base_type == BASE_TYPE_VECTOR) { GetVectorLen(field, code_ptr); + if (field.value.type.element == BASE_TYPE_UCHAR) { + GetUByte(field, code_ptr); + } } } diff --git a/tests/MyGame/Example/Monster.php b/tests/MyGame/Example/Monster.php index 6c1d34a0b..48b9c7df2 100644 --- a/tests/MyGame/Example/Monster.php +++ b/tests/MyGame/Example/Monster.php @@ -98,6 +98,14 @@ class Monster extends Table return $o != 0 ? $this->__vector_len($o) : 0; } + /** + * @return string + */ + public function getInventoryBytes() + { + return $this->__vector_as_bytes(14); + } + /** * @return sbyte */ @@ -210,6 +218,14 @@ class Monster extends Table return $o != 0 ? $this->__vector_len($o) : 0; } + /** + * @return string + */ + public function getTestnestedflatbufferBytes() + { + return $this->__vector_as_bytes(30); + } + public function getTestempty() { $obj = new Stat(); diff --git a/tests/phpTest.php b/tests/phpTest.php index 0afc0af7f..4dc83b28d 100644 --- a/tests/phpTest.php +++ b/tests/phpTest.php @@ -128,6 +128,7 @@ function test_buffer(Assert $assert, Google\FlatBuffers\ByteBuffer $bb) { } $assert->strictEqual($invsum, 10); + $assert->strictEqual(bin2hex($monster->GetInventoryBytes()), "0001020304"); $test_0 = $monster->GetTest4(0); $test_1 = $monster->GetTest4(1);