Allows structs to be stored directly as member variables.
authorWouter van Oortmerssen <wvo@google.com>
Fri, 2 Dec 2016 22:25:08 +0000 (14:25 -0800)
committerWouter van Oortmerssen <wvo@google.com>
Fri, 2 Dec 2016 22:25:08 +0000 (14:25 -0800)
Introduce a "native_inline" attribute that can be applied on fields that are structs.
This results in NativeTable code generation that sets the struct "inline" rather than
storing it in a pointer.

From cl/140527470.

Change-Id: I208724f552b8b921b20923e0bf82f42cb3582416

include/flatbuffers/idl.h
src/idl_gen_cpp.cpp
src/idl_parser.cpp
tests/monster_test.bfbs

index 2440a19..1261031 100644 (file)
@@ -234,6 +234,8 @@ struct FieldDef : public Definition {
                    // written in new data nor accessed in new code.
   bool required;   // Field must always be present.
   bool key;        // Field functions as a key for creating sorted vectors.
+  bool native_inline;  // Field will be defined inline (instead of as a pointer)
+                       // for native tables if field is a struct.
   size_t padding;  // Bytes to always pad after this field.
 };
 
@@ -454,6 +456,7 @@ class Parser : public ParserState {
     known_attributes_["idempotent"] = true;
     known_attributes_["cpp_type"] = true;
     known_attributes_["cpp_ptr_type"] = true;
+    known_attributes_["native_inline"] = true;
   }
 
   ~Parser() {
index 97cb355..7ca7d0b 100644 (file)
@@ -332,7 +332,7 @@ class CppGenerator : public BaseGenerator {
                ">";
       case BASE_TYPE_STRUCT:
         if (IsStruct(type)) {
-          if (invector) {
+          if (invector || field.native_inline) {
             return WrapInNameSpace(*type.struct_def);
           } else {
             return GenTypeNativePtr(WrapInNameSpace(*type.struct_def), &field,
@@ -1016,7 +1016,7 @@ class CppGenerator : public BaseGenerator {
         return val + "->str()";
       case BASE_TYPE_STRUCT:
         if (IsStruct(type)) {
-          if (invector) {
+          if (invector || afield.native_inline) {
             return "*" + val;
           } else {
             return GenTypeNativePtr(WrapInNameSpace(*type.struct_def),
@@ -1059,7 +1059,11 @@ class CppGenerator : public BaseGenerator {
               code += "{ for (flatbuffers::uoffset_t _i = 0;";
               code += " _i < _e->size(); _i++) { ";
               code += dest + ".push_back(";
-              std::string indexing = "_e->Get(_i)";
+              std::string indexing;
+              if (field.value.type.enum_def) {
+                indexing += "(" + field.value.type.enum_def->name + ")";
+              }
+              indexing += "_e->Get(_i)";
               if (field.value.type.element == BASE_TYPE_BOOL)
                 indexing += "!=0";
               code += GenUnpackVal(field.value.type.VectorType(),
@@ -1151,15 +1155,27 @@ class CppGenerator : public BaseGenerator {
                     code += "_fbb.CreateVectorOfStructs(" + accessor + ")";
                   } else {
                     code += "_fbb.CreateVector<flatbuffers::Offset<";
-                    code += vector_type.struct_def->name + ">>(" + accessor;
+                    code += WrapInNameSpace(*vector_type.struct_def) + ">>(" +
+                            accessor;
                     code += ".size(), [&](size_t i) { return Create";
                     code += vector_type.struct_def->name + "(_fbb, " + accessor;
                     code += "[i]" + GenPtrGet(field) + ", rehasher); })";
                   }
                   break;
-                default:
+                case BASE_TYPE_BOOL:
                   code += "_fbb.CreateVector(" + accessor + ")";
                   break;
+                default: {
+                  std::string args = accessor;
+                  if (field.value.type.enum_def) {
+                    const std::string basetype = GenTypeBasic(
+                        field.value.type.enum_def->underlying_type, false);
+                    args = "(const " + basetype + "*)" + accessor +
+                           ".data(), " + accessor + ".size()";
+                  }
+                  code += "_fbb.CreateVector(" + args + ")";
+                  break;
+                }
               }
               code += postfix;
               break;
@@ -1169,7 +1185,11 @@ class CppGenerator : public BaseGenerator {
               break;
             case BASE_TYPE_STRUCT:
               if (IsStruct(field.value.type)) {
-                code += ptrprefix + accessor + GenPtrGet(field) + postfix;
+                if (field.native_inline) {
+                  code += "&" + accessor;
+                } else {
+                  code += ptrprefix + accessor + GenPtrGet(field) + postfix;
+                }
               } else {
                 code += ptrprefix + "Create";
                 code += field.value.type.struct_def->name;
index 0dc7392..ef6e1f5 100644 (file)
@@ -680,6 +680,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
         return Error("'key' field must be string or scalar type");
     }
   }
+
+  field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
+  if (field->native_inline && !IsStruct(field->value.type))
+    return Error("native_inline can only be defined on structs'");
+
   auto nested = field->attributes.Lookup("nested_flatbuffer");
   if (nested) {
     if (nested->type.base_type != BASE_TYPE_STRING)
@@ -1758,9 +1763,6 @@ CheckedError Parser::SkipAnyJsonValue() {
     case kTokenFloatConstant:
       EXPECT(kTokenFloatConstant);
       break;
-    case kTokenNull:
-      EXPECT(kTokenNull);
-      break;
     default:
       return Error(std::string("Unexpected token:") + std::string(1, static_cast<char>(token_)));
   }
index 66d3ee8..0369f89 100644 (file)
Binary files a/tests/monster_test.bfbs and b/tests/monster_test.bfbs differ