From c5df6500995a783308a07ae5be8bfca5e024b3e5 Mon Sep 17 00:00:00 2001 From: iceboy Date: Tue, 5 Feb 2019 12:59:44 -0800 Subject: [PATCH] Implement native_shared attribute for C++. Fixes #5141. See also #5145. --- docs/source/CppUsage.md | 6 ++++++ include/flatbuffers/idl.h | 4 ++++ src/idl_gen_cpp.cpp | 20 ++++++++++++++++---- src/idl_parser.cpp | 5 ++++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md index ad47a9440..a72b96a59 100644 --- a/docs/source/CppUsage.md +++ b/docs/source/CppUsage.md @@ -88,6 +88,12 @@ 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: + +- `native_shared` (on a field): For string fields, this enables the usage of + CreateSharedString() instead of CreateString() for generated + CreateXxxDirect(), and Pack() in object-based API if enabled. + ## Object based API. {#flatbuffers_cpp_object_based_api} FlatBuffers is all about memory efficiency, which is why its base API is written diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index e48edb01e..a766f57b3 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -259,6 +259,7 @@ struct FieldDef : public Definition { required(false), key(false), native_inline(false), + native_shared(false), flexbuffer(false), nested_flatbuffer(NULL), padding(0) {} @@ -275,6 +276,8 @@ struct FieldDef : public Definition { 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. + bool native_shared; // Field will be using CreateSharedString while packing + // if field is a string. bool flexbuffer; // This field contains FlexBuffer data. StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data. size_t padding; // Bytes to always pad after this field. @@ -623,6 +626,7 @@ class Parser : public ParserState { known_attributes_["cpp_str_type"] = true; known_attributes_["native_inline"] = true; known_attributes_["native_custom_alloc"] = true; + known_attributes_["native_shared"] = true; known_attributes_["native_type"] = true; known_attributes_["native_default"] = true; known_attributes_["flexbuffer"] = true; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 9884081ad..62361fd5a 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -2083,9 +2083,15 @@ class CppGenerator : public BaseGenerator { if (!field.deprecated) { code_.SetValue("FIELD_NAME", Name(field)); if (field.value.type.base_type == BASE_TYPE_STRING) { - code_ += - " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " - "_fbb.CreateString({{FIELD_NAME}}) : 0;"; + if (!field.native_shared) { + code_ += + " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " + "_fbb.CreateString({{FIELD_NAME}}) : 0;"; + } else { + code_ += + " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " + "_fbb.CreateSharedString({{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 +2300,14 @@ 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.native_shared) { + code += "_fbb.CreateString(" + value + ")"; + } else { + code += "_fbb.CreateSharedString(" + value + ")"; + } // For optional fields, check to see if there actually is any data // in _o->field before attempting to access it. If there isn't, diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index a1d6cb060..0f7fda39e 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -777,7 +777,10 @@ 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"); + field->native_shared = field->attributes.Lookup("native_shared") != nullptr; + if (field->native_shared && field->value.type.base_type != BASE_TYPE_STRING) + return Error("native_shared can only be defined on strings"); auto nested = field->attributes.Lookup("nested_flatbuffer"); if (nested) {