mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-24 02:21:46 +00:00
Document requirement for custom string types to implement empty() and be constructible from std::string.
Add new option --cpp-str-flex-ctor to construct custom string types not via std::string, but (char * + length).
This commit is contained in:
@@ -120,7 +120,13 @@ Additional options:
|
|||||||
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
||||||
|
|
||||||
- `--cpp-str-type T` : Set object API string type (default std::string)
|
- `--cpp-str-type T` : Set object API string type (default std::string)
|
||||||
- T::c_str() and T::length() must be supported.
|
T::c_str(), T::length() and T::empty() must be supported.
|
||||||
|
The custom type also needs to be constructible from std::string (see the
|
||||||
|
--cpp-str-flex-ctor option to change this behavior).
|
||||||
|
|
||||||
|
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
|
||||||
|
std::string from Flatbuffers, but (char* + length). This allows efficient
|
||||||
|
construction of custom string types, including zero-copy construction.
|
||||||
|
|
||||||
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
||||||
|
|
||||||
|
|||||||
@@ -255,14 +255,24 @@ you, so you'll have to manage their lifecycles manually. To reference the
|
|||||||
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
||||||
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
||||||
|
|
||||||
|
|
||||||
# Using different string type.
|
# Using different string type.
|
||||||
|
|
||||||
By default the object tree is built out of `std::string`, but you can
|
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
|
influence this either globally (using the `--cpp-str-type` argument to
|
||||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
`flatc`) or per field using the `cpp_str_type` attribute.
|
||||||
|
|
||||||
The type must support T::c_str() and T::length() as member functions.
|
The type must support T::c_str(), T::length() and T::empty() as member functions.
|
||||||
|
|
||||||
|
Further, the type must be constructible from std::string, as by default a
|
||||||
|
std::string instance is constructed and then used to initialize the custom
|
||||||
|
string type. This behavior impedes efficient and zero-copy construction of
|
||||||
|
custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
|
||||||
|
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
|
||||||
|
so that the custom string type is constructed by passing the pointer and
|
||||||
|
length of the FlatBuffers String. The custom string class will require a
|
||||||
|
constructor in the following format: custom_str_class(const char *, uint32_t).
|
||||||
|
Please note that the character array is not guaranteed to be NUL terminated,
|
||||||
|
you should always use the provided size to determine end of string.
|
||||||
|
|
||||||
## Reflection (& Resizing)
|
## Reflection (& Resizing)
|
||||||
|
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ struct IDLOptions {
|
|||||||
bool gen_compare;
|
bool gen_compare;
|
||||||
std::string cpp_object_api_pointer_type;
|
std::string cpp_object_api_pointer_type;
|
||||||
std::string cpp_object_api_string_type;
|
std::string cpp_object_api_string_type;
|
||||||
|
bool cpp_object_api_string_flexible_constructor;
|
||||||
bool gen_nullable;
|
bool gen_nullable;
|
||||||
bool gen_generated;
|
bool gen_generated;
|
||||||
std::string object_prefix;
|
std::string object_prefix;
|
||||||
@@ -486,6 +487,7 @@ struct IDLOptions {
|
|||||||
generate_object_based_api(false),
|
generate_object_based_api(false),
|
||||||
gen_compare(false),
|
gen_compare(false),
|
||||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||||
|
cpp_object_api_string_flexible_constructor(false),
|
||||||
gen_nullable(false),
|
gen_nullable(false),
|
||||||
gen_generated(false),
|
gen_generated(false),
|
||||||
object_suffix("T"),
|
object_suffix("T"),
|
||||||
@@ -627,6 +629,7 @@ class Parser : public ParserState {
|
|||||||
known_attributes_["cpp_ptr_type"] = true;
|
known_attributes_["cpp_ptr_type"] = true;
|
||||||
known_attributes_["cpp_ptr_type_get"] = true;
|
known_attributes_["cpp_ptr_type_get"] = true;
|
||||||
known_attributes_["cpp_str_type"] = true;
|
known_attributes_["cpp_str_type"] = true;
|
||||||
|
known_attributes_["cpp_str_flex_ctor"] = true;
|
||||||
known_attributes_["native_inline"] = true;
|
known_attributes_["native_inline"] = true;
|
||||||
known_attributes_["native_custom_alloc"] = true;
|
known_attributes_["native_custom_alloc"] = true;
|
||||||
known_attributes_["native_type"] = true;
|
known_attributes_["native_type"] = true;
|
||||||
|
|||||||
@@ -107,7 +107,11 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
|
|||||||
" file.\n"
|
" file.\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"
|
" --cpp-str-type T Set object API string type (default std::string).\n"
|
||||||
" T::c_str() and T::length() must be supported.\n"
|
" T::c_str(), T::length() and T::empty() must be supported.\n"
|
||||||
|
" The custom type also needs to be constructible from std::string\n"
|
||||||
|
" (see the --cpp-str-flex-ctor option to change this behavior).\n"
|
||||||
|
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
|
||||||
|
" from Flatbuffers, but (char* + length).\n"
|
||||||
" --object-prefix Customise class prefix for C++ object-based API.\n"
|
" --object-prefix Customise class prefix for C++ object-based API.\n"
|
||||||
" --object-suffix Customise class suffix for C++ object-based API.\n"
|
" --object-suffix Customise class suffix for C++ object-based API.\n"
|
||||||
" Default value is \"T\".\n"
|
" Default value is \"T\".\n"
|
||||||
@@ -247,6 +251,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
|
|||||||
} else if (arg == "--cpp-str-type") {
|
} else if (arg == "--cpp-str-type") {
|
||||||
if (++argi >= argc) Error("missing type following" + arg, true);
|
if (++argi >= argc) Error("missing type following" + arg, true);
|
||||||
opts.cpp_object_api_string_type = argv[argi];
|
opts.cpp_object_api_string_type = argv[argi];
|
||||||
|
} else if (arg == "--cpp-str-flex-ctor") {
|
||||||
|
opts.cpp_object_api_string_flexible_constructor = true;
|
||||||
} else if (arg == "--gen-nullable") {
|
} else if (arg == "--gen-nullable") {
|
||||||
opts.gen_nullable = true;
|
opts.gen_nullable = true;
|
||||||
} else if (arg == "--gen-generated") {
|
} else if (arg == "--gen-generated") {
|
||||||
|
|||||||
@@ -578,6 +578,12 @@ class CppGenerator : public BaseGenerator {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FlexibleStringConstructor(const FieldDef *field) {
|
||||||
|
auto attr = field ? (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr) : false;
|
||||||
|
auto ret = attr ? attr : parser_.opts.cpp_object_api_string_flexible_constructor;
|
||||||
|
return (ret && NativeString(field) != "std::string"); // Only for custom string types.
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -2138,7 +2144,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
bool invector, const FieldDef &afield) {
|
bool invector, const FieldDef &afield) {
|
||||||
switch (type.base_type) {
|
switch (type.base_type) {
|
||||||
case BASE_TYPE_STRING: {
|
case BASE_TYPE_STRING: {
|
||||||
return val + "->str()";
|
if (FlexibleStringConstructor(&afield)) {
|
||||||
|
return NativeString(&afield) + "(" + val + "->c_str(), " + val + "->size())";
|
||||||
|
} else {
|
||||||
|
return val + "->str()";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
const auto name = WrapInNameSpace(*type.struct_def);
|
const auto name = WrapInNameSpace(*type.struct_def);
|
||||||
@@ -2169,7 +2179,7 @@ class CppGenerator : public BaseGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
std::string GenUnpackFieldStatement(const FieldDef &field,
|
std::string GenUnpackFieldStatement(const FieldDef &field,
|
||||||
const FieldDef *union_field) {
|
const FieldDef *union_field) {
|
||||||
|
|||||||
Reference in New Issue
Block a user