Commit f2071e4f authored by Alexander Gallego's avatar Alexander Gallego Committed by Wouter van Oortmerssen

Add arbitrary string type to the native object API (#4218)

* Custom strings are very common for optimizations around small objects
  or growth style optimizations, i.e.: grow at 1.57 times vs doubling vs..

  A second common strategy is to cooperate w/ the memory allocator
  see FBString[1] and seastar[2] string for examples.

[1] fbstring: https://github.com/facebook/folly/blob/master/folly/docs/FBString.md
[2] sstring: https://github.com/scylladb/seastar/blob/master/core/sstring.hh
parent 9c25ecdc
...@@ -200,6 +200,15 @@ pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *` ...@@ -200,6 +200,15 @@ pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
pointers. Unlike the smart pointers, naked pointers do not manage memory for pointers. Unlike the smart pointers, naked pointers do not manage memory for
you, so you'll have to manage their lifecycles manually. you, so you'll have to manage their lifecycles manually.
# Using different string type.
By default the object tree is built out of `std::string`, but you can
influence this either globally (using the `--cpp-str-type` argument to
`flatc`) or per field using the `cpp_str_type` attribute.
The type must support T::c_str() and T::length() as member functions.
## Reflection (& Resizing) ## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to There is experimental support for reflection in FlatBuffers, allowing you to
......
...@@ -980,6 +980,15 @@ FLATBUFFERS_FINAL_CLASS ...@@ -980,6 +980,15 @@ FLATBUFFERS_FINAL_CLASS
return str ? CreateString(str->c_str(), str->Length()) : 0; return str ? CreateString(str->c_str(), str->Length()) : 0;
} }
/// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const reference to a std::string like type with support
/// of T::c_str() and T::length() to store in the buffer.
/// @return Returns the offset in the buffer where the string starts.
template<typename T>
Offset<String> CreateString(const T &str) {
return CreateString(str.c_str(), str.length());
}
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
/// If a string with this exact contents has already been serialized before, /// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string. /// instead simply returns the offset of the existing string.
......
...@@ -353,6 +353,7 @@ struct IDLOptions { ...@@ -353,6 +353,7 @@ struct IDLOptions {
bool escape_proto_identifiers; bool escape_proto_identifiers;
bool generate_object_based_api; bool generate_object_based_api;
std::string cpp_object_api_pointer_type; std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type;
bool union_value_namespacing; bool union_value_namespacing;
bool allow_non_utf8; bool allow_non_utf8;
std::string include_prefix; std::string include_prefix;
...@@ -479,6 +480,7 @@ class Parser : public ParserState { ...@@ -479,6 +480,7 @@ class Parser : public ParserState {
known_attributes_["idempotent"] = true; known_attributes_["idempotent"] = true;
known_attributes_["cpp_type"] = true; known_attributes_["cpp_type"] = true;
known_attributes_["cpp_ptr_type"] = true; known_attributes_["cpp_ptr_type"] = true;
known_attributes_["cpp_str_type"] = true;
known_attributes_["native_inline"] = true; known_attributes_["native_inline"] = true;
known_attributes_["native_type"] = true; known_attributes_["native_type"] = true;
known_attributes_["native_default"] = true; known_attributes_["native_default"] = true;
...@@ -743,4 +745,3 @@ bool GenerateGoGRPC(const Parser &parser, ...@@ -743,4 +745,3 @@ bool GenerateGoGRPC(const Parser &parser,
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATBUFFERS_IDL_H_ #endif // FLATBUFFERS_IDL_H_
...@@ -86,6 +86,8 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const { ...@@ -86,6 +86,8 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" --escape-proto-ids Disable appending '_' in namespaces names.\n" " --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --gen-object-api Generate an additional object-based API.\n" " --gen-object-api Generate an additional object-based API.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n" " --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --cpp-str-type T Set object API string type (default std::string)\n"
" T::c_str() and T::length() must be supported\n"
" --no-js-exports Removes Node.js style export lines in JS.\n" " --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n" " --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n" " --raw-binary Allow binaries without file_indentifier to be read.\n"
...@@ -178,6 +180,9 @@ int FlatCompiler::Compile(int argc, const char** argv) { ...@@ -178,6 +180,9 @@ int FlatCompiler::Compile(int argc, const char** argv) {
} else if (arg == "--cpp-ptr-type") { } else if (arg == "--cpp-ptr-type") {
if (++argi >= argc) Error("missing type following" + arg, true); if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_pointer_type = argv[argi]; opts.cpp_object_api_pointer_type = argv[argi];
} else if (arg == "--cpp-str-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_string_type = argv[argi];
} else if(arg == "--gen-all") { } else if(arg == "--gen-all") {
opts.generate_all = true; opts.generate_all = true;
opts.include_dependence_headers = false; opts.include_dependence_headers = false;
......
...@@ -362,6 +362,15 @@ class CppGenerator : public BaseGenerator { ...@@ -362,6 +362,15 @@ class CppGenerator : public BaseGenerator {
return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type; return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type;
} }
const std::string NativeString(const FieldDef *field) {
auto attr = field ? field->attributes.Lookup("cpp_str_type") : nullptr;
auto &ret = attr ? attr->constant : parser_.opts.cpp_object_api_string_type;
if (ret.empty()) {
return "std::string";
}
return ret;
}
std::string GenTypeNativePtr(const std::string &type, const FieldDef *field, std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
bool is_constructor) { bool is_constructor) {
auto &ptr_type = PtrType(field); auto &ptr_type = PtrType(field);
...@@ -383,7 +392,7 @@ class CppGenerator : public BaseGenerator { ...@@ -383,7 +392,7 @@ class CppGenerator : public BaseGenerator {
const FieldDef &field) { const FieldDef &field) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
return "std::string"; return NativeString(&field);
} }
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field); const auto type_name = GenTypeNative(type.VectorType(), true, field);
......
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