Commit 60e94cf0 authored by iceboy's avatar iceboy Committed by Wouter van Oortmerssen

Implement (shared) attribute for C++ (#5157)

* 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
parent cf47f271
...@@ -88,6 +88,14 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc: ...@@ -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.* *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} ## Object based API. {#flatbuffers_cpp_object_based_api}
FlatBuffers is all about memory efficiency, which is why its base API is written FlatBuffers is all about memory efficiency, which is why its base API is written
......
...@@ -258,6 +258,7 @@ struct FieldDef : public Definition { ...@@ -258,6 +258,7 @@ struct FieldDef : public Definition {
: deprecated(false), : deprecated(false),
required(false), required(false),
key(false), key(false),
shared(false),
native_inline(false), native_inline(false),
flexbuffer(false), flexbuffer(false),
nested_flatbuffer(NULL), nested_flatbuffer(NULL),
...@@ -273,6 +274,8 @@ struct FieldDef : public Definition { ...@@ -273,6 +274,8 @@ struct FieldDef : public Definition {
// written in new data nor accessed in new code. // written in new data nor accessed in new code.
bool required; // Field must always be present. bool required; // Field must always be present.
bool key; // Field functions as a key for creating sorted vectors. 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) bool native_inline; // Field will be defined inline (instead of as a pointer)
// for native tables if field is a struct. // for native tables if field is a struct.
bool flexbuffer; // This field contains FlexBuffer data. bool flexbuffer; // This field contains FlexBuffer data.
...@@ -608,6 +611,7 @@ class Parser : public ParserState { ...@@ -608,6 +611,7 @@ class Parser : public ParserState {
known_attributes_["deprecated"] = true; known_attributes_["deprecated"] = true;
known_attributes_["required"] = true; known_attributes_["required"] = true;
known_attributes_["key"] = true; known_attributes_["key"] = true;
known_attributes_["shared"] = true;
known_attributes_["hash"] = true; known_attributes_["hash"] = true;
known_attributes_["id"] = true; known_attributes_["id"] = true;
known_attributes_["force_align"] = true; known_attributes_["force_align"] = true;
......
...@@ -2083,9 +2083,14 @@ class CppGenerator : public BaseGenerator { ...@@ -2083,9 +2083,14 @@ class CppGenerator : public BaseGenerator {
if (!field.deprecated) { if (!field.deprecated) {
code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_NAME", Name(field));
if (field.value.type.base_type == BASE_TYPE_STRING) { if (field.value.type.base_type == BASE_TYPE_STRING) {
if (!field.shared) {
code_.SetValue("CREATE_STRING", "CreateString");
} else {
code_.SetValue("CREATE_STRING", "CreateSharedString");
}
code_ += code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? " " 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) { } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\"; code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
const auto vtype = field.value.type.VectorType(); const auto vtype = field.value.type.VectorType();
...@@ -2294,8 +2299,16 @@ class CppGenerator : public BaseGenerator { ...@@ -2294,8 +2299,16 @@ class CppGenerator : public BaseGenerator {
switch (field.value.type.base_type) { switch (field.value.type.base_type) {
// String fields are of the form: // String fields are of the form:
// _fbb.CreateString(_o->field) // _fbb.CreateString(_o->field)
// or
// _fbb.CreateSharedString(_o->field)
case BASE_TYPE_STRING: { 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 // For optional fields, check to see if there actually is any data
// in _o->field before attempting to access it. If there isn't, // in _o->field before attempting to access it. If there isn't,
......
...@@ -767,6 +767,9 @@ CheckedError Parser::ParseField(StructDef &struct_def) { ...@@ -767,6 +767,9 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return Error("'key' field must be string or scalar type"); 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 = auto field_native_custom_alloc =
field->attributes.Lookup("native_custom_alloc"); field->attributes.Lookup("native_custom_alloc");
...@@ -777,7 +780,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { ...@@ -777,7 +780,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
field->native_inline = field->attributes.Lookup("native_inline") != nullptr; field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
if (field->native_inline && !IsStruct(field->value.type)) 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"); auto nested = field->attributes.Lookup("nested_flatbuffer");
if (nested) { if (nested) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment