Implement (shared) attribute for C++ (#5157)
authoriceboy <me@iceboy.org>
Mon, 11 Feb 2019 19:53:45 +0000 (11:53 -0800)
committerWouter van Oortmerssen <aardappel@gmail.com>
Mon, 11 Feb 2019 19:53:45 +0000 (20:53 +0100)
* Implement native_shared attribute for C++.

Fixes #5141. See also #5145.

* Refine comment in idl.h

* Also refine docs

* Revert "Also refine docs"

This reverts commit 09dab7b45c56c2d17eac493203adc8caaa0df2cc.

* Also refine docs again.

* grumble

docs/source/CppUsage.md
include/flatbuffers/idl.h
src/idl_gen_cpp.cpp
src/idl_parser.cpp

index 7404512..2808c49 100644 (file)
@@ -88,6 +88,14 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
 
 *Note: That we never stored a `mana` value, so it will return the default.*
 
+The following attributes are supported:
+
+-   `shared` (on a field): For string fields, this enables the usage of string
+    pooling (i.e. `CreateSharedString`) as default serialization behavior.
+
+    Specifically, `CreateXxxDirect` functions and `Pack` functions for object
+    based API (see below) will use `CreateSharedString` to create strings.
+
 ## Object based API.  {#flatbuffers_cpp_object_based_api}
 
 FlatBuffers is all about memory efficiency, which is why its base API is written
index e48edb0..3c31881 100644 (file)
@@ -258,6 +258,7 @@ struct FieldDef : public Definition {
       : deprecated(false),
         required(false),
         key(false),
+        shared(false),
         native_inline(false),
         flexbuffer(false),
         nested_flatbuffer(NULL),
@@ -273,6 +274,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 shared;  // Field will be using string pooling (i.e. CreateSharedString)
+                // as default serialization behavior if field is a string.
   bool native_inline;  // Field will be defined inline (instead of as a pointer)
                        // for native tables if field is a struct.
   bool flexbuffer;     // This field contains FlexBuffer data.
@@ -608,6 +611,7 @@ class Parser : public ParserState {
     known_attributes_["deprecated"] = true;
     known_attributes_["required"] = true;
     known_attributes_["key"] = true;
+    known_attributes_["shared"] = true;
     known_attributes_["hash"] = true;
     known_attributes_["id"] = true;
     known_attributes_["force_align"] = true;
index 9884081..9294953 100644 (file)
@@ -2083,9 +2083,14 @@ class CppGenerator : public BaseGenerator {
         if (!field.deprecated) {
           code_.SetValue("FIELD_NAME", Name(field));
           if (field.value.type.base_type == BASE_TYPE_STRING) {
+            if (!field.shared) {
+              code_.SetValue("CREATE_STRING", "CreateString");
+            } else {
+              code_.SetValue("CREATE_STRING", "CreateSharedString");
+            }
             code_ +=
                 "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
-                "_fbb.CreateString({{FIELD_NAME}}) : 0;";
+                "_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
           } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
             code_ += "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
             const auto vtype = field.value.type.VectorType();
@@ -2294,8 +2299,16 @@ class CppGenerator : public BaseGenerator {
     switch (field.value.type.base_type) {
       // String fields are of the form:
       //   _fbb.CreateString(_o->field)
+      // or
+      //   _fbb.CreateSharedString(_o->field)
       case BASE_TYPE_STRING: {
-        code += "_fbb.CreateString(" + value + ")";
+        if (!field.shared) {
+          code += "_fbb.CreateString(";
+        } else {
+          code += "_fbb.CreateSharedString(";
+        }
+        code += value;
+        code.push_back(')');
 
         // For optional fields, check to see if there actually is any data
         // in _o->field before attempting to access it. If there isn't,
index a1d6cb0..32a9a72 100644 (file)
@@ -767,6 +767,9 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
         return Error("'key' field must be string or scalar type");
     }
   }
+  field->shared = field->attributes.Lookup("shared") != nullptr;
+  if (field->shared && field->value.type.base_type != BASE_TYPE_STRING)
+    return Error("shared can only be defined on strings");
 
   auto field_native_custom_alloc =
       field->attributes.Lookup("native_custom_alloc");
@@ -777,7 +780,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
 
   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'");
+    return Error("native_inline can only be defined on structs");
 
   auto nested = field->attributes.Lookup("nested_flatbuffer");
   if (nested) {