Fix incorrect padding in arrays of structs (Issue #5484) (#5491)
authorsvenk177 <50141814+svenk177@users.noreply.github.com>
Fri, 23 Aug 2019 17:46:47 +0000 (19:46 +0200)
committerWouter van Oortmerssen <aardappel@gmail.com>
Fri, 23 Aug 2019 17:46:47 +0000 (10:46 -0700)
16 files changed:
include/flatbuffers/idl.h
tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
tests/JavaTest.java
tests/MyGame/Example/ArrayStruct.cs
tests/MyGame/Example/ArrayStruct.java
tests/MyGame/Example/ArrayStruct.py
tests/MyGame/Example/NestedStruct.cs
tests/MyGame/Example/NestedStruct.java
tests/MyGame/Example/NestedStruct.py
tests/arrays_test.bfbs
tests/arrays_test.fbs
tests/arrays_test.golden
tests/arrays_test.schema.json
tests/arrays_test_generated.h
tests/py_test.py
tests/test.cpp

index fe68b0d..c3cec06 100644 (file)
@@ -367,9 +367,14 @@ inline size_t InlineSize(const Type &type) {
 }
 
 inline size_t InlineAlignment(const Type &type) {
-  return IsStruct(type)
-             ? type.struct_def->minalign
-             : (SizeOf(IsArray(type) ? type.element : type.base_type));
+  if (IsStruct(type)) {
+    return type.struct_def->minalign;
+  } else if (IsArray(type)) {
+    return IsStruct(type.VectorType()) ? type.struct_def->minalign
+                                       : SizeOf(type.element);
+  } else {
+    return SizeOf(type.base_type);
+  }
 }
 
 struct EnumDef;
index b09119c..8e9fd3d 100644 (file)
@@ -342,6 +342,9 @@ namespace FlatBuffers.Test
             int[,]  d_a = new int[2, 2];
             TestEnum[]  d_b = new TestEnum[2];
             TestEnum[,] d_c = new TestEnum[2, 2];
+            long[,]     d_d = new long[2, 2];
+            int         e;
+            long[]      f = new long[2];
 
             a = 0.5f;
             for (int i = 0; i < 15; i++) b[i] = i;
@@ -356,9 +359,16 @@ namespace FlatBuffers.Test
             d_c[0, 1] = TestEnum.B;
             d_c[1, 0] = TestEnum.C;
             d_c[1, 1] = TestEnum.B;
+            d_d[0, 0] = -1;
+            d_d[0, 1] = 1;
+            d_d[1, 0] = -2;
+            d_d[1, 1] = 2;
+            e = 2;
+            f[0] = -1;
+            f[1] = 1;
 
             Offset<ArrayStruct> arrayOffset = ArrayStruct.CreateArrayStruct(
-                builder, a, b, c, d_a, d_b, d_c);
+                builder, a, b, c, d_a, d_b, d_c, d_d, e, f);
 
             // Create a table with the ArrayStruct.
             ArrayTable.StartArrayTable(builder);
@@ -382,6 +392,13 @@ namespace FlatBuffers.Test
             Assert.AreEqual(table.A?.D(0).C(1), TestEnum.B);
             Assert.AreEqual(table.A?.D(1).C(0), TestEnum.C);
             Assert.AreEqual(table.A?.D(1).C(1), TestEnum.B);
+            Assert.AreEqual(table.A?.D(0).D(0), -1);
+            Assert.AreEqual(table.A?.D(0).D(1), 1);
+            Assert.AreEqual(table.A?.D(1).D(0), -2);
+            Assert.AreEqual(table.A?.D(1).D(1), 2);
+            Assert.AreEqual(table.A?.E, 2);
+            Assert.AreEqual(table.A?.F(0), -1);
+            Assert.AreEqual(table.A?.F(1), 1);
         }
     }
 }
index 6505767..f31e654 100644 (file)
@@ -463,6 +463,9 @@ class JavaTest {
         int[][]     d_a = new int[2][2];
         byte[]      d_b = new byte[2];
         byte[][]    d_c = new byte[2][2];
+        long[][]    d_d = new long[2][2];
+        int         e;
+        long[]      f = new long[2];
 
         a = 0.5f;
         for (int i = 0; i < 15; i++) b[i] = i;
@@ -477,9 +480,16 @@ class JavaTest {
         d_c[0][1] = TestEnum.B;
         d_c[1][0] = TestEnum.C;
         d_c[1][1] = TestEnum.B;
+        d_d[0][0] = -1;
+        d_d[0][1] = 1;
+        d_d[1][0] = -2;
+        d_d[1][1] = 2;
+        e = 2;
+        f[0] = -1;
+        f[1] = 1;
 
         int arrayOffset = ArrayStruct.createArrayStruct(builder,
-            a, b, c, d_a, d_b, d_c);
+            a, b, c, d_a, d_b, d_c, d_d, e, f);
 
         // Create a table with the ArrayStruct.
         ArrayTable.startArrayTable(builder);
@@ -504,6 +514,13 @@ class JavaTest {
         TestEq(table.a().d(nested, 0).c(1), TestEnum.B);
         TestEq(table.a().d(nested, 1).c(0), TestEnum.C);
         TestEq(table.a().d(nested, 1).c(1), TestEnum.B);
+        TestEq(table.a().d(nested, 0).d(0), (long)-1);
+        TestEq(table.a().d(nested, 0).d(1), (long)1);
+        TestEq(table.a().d(nested, 1).d(0), (long)-2);
+        TestEq(table.a().d(nested, 1).d(1), (long)2);
+        TestEq(table.a().e(), 2);
+        TestEq(table.a().f(0), (long)-1);
+        TestEq(table.a().f(1), (long)1);
     }
 
     static <T> void TestEq(T a, T b) {
index 28815e7..bdcbb3f 100644 (file)
@@ -21,13 +21,25 @@ public struct ArrayStruct : IFlatbufferObject
   public void MutateB(int j, int b) { __p.bb.PutInt(__p.bb_pos + 4 + j * 4, b); }
   public sbyte C { get { return __p.bb.GetSbyte(__p.bb_pos + 64); } }
   public void MutateC(sbyte c) { __p.bb.PutSbyte(__p.bb_pos + 64, c); }
-  public MyGame.Example.NestedStruct D(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 68 + j * 12, __p.bb); }
+  public MyGame.Example.NestedStruct D(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 72 + j * 32, __p.bb); }
+  public int E { get { return __p.bb.GetInt(__p.bb_pos + 136); } }
+  public void MutateE(int e) { __p.bb.PutInt(__p.bb_pos + 136, e); }
+  public long F(int j) { return __p.bb.GetLong(__p.bb_pos + 144 + j * 8); }
+  public void MutateF(int j, long f) { __p.bb.PutLong(__p.bb_pos + 144 + j * 8, f); }
 
-  public static Offset<MyGame.Example.ArrayStruct> CreateArrayStruct(FlatBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C) {
-    builder.Prep(4, 92);
+  public static Offset<MyGame.Example.ArrayStruct> CreateArrayStruct(FlatBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C, long[,] d_D, int E, long[] F) {
+    builder.Prep(8, 160);
     for (int _idx0 = 2; _idx0 > 0; _idx0--) {
-      builder.Prep(4, 12);
-      builder.Pad(1);
+      builder.PutLong(F[_idx0-1]);
+    }
+    builder.Pad(4);
+    builder.PutInt(E);
+    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
+      builder.Prep(8, 32);
+      for (int _idx1 = 2; _idx1 > 0; _idx1--) {
+        builder.PutLong(d_D[_idx0-1,_idx1-1]);
+      }
+      builder.Pad(5);
       for (int _idx1 = 2; _idx1 > 0; _idx1--) {
         builder.PutSbyte((sbyte)d_C[_idx0-1,_idx1-1]);
       }
@@ -36,7 +48,7 @@ public struct ArrayStruct : IFlatbufferObject
         builder.PutInt(d_A[_idx0-1,_idx1-1]);
       }
     }
-    builder.Pad(3);
+    builder.Pad(7);
     builder.PutSbyte(C);
     for (int _idx0 = 15; _idx0 > 0; _idx0--) {
       builder.PutInt(B[_idx0-1]);
index 0098c55..7cfe9bb 100644 (file)
@@ -18,13 +18,25 @@ public final class ArrayStruct extends Struct {
   public void mutateB(int j, int b) { bb.putInt(bb_pos + 4 + j * 4, b); }
   public byte c() { return bb.get(bb_pos + 64); }
   public void mutateC(byte c) { bb.put(bb_pos + 64, c); }
-  public MyGame.Example.NestedStruct d(MyGame.Example.NestedStruct obj, int j) { return obj.__assign(bb_pos + 68 + j * 12, bb); }
+  public MyGame.Example.NestedStruct d(MyGame.Example.NestedStruct obj, int j) { return obj.__assign(bb_pos + 72 + j * 32, bb); }
+  public int e() { return bb.getInt(bb_pos + 136); }
+  public void mutateE(int e) { bb.putInt(bb_pos + 136, e); }
+  public long f(int j) { return bb.getLong(bb_pos + 144 + j * 8); }
+  public void mutateF(int j, long f) { bb.putLong(bb_pos + 144 + j * 8, f); }
 
-  public static int createArrayStruct(FlatBufferBuilder builder, float a, int[] b, byte c, int[][] d_a, byte[] d_b, byte[][] d_c) {
-    builder.prep(4, 92);
+  public static int createArrayStruct(FlatBufferBuilder builder, float a, int[] b, byte c, int[][] d_a, byte[] d_b, byte[][] d_c, long[][] d_d, int e, long[] f) {
+    builder.prep(8, 160);
     for (int _idx0 = 2; _idx0 > 0; _idx0--) {
-      builder.prep(4, 12);
-      builder.pad(1);
+      builder.putLong(f[_idx0-1]);
+    }
+    builder.pad(4);
+    builder.putInt(e);
+    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
+      builder.prep(8, 32);
+      for (int _idx1 = 2; _idx1 > 0; _idx1--) {
+        builder.putLong(d_d[_idx0-1][_idx1-1]);
+      }
+      builder.pad(5);
       for (int _idx1 = 2; _idx1 > 0; _idx1--) {
         builder.putByte(d_c[_idx0-1][_idx1-1]);
       }
@@ -33,7 +45,7 @@ public final class ArrayStruct extends Struct {
         builder.putInt(d_a[_idx0-1][_idx1-1]);
       }
     }
-    builder.pad(3);
+    builder.pad(7);
     builder.putByte(c);
     for (int _idx0 = 15; _idx0 > 0; _idx0--) {
       builder.putInt(b[_idx0-1]);
index 79dda31..f36ec54 100644 (file)
@@ -19,21 +19,31 @@ class ArrayStruct(object):
     def C(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(64))
     # ArrayStruct
     def D(self, obj, i):
-        obj.Init(self._tab.Bytes, self._tab.Pos + 68 + i * 12)
+        obj.Init(self._tab.Bytes, self._tab.Pos + 72 + i * 32)
         return obj
 
+    # ArrayStruct
+    def E(self): return self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(136))
+    # ArrayStruct
+    def F(self): return [self._tab.Get(flatbuffers.number_types.Int64Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(144 + i * 8)) for i in range(2)]
 
-def CreateArrayStruct(builder, a, b, c, d_a, d_b, d_c):
-    builder.Prep(4, 92)
+def CreateArrayStruct(builder, a, b, c, d_a, d_b, d_c, d_d, e, f):
+    builder.Prep(8, 160)
     for _idx0 in range(2 , 0, -1):
-        builder.Prep(4, 12)
-        builder.Pad(1)
+        builder.PrependInt64(f[_idx0-1])
+    builder.Pad(4)
+    builder.PrependInt32(e)
+    for _idx0 in range(2 , 0, -1):
+        builder.Prep(8, 32)
+        for _idx1 in range(2 , 0, -1):
+            builder.PrependInt64(d_d[_idx0-1][_idx1-1])
+        builder.Pad(5)
         for _idx1 in range(2 , 0, -1):
             builder.PrependInt8(d_c[_idx0-1][_idx1-1])
         builder.PrependInt8(d_b[_idx0-1])
         for _idx1 in range(2 , 0, -1):
             builder.PrependInt32(d_a[_idx0-1][_idx1-1])
-    builder.Pad(3)
+    builder.Pad(7)
     builder.PrependInt8(c)
     for _idx0 in range(15 , 0, -1):
         builder.PrependInt32(b[_idx0-1])
index 3f1f2f0..1e74524 100644 (file)
@@ -21,10 +21,15 @@ public struct NestedStruct : IFlatbufferObject
   public void MutateB(MyGame.Example.TestEnum b) { __p.bb.PutSbyte(__p.bb_pos + 8, (sbyte)b); }
   public MyGame.Example.TestEnum C(int j) { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 9 + j * 1); }
   public void MutateC(int j, MyGame.Example.TestEnum c) { __p.bb.PutSbyte(__p.bb_pos + 9 + j * 1, (sbyte)c); }
+  public long D(int j) { return __p.bb.GetLong(__p.bb_pos + 16 + j * 8); }
+  public void MutateD(int j, long d) { __p.bb.PutLong(__p.bb_pos + 16 + j * 8, d); }
 
-  public static Offset<MyGame.Example.NestedStruct> CreateNestedStruct(FlatBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C) {
-    builder.Prep(4, 12);
-    builder.Pad(1);
+  public static Offset<MyGame.Example.NestedStruct> CreateNestedStruct(FlatBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C, long[] D) {
+    builder.Prep(8, 32);
+    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
+      builder.PutLong(D[_idx0-1]);
+    }
+    builder.Pad(5);
     for (int _idx0 = 2; _idx0 > 0; _idx0--) {
       builder.PutSbyte((sbyte)C[_idx0-1]);
     }
index 3c8a8f6..29534d0 100644 (file)
@@ -18,10 +18,15 @@ public final class NestedStruct extends Struct {
   public void mutateB(byte b) { bb.put(bb_pos + 8, b); }
   public byte c(int j) { return bb.get(bb_pos + 9 + j * 1); }
   public void mutateC(int j, byte c) { bb.put(bb_pos + 9 + j * 1, c); }
+  public long d(int j) { return bb.getLong(bb_pos + 16 + j * 8); }
+  public void mutateD(int j, long d) { bb.putLong(bb_pos + 16 + j * 8, d); }
 
-  public static int createNestedStruct(FlatBufferBuilder builder, int[] a, byte b, byte[] c) {
-    builder.prep(4, 12);
-    builder.pad(1);
+  public static int createNestedStruct(FlatBufferBuilder builder, int[] a, byte b, byte[] c, long[] d) {
+    builder.prep(8, 32);
+    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
+      builder.putLong(d[_idx0-1]);
+    }
+    builder.pad(5);
     for (int _idx0 = 2; _idx0 > 0; _idx0--) {
       builder.putByte(c[_idx0-1]);
     }
index aa742f4..c009973 100644 (file)
@@ -17,10 +17,14 @@ class NestedStruct(object):
     def B(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(8))
     # NestedStruct
     def C(self): return [self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(9 + i * 1)) for i in range(2)]
+    # NestedStruct
+    def D(self): return [self._tab.Get(flatbuffers.number_types.Int64Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(16 + i * 8)) for i in range(2)]
 
-def CreateNestedStruct(builder, a, b, c):
-    builder.Prep(4, 12)
-    builder.Pad(1)
+def CreateNestedStruct(builder, a, b, c, d):
+    builder.Prep(8, 32)
+    for _idx0 in range(2 , 0, -1):
+        builder.PrependInt64(d[_idx0-1])
+    builder.Pad(5)
     for _idx0 in range(2 , 0, -1):
         builder.PrependInt8(c[_idx0-1])
     builder.PrependInt8(b)
index 2a89968..d486072 100644 (file)
Binary files a/tests/arrays_test.bfbs and b/tests/arrays_test.bfbs differ
index 40bce66..90cb0d7 100644 (file)
@@ -6,6 +6,7 @@ struct NestedStruct{
   a:[int:2];
   b:TestEnum;
   c:[TestEnum:2];
+  d:[int64:2];
 }
 
 struct ArrayStruct{
@@ -13,6 +14,8 @@ struct ArrayStruct{
   b:[int:0xF];
   c:byte;
   d:[NestedStruct:2];
+  e:int32;
+  f:[int64:2];
 }
 
 table ArrayTable{
index c032688..c7037d7 100644 (file)
@@ -7,13 +7,17 @@
       {
         a : [-1,2],
         b : A,
-        c : [C, B]
+        c : [C, B],
+        d : [0x1122334455667788, -0x1122334455667788]
       },
       {
         a : [3,-4],
         b : B,
-        c : [B, A]
+        c : [B, A],
+        d : [-0x1122334455667788, 0x1122334455667788]
       }
-    ]
+    ],
+    e: 1,
+    f: [-0x8000000000000000, 0x7FFFFFFFFFFFFFFF]
   }
 }
\ No newline at end of file
index 6803a1a..1ef5110 100644 (file)
                 "$ref" : "#/definitions/MyGame_Example_TestEnum",
                 "minItems": 2,
                 "maxItems": 2
+              },
+        "d" : {
+                "type" : "array", "items" : { "type" : "number" },
+                "minItems": 2,
+                "maxItems": 2
               }
       },
       "additionalProperties" : false
                 "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_NestedStruct" },
                 "minItems": 2,
                 "maxItems": 2
+              },
+        "e" : {
+                "type" : "number"
+              },
+        "f" : {
+                "type" : "array", "items" : { "type" : "number" },
+                "minItems": 2,
+                "maxItems": 2
               }
       },
       "additionalProperties" : false
index 17b0e5a..9fc0d2f 100644 (file)
@@ -62,12 +62,13 @@ inline const char *EnumNameTestEnum(TestEnum e) {
   return EnumNamesTestEnum()[index];
 }
 
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) NestedStruct FLATBUFFERS_FINAL_CLASS {
+FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) NestedStruct FLATBUFFERS_FINAL_CLASS {
  private:
   int32_t a_[2];
   int8_t b_;
   int8_t c_[2];
-  int8_t padding0__;
+  int8_t padding0__;  int32_t padding1__;
+  int64_t d_[2];
 
  public:
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -80,7 +81,8 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) NestedStruct FLATBUFFERS_FINAL_CLASS {
       : b_(flatbuffers::EndianScalar(static_cast<int8_t>(_b))) {
     std::memset(a_, 0, sizeof(a_));
     std::memset(c_, 0, sizeof(c_));
-    (void)padding0__;
+    (void)padding0__;    (void)padding1__;
+    std::memset(d_, 0, sizeof(d_));
   }
   const flatbuffers::Array<int32_t, 2> *a() const {
     return reinterpret_cast<const flatbuffers::Array<int32_t, 2> *>(a_);
@@ -100,14 +102,21 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) NestedStruct FLATBUFFERS_FINAL_CLASS {
   flatbuffers::Array<MyGame::Example::TestEnum, 2> *mutable_c() {
     return reinterpret_cast<flatbuffers::Array<MyGame::Example::TestEnum, 2> *>(c_);
   }
+  const flatbuffers::Array<int64_t, 2> *d() const {
+    return reinterpret_cast<const flatbuffers::Array<int64_t, 2> *>(d_);
+  }
+  flatbuffers::Array<int64_t, 2> *mutable_d() {
+    return reinterpret_cast<flatbuffers::Array<int64_t, 2> *>(d_);
+  }
 };
-FLATBUFFERS_STRUCT_END(NestedStruct, 12);
+FLATBUFFERS_STRUCT_END(NestedStruct, 32);
 
 inline bool operator==(const NestedStruct &lhs, const NestedStruct &rhs) {
   return
       (lhs.a() == rhs.a()) &&
       (lhs.b() == rhs.b()) &&
-      (lhs.c() == rhs.c());
+      (lhs.c() == rhs.c()) &&
+      (lhs.d() == rhs.d());
 }
 
 inline bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs) {
@@ -115,13 +124,16 @@ inline bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs) {
 }
 
 
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) ArrayStruct FLATBUFFERS_FINAL_CLASS {
+FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) ArrayStruct FLATBUFFERS_FINAL_CLASS {
  private:
   float a_;
   int32_t b_[15];
   int8_t c_;
-  int8_t padding0__;  int16_t padding1__;
+  int8_t padding0__;  int16_t padding1__;  int32_t padding2__;
   MyGame::Example::NestedStruct d_[2];
+  int32_t e_;
+  int32_t padding3__;
+  int64_t f_[2];
 
  public:
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -130,14 +142,19 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) ArrayStruct FLATBUFFERS_FINAL_CLASS {
   ArrayStruct() {
     memset(static_cast<void *>(this), 0, sizeof(ArrayStruct));
   }
-  ArrayStruct(float _a, int8_t _c)
+  ArrayStruct(float _a, int8_t _c, int32_t _e)
       : a_(flatbuffers::EndianScalar(_a)),
         c_(flatbuffers::EndianScalar(_c)),
         padding0__(0),
-        padding1__(0) {
+        padding1__(0),
+        padding2__(0),
+        e_(flatbuffers::EndianScalar(_e)),
+        padding3__(0) {
     std::memset(b_, 0, sizeof(b_));
-    (void)padding0__;    (void)padding1__;
+    (void)padding0__;    (void)padding1__;    (void)padding2__;
     std::memset(d_, 0, sizeof(d_));
+    (void)padding3__;
+    std::memset(f_, 0, sizeof(f_));
   }
   float a() const {
     return flatbuffers::EndianScalar(a_);
@@ -163,15 +180,29 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) ArrayStruct FLATBUFFERS_FINAL_CLASS {
   flatbuffers::Array<MyGame::Example::NestedStruct, 2> *mutable_d() {
     return reinterpret_cast<flatbuffers::Array<MyGame::Example::NestedStruct, 2> *>(d_);
   }
+  int32_t e() const {
+    return flatbuffers::EndianScalar(e_);
+  }
+  void mutate_e(int32_t _e) {
+    flatbuffers::WriteScalar(&e_, _e);
+  }
+  const flatbuffers::Array<int64_t, 2> *f() const {
+    return reinterpret_cast<const flatbuffers::Array<int64_t, 2> *>(f_);
+  }
+  flatbuffers::Array<int64_t, 2> *mutable_f() {
+    return reinterpret_cast<flatbuffers::Array<int64_t, 2> *>(f_);
+  }
 };
-FLATBUFFERS_STRUCT_END(ArrayStruct, 92);
+FLATBUFFERS_STRUCT_END(ArrayStruct, 160);
 
 inline bool operator==(const ArrayStruct &lhs, const ArrayStruct &rhs) {
   return
       (lhs.a() == rhs.a()) &&
       (lhs.b() == rhs.b()) &&
       (lhs.c() == rhs.c()) &&
-      (lhs.d() == rhs.d());
+      (lhs.d() == rhs.d()) &&
+      (lhs.e() == rhs.e()) &&
+      (lhs.f() == rhs.f());
 }
 
 inline bool operator!=(const ArrayStruct &lhs, const ArrayStruct &rhs) {
@@ -298,19 +329,21 @@ inline const flatbuffers::TypeTable *NestedStructTypeTable() {
   static const flatbuffers::TypeCode type_codes[] = {
     { flatbuffers::ET_SEQUENCE, 0, -1 },
     { flatbuffers::ET_CHAR, 0, 0 },
-    { flatbuffers::ET_SEQUENCE, 0, 0 }
+    { flatbuffers::ET_SEQUENCE, 0, 0 },
+    { flatbuffers::ET_SEQUENCE, 0, -1 }
   };
   static const flatbuffers::TypeFunction type_refs[] = {
     MyGame::Example::TestEnumTypeTable
   };
-  static const int64_t values[] = { 0, 8, 9, 12 };
+  static const int64_t values[] = { 0, 8, 9, 16, 32 };
   static const char * const names[] = {
     "a",
     "b",
-    "c"
+    "c",
+    "d"
   };
   static const flatbuffers::TypeTable tt = {
-    flatbuffers::ST_STRUCT, 3, type_codes, type_refs, values, names
+    flatbuffers::ST_STRUCT, 4, type_codes, type_refs, values, names
   };
   return &tt;
 }
@@ -320,20 +353,24 @@ inline const flatbuffers::TypeTable *ArrayStructTypeTable() {
     { flatbuffers::ET_FLOAT, 0, -1 },
     { flatbuffers::ET_SEQUENCE, 0, -1 },
     { flatbuffers::ET_CHAR, 0, -1 },
-    { flatbuffers::ET_SEQUENCE, 0, 0 }
+    { flatbuffers::ET_SEQUENCE, 0, 0 },
+    { flatbuffers::ET_INT, 0, -1 },
+    { flatbuffers::ET_SEQUENCE, 0, -1 }
   };
   static const flatbuffers::TypeFunction type_refs[] = {
     MyGame::Example::NestedStructTypeTable
   };
-  static const int64_t values[] = { 0, 4, 64, 68, 92 };
+  static const int64_t values[] = { 0, 4, 64, 72, 136, 144, 160 };
   static const char * const names[] = {
     "a",
     "b",
     "c",
-    "d"
+    "d",
+    "e",
+    "f"
   };
   static const flatbuffers::TypeTable tt = {
-    flatbuffers::ST_STRUCT, 4, type_codes, type_refs, values, names
+    flatbuffers::ST_STRUCT, 6, type_codes, type_refs, values, names
   };
   return &tt;
 }
index b152270..0a661f3 100644 (file)
@@ -1568,9 +1568,12 @@ class TestFixedLengthArrays(unittest.TestCase):
                 MyGame.Example.TestEnum.TestEnum.B], \
                 [MyGame.Example.TestEnum.TestEnum.C, \
                  MyGame.Example.TestEnum.TestEnum.B]]
+        d_d = [[-1, 1], [-2, 2]]
+        e = 2
+        f = [-1, 1]
 
         arrayOffset = MyGame.Example.ArrayStruct.CreateArrayStruct(builder, \
-            a, b, c, d_a, d_b, d_c)
+            a, b, c, d_a, d_b, d_c, d_d, e, f)
 
         # Create a table with the ArrayStruct.
         MyGame.Example.ArrayTable.ArrayTableStart(builder)
@@ -1601,6 +1604,10 @@ class TestFixedLengthArrays(unittest.TestCase):
         self.assertEqual(table.A().D(nested, 1).C(), \
             [MyGame.Example.TestEnum.TestEnum.C, \
              MyGame.Example.TestEnum.TestEnum.B])
+        self.assertEqual(table.A().D(nested, 0).D(), [-1, 1])
+        self.assertEqual(table.A().D(nested, 1).D(), [-2, 2])
+        self.assertEqual(table.A().E(), 2)
+        self.assertEqual(table.A().F(), [-1, 1])
 
 
 def CheckAgainstGoldDataGo():
index 461840c..2efef43 100644 (file)
@@ -2810,6 +2810,9 @@ void FixedLengthArrayTest() {
   TEST_NOTNULL(nStruct0.mutable_c());
   nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
   nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
+  TEST_NOTNULL(nStruct0.mutable_d());
+  nStruct0.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::max());
+  nStruct0.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::min());
   MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
   TEST_NOTNULL(nStruct1.mutable_a());
   nStruct1.mutable_a()->Mutate(0, 3);
@@ -2817,10 +2820,14 @@ void FixedLengthArrayTest() {
   TEST_NOTNULL(nStruct1.mutable_c());
   nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
   nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
-  MyGame::Example::ArrayStruct aStruct(2, 12);
+  TEST_NOTNULL(nStruct1.mutable_d());
+  nStruct1.mutable_d()->Mutate(0, flatbuffers::numeric_limits<int64_t>::min());
+  nStruct1.mutable_d()->Mutate(1, flatbuffers::numeric_limits<int64_t>::max());
+  MyGame::Example::ArrayStruct aStruct(2, 12, 1);
   TEST_NOTNULL(aStruct.b());
   TEST_NOTNULL(aStruct.mutable_b());
   TEST_NOTNULL(aStruct.mutable_d());
+  TEST_NOTNULL(aStruct.mutable_f());
   for (int i = 0; i < aStruct.b()->size(); i++)
     aStruct.mutable_b()->Mutate(i, i + 1);
   aStruct.mutable_d()->Mutate(0, nStruct0);
@@ -2836,8 +2843,10 @@ void FixedLengthArrayTest() {
   TEST_NOTNULL(mArStruct);
   TEST_NOTNULL(mArStruct->b());
   TEST_NOTNULL(mArStruct->d());
+  TEST_NOTNULL(mArStruct->f());
   TEST_NOTNULL(mArStruct->mutable_b());
   TEST_NOTNULL(mArStruct->mutable_d());
+  TEST_NOTNULL(mArStruct->mutable_f());
   mArStruct->mutable_b()->Mutate(14, -14);
   TEST_EQ(mArStruct->a(), 2);
   TEST_EQ(mArStruct->b()->size(), 15);
@@ -2859,14 +2868,25 @@ void FixedLengthArrayTest() {
           true);
   TEST_EQ(mArStruct->d()->Get(0).c()->Get(1) == MyGame::Example::TestEnum::A,
           true);
+  TEST_EQ(mArStruct->d()->Get(0).d()->Get(0),
+          flatbuffers::numeric_limits<int64_t>::max());
+  TEST_EQ(mArStruct->d()->Get(0).d()->Get(1),
+          flatbuffers::numeric_limits<int64_t>::min());
   TEST_EQ(mArStruct->d()->Get(1).b() == MyGame::Example::TestEnum::C, true);
   TEST_NOTNULL(mArStruct->d()->Get(1).c());
   TEST_EQ(mArStruct->d()->Get(1).c()->Get(0) == MyGame::Example::TestEnum::C,
           true);
   TEST_EQ(mArStruct->d()->Get(1).c()->Get(1) == MyGame::Example::TestEnum::A,
           true);
+  TEST_EQ(mArStruct->d()->Get(1).d()->Get(0),
+          flatbuffers::numeric_limits<int64_t>::min());
+  TEST_EQ(mArStruct->d()->Get(1).d()->Get(1),
+          flatbuffers::numeric_limits<int64_t>::max());
   for (int i = 0; i < mArStruct->b()->size() - 1; i++)
     TEST_EQ(mArStruct->b()->Get(i), i + 1);
+  // Check alignment
+  TEST_EQ(reinterpret_cast<uintptr_t>(mArStruct->d()) % 8, 0);
+  TEST_EQ(reinterpret_cast<uintptr_t>(mArStruct->f()) % 8, 0);
 #endif
 }