mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-29 19:42:02 +00:00
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
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
9c25ecdcd1
commit
f2071e4f80
@@ -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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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,
|
|||||||
} // 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 {
|
|||||||
" --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) {
|
|||||||
} 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 {
|
|||||||
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 {
|
|||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user