[Lua] manipulate byte array as string (#6624)
author罗泽轩 <spacewanderlzx@gmail.com>
Sat, 8 May 2021 05:57:13 +0000 (13:57 +0800)
committerGitHub <noreply@github.com>
Sat, 8 May 2021 05:57:13 +0000 (22:57 -0700)
* [Lua] manipulate byte array as string

Sometimes it would be more effective than reading byte by byte

* change according to the review

* update

lua/flatbuffers/view.lua
src/idl_gen_lua.cpp
tests/MyGame/Example/Monster.lua
tests/MyGame/Example/TypeAliases.lua
tests/luatest.lua

index 105e967..433f25c 100644 (file)
@@ -76,6 +76,17 @@ function mt:Vector(off)
     return off + self:Get(N.UOffsetT, off) + 4
 end
 
+function mt:VectorAsString(off, start, stop)
+    local o = self:Offset(off)
+    if o ~= 0 then
+        start = start or 1
+        stop = stop or self:VectorLen(o)
+        local a = self:Vector(o) + start - 1
+        return self.bytes:Slice(a, a + stop - start + 1)
+    end
+    return nil
+end
+
 function mt:Union(t2, off)
     assert(getmetatable(t2) == mt_name)
     enforceOffset(off)
index e7e7834..9efc435 100644 (file)
@@ -339,6 +339,18 @@ class LuaGenerator : public BaseGenerator {
     code += EndFunc;
   }
 
+  // Access a byte/ubyte vector as a string
+  void AccessByteVectorAsString(const StructDef &struct_def,
+                                const FieldDef &field, std::string *code_ptr) {
+    std::string &code = *code_ptr;
+    GenReceiver(struct_def, code_ptr);
+    code += MakeCamel(NormalizedName(field));
+    code += "AsString(start, stop)\n";
+    code += std::string(Indent) + "return " + SelfData + ":VectorAsString(" +
+            NumToString(field.value.offset) + ", start, stop)\n";
+    code += EndFunc;
+  }
+
   // Begin the creator function signature.
   void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
     std::string &code = *code_ptr;
@@ -499,6 +511,10 @@ class LuaGenerator : public BaseGenerator {
             GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
           } else {
             GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+            if (vectortype.base_type == BASE_TYPE_CHAR ||
+                vectortype.base_type == BASE_TYPE_UCHAR) {
+              AccessByteVectorAsString(struct_def, field, code_ptr);
+            }
           }
           break;
         }
index fbd2c74..26b59d3 100644 (file)
@@ -62,6 +62,9 @@ function Monster_mt:Inventory(j)
     end
     return 0
 end
+function Monster_mt:InventoryAsString(start, stop)
+    return self.view:VectorAsString(14, start, stop)
+end
 function Monster_mt:InventoryLength()
     local o = self.view:Offset(14)
     if o ~= 0 then
@@ -160,6 +163,9 @@ function Monster_mt:Testnestedflatbuffer(j)
     end
     return 0
 end
+function Monster_mt:TestnestedflatbufferAsString(start, stop)
+    return self.view:VectorAsString(30, start, stop)
+end
 function Monster_mt:TestnestedflatbufferLength()
     local o = self.view:Offset(30)
     if o ~= 0 then
@@ -315,6 +321,9 @@ function Monster_mt:Flex(j)
     end
     return 0
 end
+function Monster_mt:FlexAsString(start, stop)
+    return self.view:VectorAsString(64, start, stop)
+end
 function Monster_mt:FlexLength()
     local o = self.view:Offset(64)
     if o ~= 0 then
@@ -518,6 +527,9 @@ function Monster_mt:VectorOfEnums(j)
     end
     return 0
 end
+function Monster_mt:VectorOfEnumsAsString(start, stop)
+    return self.view:VectorAsString(98, start, stop)
+end
 function Monster_mt:VectorOfEnumsLength()
     local o = self.view:Offset(98)
     if o ~= 0 then
@@ -540,6 +552,9 @@ function Monster_mt:Testrequirednestedflatbuffer(j)
     end
     return 0
 end
+function Monster_mt:TestrequirednestedflatbufferAsString(start, stop)
+    return self.view:VectorAsString(102, start, stop)
+end
 function Monster_mt:TestrequirednestedflatbufferLength()
     local o = self.view:Offset(102)
     if o ~= 0 then
index 91c62c4..e9c680b 100644 (file)
@@ -102,6 +102,9 @@ function TypeAliases_mt:V8(j)
     end
     return 0
 end
+function TypeAliases_mt:V8AsString(start, stop)
+    return self.view:VectorAsString(24, start, stop)
+end
 function TypeAliases_mt:V8Length()
     local o = self.view:Offset(24)
     if o ~= 0 then
index 26b0a98..1a70f5f 100644 (file)
@@ -282,6 +282,41 @@ local function getRootAs_canAcceptString()
     assert(mon:Hp() == 80, "Monster Hp is not 80")
 end
     
+local function testAccessByteVectorAsString()
+    local f = assert(io.open('monsterdata_test.mon', 'rb'))
+    local wireData = f:read("*a")
+    f:close()
+    local mon = monster.GetRootAsMonster(wireData, 0)
+    -- the data of byte array Inventory is [0, 1, 2, 3, 4]
+    local s = mon:InventoryAsString(1, 3)
+    assert(#s == 3)
+    for i = 1, #s do
+        assert(string.byte(s, i) == i - 1)
+    end
+
+    local s = mon:InventoryAsString(2, 5)
+    assert(#s == 4)
+    for i = 1, #s do
+        assert(string.byte(s, i) == i)
+    end
+
+    local s = mon:InventoryAsString(5, 5)
+    assert(#s == 1)
+    assert(string.byte(s, 1) == 4)
+
+    local s = mon:InventoryAsString(2)
+    assert(#s == 4)
+    for i = 1, #s do
+        assert(string.byte(s, i) == i)
+    end
+
+    local s = mon:InventoryAsString()
+    assert(#s == 5)
+    for i = 1, #s do
+        assert(string.byte(s, i) == i - 1)
+    end
+end
+
 local tests = 
 { 
     {   
@@ -305,6 +340,10 @@ local tests =
         f = getRootAs_canAcceptString,
         d = "Tests that GetRootAs<type>() generated methods accept strings"
     },
+    {
+        f = testAccessByteVectorAsString,
+        d = "Access byte vector as string"
+    },
 }
 
 local benchmarks =