Implement __vector_as_bytes and methods to get [ubyte] efficiently
authorArmen Baghumian <armen@vardump.org>
Mon, 14 Mar 2016 06:37:22 +0000 (17:37 +1100)
committerArmen Baghumian <abaghumian@noggin.com.au>
Tue, 29 Mar 2016 03:56:09 +0000 (14:56 +1100)
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
src/idl_gen_php.cpp
tests/MyGame/Example/Monster.php
tests/phpTest.php

index 7f61145..6f917c1 100644 (file)
@@ -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
index 2488b1d..5b904a0 100644 (file)
@@ -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);
+        }
       }
     }
 
index 6c1d34a..48b9c7d 100644 (file)
@@ -99,6 +99,14 @@ class Monster extends Table
     }
 
     /**
+     * @return string
+     */
+    public function getInventoryBytes()
+    {
+        return $this->__vector_as_bytes(14);
+    }
+
+    /**
      * @return sbyte
      */
     public function getColor()
@@ -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();
index 0afc0af..4dc83b2 100644 (file)
@@ -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);