mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-06 13:37:25 +00:00
Added support for structs and strings in unions.
(C++ only for now). Also fixed vector of union support in the object API. Bug: 36902939 Change-Id: I935f4cc2c303a4728e26c7916a8ec0adcd6f84cb Tested: on Linux.
This commit is contained in:
@@ -109,7 +109,7 @@ class CppGenerator : public BaseGenerator {
|
||||
SetNameSpace(struct_def.defined_namespace);
|
||||
code_ += "struct " + struct_def.name + ";";
|
||||
if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
|
||||
code_ += "struct " + NativeName(struct_def.name) + ";";
|
||||
code_ += "struct " + NativeName(struct_def.name, &struct_def) + ";";
|
||||
}
|
||||
code_ += "";
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class CppGenerator : public BaseGenerator {
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// A convenient root unpack function.
|
||||
auto native_name =
|
||||
NativeName(WrapInNameSpace(struct_def));
|
||||
NativeName(WrapInNameSpace(struct_def), &struct_def);
|
||||
code_.SetValue("UNPACK_RETURN",
|
||||
GenTypeNativePtr(native_name, nullptr, false));
|
||||
code_.SetValue("UNPACK_TYPE",
|
||||
@@ -355,7 +355,9 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
// TODO(wvo): make this configurable.
|
||||
static std::string NativeName(const std::string &name) { return name + "T"; }
|
||||
static std::string NativeName(const std::string &name, const StructDef *sd) {
|
||||
return sd && !sd->fixed ? name + "T" : name;
|
||||
}
|
||||
|
||||
const std::string &PtrType(const FieldDef *field) {
|
||||
auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
|
||||
@@ -411,7 +413,8 @@ class CppGenerator : public BaseGenerator {
|
||||
return GenTypeNativePtr(type_name, &field, false);
|
||||
}
|
||||
} else {
|
||||
return GenTypeNativePtr(NativeName(type_name), &field, false);
|
||||
return GenTypeNativePtr(NativeName(type_name, type.struct_def),
|
||||
&field, false);
|
||||
}
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
@@ -458,6 +461,26 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
std::string StripUnionType(const std::string &name) {
|
||||
return name.substr(0, name.size() - strlen(UnionTypeFieldSuffix()));
|
||||
}
|
||||
|
||||
std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type,
|
||||
bool native_type = false) {
|
||||
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
auto name = actual_type ? ev.union_type.struct_def->name : ev.name;
|
||||
return wrap
|
||||
? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name)
|
||||
: name;
|
||||
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
|
||||
return actual_type
|
||||
? (native_type ? "std::string" : "flatbuffers::String")
|
||||
: ev.name;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string UnionVerifySignature(const EnumDef &enum_def) {
|
||||
return "bool Verify" + enum_def.name +
|
||||
"(flatbuffers::Verifier &verifier, const void *obj, " +
|
||||
@@ -474,7 +497,7 @@ class CppGenerator : public BaseGenerator {
|
||||
static std::string UnionUnPackSignature(const EnumDef &enum_def,
|
||||
bool inclass) {
|
||||
return (inclass ? "static " : "") +
|
||||
std::string("flatbuffers::NativeTable *") +
|
||||
std::string("void *") +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"UnPack(const void *obj, " + enum_def.name +
|
||||
" type, const flatbuffers::resolver_function_t *resolver)";
|
||||
@@ -493,7 +516,7 @@ class CppGenerator : public BaseGenerator {
|
||||
return "flatbuffers::Offset<" + struct_def.name + "> Create" +
|
||||
struct_def.name +
|
||||
"(flatbuffers::FlatBufferBuilder &_fbb, const " +
|
||||
NativeName(struct_def.name) +
|
||||
NativeName(struct_def.name, &struct_def) +
|
||||
" *_o, const flatbuffers::rehasher_function_t *_rehasher" +
|
||||
(predecl ? " = nullptr" : "") + ")";
|
||||
}
|
||||
@@ -504,14 +527,14 @@ class CppGenerator : public BaseGenerator {
|
||||
"flatbuffers::Offset<" + struct_def.name + "> " +
|
||||
(inclass ? "" : struct_def.name + "::") +
|
||||
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
|
||||
"const " + NativeName(struct_def.name) + "* _o, " +
|
||||
"const " + NativeName(struct_def.name, &struct_def) + "* _o, " +
|
||||
"const flatbuffers::rehasher_function_t *_rehasher" +
|
||||
(inclass ? " = nullptr" : "") + ")";
|
||||
}
|
||||
|
||||
static std::string TableUnPackSignature(const StructDef &struct_def,
|
||||
bool inclass) {
|
||||
return NativeName(struct_def.name) + " *" +
|
||||
return NativeName(struct_def.name, &struct_def) + " *" +
|
||||
(inclass ? "" : struct_def.name + "::") +
|
||||
"UnPack(const flatbuffers::resolver_function_t *_resolver" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
@@ -520,8 +543,8 @@ class CppGenerator : public BaseGenerator {
|
||||
static std::string TableUnPackToSignature(const StructDef &struct_def,
|
||||
bool inclass) {
|
||||
return "void " + (inclass ? "" : struct_def.name + "::") +
|
||||
"UnPackTo(" + NativeName(struct_def.name) + " *" + "_o, " +
|
||||
"const flatbuffers::resolver_function_t *_resolver" +
|
||||
"UnPackTo(" + NativeName(struct_def.name, &struct_def) + " *" +
|
||||
"_o, const flatbuffers::resolver_function_t *_resolver" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
}
|
||||
|
||||
@@ -629,7 +652,7 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
// Generate type traits for unions to map from a type to union enum value.
|
||||
if (enum_def.is_union) {
|
||||
if (enum_def.is_union && !enum_def.uses_type_aliases) {
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
const auto &ev = **it;
|
||||
@@ -638,7 +661,7 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
|
||||
}
|
||||
else {
|
||||
auto name = WrapInNameSpace(*ev.struct_def);
|
||||
auto name = GetUnionElement(ev, true, true);
|
||||
code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
|
||||
}
|
||||
|
||||
@@ -657,29 +680,31 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
code_ += "struct {{NAME}}Union {";
|
||||
code_ += " {{NAME}} type;";
|
||||
code_ += " flatbuffers::NativeTable *table;";
|
||||
code_ += " void *value;";
|
||||
code_ += "";
|
||||
code_ += " {{NAME}}Union() : type({{NONE}}), table(nullptr) {}";
|
||||
code_ += " {{NAME}}Union() : type({{NONE}}), value(nullptr) {}";
|
||||
code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :";
|
||||
code_ += " type({{NONE}}), table(nullptr)";
|
||||
code_ += " { std::swap(type, u.type); std::swap(table, u.table); }";
|
||||
code_ += " type({{NONE}}), value(nullptr)";
|
||||
code_ += " { std::swap(type, u.type); std::swap(value, u.value); }";
|
||||
code_ += " {{NAME}}Union(const {{NAME}}Union &);";
|
||||
code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &);";
|
||||
code_ += " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT";
|
||||
code_ += " { std::swap(type, u.type); std::swap(table, u.table); return *this; }";
|
||||
code_ += " { std::swap(type, u.type); std::swap(value, u.value); return *this; }";
|
||||
code_ += " ~{{NAME}}Union() { Reset(); }";
|
||||
code_ += "";
|
||||
code_ += " void Reset();";
|
||||
code_ += "";
|
||||
code_ += " template <typename T>";
|
||||
code_ += " void Set(T&& value) {";
|
||||
code_ += " Reset();";
|
||||
code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;";
|
||||
code_ += " if (type != {{NONE}}) {";
|
||||
code_ += " table = new T(std::forward<T>(value));";
|
||||
code_ += " }";
|
||||
code_ += " }";
|
||||
code_ += "";
|
||||
if (!enum_def.uses_type_aliases) {
|
||||
code_ += " template <typename T>";
|
||||
code_ += " void Set(T&& val) {";
|
||||
code_ += " Reset();";
|
||||
code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;";
|
||||
code_ += " if (type != {{NONE}}) {";
|
||||
code_ += " value = new T(std::forward<T>(val));";
|
||||
code_ += " }";
|
||||
code_ += " }";
|
||||
code_ += "";
|
||||
}
|
||||
code_ += " " + UnionUnPackSignature(enum_def, true) + ";";
|
||||
code_ += " " + UnionPackSignature(enum_def, true) + ";";
|
||||
code_ += "";
|
||||
@@ -691,14 +716,16 @@ class CppGenerator : public BaseGenerator {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto native_type = NativeName(WrapInNameSpace(*ev.struct_def));
|
||||
const auto native_type =
|
||||
NativeName(GetUnionElement(ev, true, true, true),
|
||||
ev.union_type.struct_def);
|
||||
code_.SetValue("NATIVE_TYPE", native_type);
|
||||
code_.SetValue("NATIVE_NAME", ev.name);
|
||||
code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
|
||||
|
||||
code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
|
||||
code_ += " return type == {{NATIVE_ID}} ?";
|
||||
code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(table) : nullptr;";
|
||||
code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;";
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += "};";
|
||||
@@ -728,10 +755,23 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
|
||||
if (ev.value) {
|
||||
code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def));
|
||||
code_.SetValue("TYPE", GetUnionElement(ev, true, true));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
|
||||
code_ += " return verifier.VerifyTable(ptr);";
|
||||
auto getptr =
|
||||
" auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
|
||||
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
if (ev.union_type.struct_def->fixed) {
|
||||
code_ += " return true;";
|
||||
} else {
|
||||
code_ += getptr;
|
||||
code_ += " return verifier.VerifyTable(ptr);";
|
||||
}
|
||||
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
|
||||
code_ += getptr;
|
||||
code_ += " return verifier.Verify(ptr);";
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
code_ += " }";
|
||||
} else {
|
||||
code_ += " case {{LABEL}}: {";
|
||||
@@ -768,10 +808,21 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def));
|
||||
code_.SetValue("TYPE", GetUnionElement(ev, true, true));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
|
||||
code_ += " return ptr->UnPack(resolver);";
|
||||
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
if (ev.union_type.struct_def->fixed) {
|
||||
code_ += " return new " +
|
||||
WrapInNameSpace(*ev.union_type.struct_def) + "(*ptr);";
|
||||
} else {
|
||||
code_ += " return ptr->UnPack(resolver);";
|
||||
}
|
||||
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
|
||||
code_ += " return new std::string(ptr->c_str(), ptr->size());";
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += " default: return nullptr;";
|
||||
@@ -789,11 +840,23 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def)));
|
||||
code_.SetValue("NAME", ev.struct_def->name);
|
||||
code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
|
||||
ev.union_type.struct_def));
|
||||
code_.SetValue("NAME", GetUnionElement(ev, false, true));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(table);";
|
||||
code_ += " return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(value);";
|
||||
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
if (ev.union_type.struct_def->fixed) {
|
||||
code_ += " return _fbb.CreateStruct(*ptr).Union();";
|
||||
} else {
|
||||
code_ +=
|
||||
" return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
|
||||
}
|
||||
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
|
||||
code_ += " return _fbb.CreateString(*ptr).Union();";
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += " default: return 0;";
|
||||
@@ -815,17 +878,18 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def)));
|
||||
code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
|
||||
ev.union_type.struct_def));
|
||||
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(table);";
|
||||
code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(value);";
|
||||
code_ += " delete ptr;";
|
||||
code_ += " break;";
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += " default: break;";
|
||||
code_ += " }";
|
||||
code_ += " table = nullptr;";
|
||||
code_ += " value = nullptr;";
|
||||
code_ += " type = {{NONE}};";
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
@@ -914,7 +978,9 @@ class CppGenerator : public BaseGenerator {
|
||||
// Generate a member, including a default value for scalars and raw pointers.
|
||||
void GenMember(const FieldDef &field) {
|
||||
if (!field.deprecated && // Deprecated fields won't be accessible.
|
||||
field.value.type.base_type != BASE_TYPE_UTYPE) {
|
||||
field.value.type.base_type != BASE_TYPE_UTYPE &&
|
||||
(field.value.type.base_type != BASE_TYPE_VECTOR ||
|
||||
field.value.type.element != BASE_TYPE_UTYPE)) {
|
||||
auto type = GenTypeNative(field.value.type, false, field);
|
||||
auto cpp_type = field.attributes.Lookup("cpp_type");
|
||||
auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " ");
|
||||
@@ -964,7 +1030,7 @@ class CppGenerator : public BaseGenerator {
|
||||
initializer_list = "\n : " + initializer_list;
|
||||
}
|
||||
|
||||
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name));
|
||||
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def));
|
||||
code_.SetValue("INIT_LIST", initializer_list);
|
||||
|
||||
code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";
|
||||
@@ -972,7 +1038,7 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
void GenNativeTable(const StructDef &struct_def) {
|
||||
const auto native_name = NativeName(struct_def.name);
|
||||
const auto native_name = NativeName(struct_def.name, &struct_def);
|
||||
code_.SetValue("STRUCT_NAME", struct_def.name);
|
||||
code_.SetValue("NATIVE_NAME", native_name);
|
||||
|
||||
@@ -1138,24 +1204,23 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
for (auto u_it = u->vals.vec.begin();
|
||||
u_it != u->vals.vec.end(); ++u_it) {
|
||||
if (!(*u_it)->struct_def) {
|
||||
auto &ev = **u_it;
|
||||
if (ev.union_type.base_type == BASE_TYPE_NONE) {
|
||||
continue;
|
||||
}
|
||||
auto arg_struct_def = (*u_it)->struct_def;
|
||||
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
|
||||
auto full_struct_name = GetUnionElement(ev, true, true);
|
||||
|
||||
// @TODO: Mby make this decisions more universal? How?
|
||||
code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix());
|
||||
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||
u->defined_namespace, GetEnumValUse(*u, **u_it)));
|
||||
u->defined_namespace, GetEnumValUse(*u, ev)));
|
||||
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
|
||||
code_.SetValue("U_FIELD_NAME",
|
||||
field.name + "_as_" + (*u_it)->name);
|
||||
field.name + "_as_" + ev.name);
|
||||
|
||||
// `const Type *union_name_asType() const` accessor.
|
||||
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
|
||||
code_ += " return ({{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}})? "
|
||||
code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
|
||||
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
|
||||
": nullptr;";
|
||||
code_ += " }";
|
||||
@@ -1279,23 +1344,25 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
auto u = field.value.type.enum_def;
|
||||
if (u->uses_type_aliases) continue;
|
||||
|
||||
code_.SetValue("FIELD_NAME", field.name);
|
||||
|
||||
for (auto u_it = u->vals.vec.begin();
|
||||
u_it != u->vals.vec.end(); ++u_it) {
|
||||
if (!(*u_it)->struct_def) {
|
||||
auto &ev = **u_it;
|
||||
if (ev.union_type.base_type == BASE_TYPE_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto arg_struct_def = (*u_it)->struct_def;
|
||||
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
|
||||
auto full_struct_name = GetUnionElement(ev, true, true);
|
||||
|
||||
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||
u->defined_namespace, GetEnumValUse(*u, **u_it)));
|
||||
u->defined_namespace, GetEnumValUse(*u, ev)));
|
||||
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
|
||||
code_.SetValue("U_FIELD_NAME",
|
||||
field.name + "_as_" + (*u_it)->name);
|
||||
field.name + "_as_" + ev.name);
|
||||
|
||||
// `template<> const T *union_name_as<T>() const` accessor.
|
||||
code_ += "template<> "
|
||||
@@ -1475,6 +1542,14 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenUnionUnpackVal(const FieldDef &afield,
|
||||
const char *vec_elem_access,
|
||||
const char *vec_type_access) {
|
||||
return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" +
|
||||
vec_elem_access + ", " + afield.name + UnionTypeFieldSuffix() +
|
||||
"()" + vec_type_access + ", _resolver)";
|
||||
}
|
||||
|
||||
std::string GenUnpackVal(const Type &type, const std::string &val,
|
||||
bool invector, const FieldDef &afield) {
|
||||
switch (type.base_type) {
|
||||
@@ -1494,10 +1569,18 @@ class CppGenerator : public BaseGenerator {
|
||||
return ptype + "(new " + name + "(*" + val + "))";
|
||||
}
|
||||
} else {
|
||||
const auto ptype = GenTypeNativePtr(NativeName(name), &afield, true);
|
||||
const auto ptype = GenTypeNativePtr(NativeName(name, type.struct_def),
|
||||
&afield, true);
|
||||
return ptype + "(" + val + "->UnPack(_resolver))";
|
||||
}
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
return GenUnionUnpackVal(afield,
|
||||
invector ? "->Get(_i)" : "",
|
||||
invector ? ("->GetEnum<" +
|
||||
type.enum_def->name +
|
||||
">(_i)").c_str() : "");
|
||||
}
|
||||
default: {
|
||||
return val;
|
||||
break;
|
||||
@@ -1523,10 +1606,19 @@ class CppGenerator : public BaseGenerator {
|
||||
// for (uoffset_t i = 0; i < _e->size(); ++i) {
|
||||
// _o->field.push_back(_e->Get(_i));
|
||||
// }
|
||||
code += "{ _o->" + field.name + ".resize(_e->size()); ";
|
||||
auto name = field.name;
|
||||
if (field.value.type.element == BASE_TYPE_UTYPE) {
|
||||
name = StripUnionType(field.name);
|
||||
}
|
||||
auto access = field.value.type.element == BASE_TYPE_UTYPE
|
||||
? ".type"
|
||||
: (field.value.type.element == BASE_TYPE_UNION
|
||||
? ".value"
|
||||
: "");
|
||||
code += "{ _o->" + name + ".resize(_e->size()); ";
|
||||
code += "for (flatbuffers::uoffset_t _i = 0;";
|
||||
code += " _i < _e->size(); _i++) { ";
|
||||
code += "_o->" + field.name + "[_i] = ";
|
||||
code += "_o->" + name + "[_i]" + access + " = ";
|
||||
code += GenUnpackVal(field.value.type.VectorType(),
|
||||
indexing, true, field);
|
||||
code += "; } }";
|
||||
@@ -1540,12 +1632,11 @@ class CppGenerator : public BaseGenerator {
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
// Generate code that sets the union table, of the form:
|
||||
// _o->field.table = Union::Unpack(_e, field_type(), resolver);
|
||||
code += "_o->" + field.name + ".table = ";
|
||||
code += field.value.type.enum_def->name + "Union::UnPack(";
|
||||
code += "_e, " + field.name + UnionTypeFieldSuffix() + "(),";
|
||||
code += "_resolver);";
|
||||
// Generate code that sets the union value, of the form:
|
||||
// _o->field.value = Union::Unpack(_e, field_type(), resolver);
|
||||
code += "_o->" + field.name + ".value = ";
|
||||
code += GenUnionUnpackVal(field, "", "");
|
||||
code += ";";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -1577,8 +1668,7 @@ class CppGenerator : public BaseGenerator {
|
||||
std::string GenCreateParam(const FieldDef &field) {
|
||||
std::string value = "_o->";
|
||||
if (field.value.type.base_type == BASE_TYPE_UTYPE) {
|
||||
value += field.name.substr(0, field.name.size() -
|
||||
strlen(UnionTypeFieldSuffix()));
|
||||
value += StripUnionType(field.name);
|
||||
value += ".type";
|
||||
} else {
|
||||
value += field.name;
|
||||
@@ -1635,6 +1725,19 @@ class CppGenerator : public BaseGenerator {
|
||||
code += "_fbb.CreateVector(" + value + ")";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
code += "_fbb.CreateVector<flatbuffers::Offset<void>>(" + value +
|
||||
".size(), [&](size_t i) { return " + value +
|
||||
"[i].Pack(_fbb, _rehasher); })";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UTYPE: {
|
||||
value = StripUnionType(value);
|
||||
code += "_fbb.CreateVector<uint8_t>(" + value +
|
||||
".size(), [&](size_t i) { return static_cast<uint8_t>(" + value +
|
||||
"[i].type); })";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (field.value.type.enum_def) {
|
||||
// For enumerations, we need to get access to the array data for
|
||||
@@ -1693,7 +1796,7 @@ class CppGenerator : public BaseGenerator {
|
||||
// Generate code for tables that needs to come after the regular definition.
|
||||
void GenTablePost(const StructDef &struct_def) {
|
||||
code_.SetValue("STRUCT_NAME", struct_def.name);
|
||||
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name));
|
||||
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def));
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate the X::UnPack() method.
|
||||
|
||||
@@ -71,7 +71,8 @@ namespace js {
|
||||
class JsGenerator : public BaseGenerator {
|
||||
public:
|
||||
typedef std::unordered_set<std::string> imported_fileset;
|
||||
typedef std::unordered_multimap<std::string, ReexportDescription> reexport_map;
|
||||
typedef std::unordered_multimap<std::string, ReexportDescription>
|
||||
reexport_map;
|
||||
|
||||
JsGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
@@ -104,19 +105,22 @@ class JsGenerator : public BaseGenerator {
|
||||
code += enum_code;
|
||||
code += struct_code;
|
||||
|
||||
if (lang_.language == IDLOptions::kJs && !exports_code.empty() && !parser_.opts.skip_js_exports) {
|
||||
if (lang_.language == IDLOptions::kJs && !exports_code.empty() &&
|
||||
!parser_.opts.skip_js_exports) {
|
||||
code += "// Exports for Node.js and RequireJS\n";
|
||||
code += exports_code;
|
||||
}
|
||||
|
||||
return SaveFile(GeneratedFileName(path_, file_name_, lang_).c_str(), code, false);
|
||||
return SaveFile(GeneratedFileName(path_, file_name_, lang_).c_str(), code,
|
||||
false);
|
||||
}
|
||||
|
||||
private:
|
||||
JsLanguageParameters lang_;
|
||||
|
||||
// Generate code for imports
|
||||
void generateImportDependencies(std::string *code_ptr, const imported_fileset &imported_files) {
|
||||
void generateImportDependencies(std::string *code_ptr,
|
||||
const imported_fileset &imported_files) {
|
||||
std::string &code = *code_ptr;
|
||||
for (auto it = imported_files.begin(); it != imported_files.end(); ++it) {
|
||||
const auto &file = *it;
|
||||
@@ -129,11 +133,13 @@ class JsGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate reexports, which might not have been explicitly imported using the "export import" trick
|
||||
// Generate reexports, which might not have been explicitly imported using the
|
||||
// "export import" trick
|
||||
void generateReexports(std::string *code_ptr,
|
||||
const reexport_map &reexports,
|
||||
imported_fileset imported_files) {
|
||||
if (!parser_.opts.reexport_ts_modules || lang_.language != IDLOptions::kTs) {
|
||||
if (!parser_.opts.reexport_ts_modules ||
|
||||
lang_.language != IDLOptions::kTs) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -152,7 +158,9 @@ class JsGenerator : public BaseGenerator {
|
||||
|
||||
code += "export namespace " + file.second.target_namespace + " { \n";
|
||||
code += "export import " + file.second.symbol + " = ";
|
||||
code += GenFileNamespacePrefix(file.first) + "." + file.second.source_namespace + "." + file.second.symbol + "; }\n";
|
||||
code += GenFileNamespacePrefix(file.first) + "." +
|
||||
file.second.source_namespace + "." + file.second.symbol +
|
||||
"; }\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,11 +183,13 @@ class JsGenerator : public BaseGenerator {
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
auto &struct_def = **it;
|
||||
GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr, imported_files);
|
||||
GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr,
|
||||
imported_files);
|
||||
}
|
||||
}
|
||||
void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) {
|
||||
if (lang_.language == IDLOptions::kTs && parser_.opts.skip_flatbuffers_import) {
|
||||
if (lang_.language == IDLOptions::kTs &&
|
||||
parser_.opts.skip_flatbuffers_import) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -282,13 +292,14 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
std::string &exports = *exports_ptr;
|
||||
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "export namespace " + GetNameSpace(enum_def) + "{\n" + "export enum " + enum_def.name + "{\n";
|
||||
code += "export namespace " + GetNameSpace(enum_def) + "{\n" +
|
||||
"export enum " + enum_def.name + "{\n";
|
||||
} else {
|
||||
if (enum_def.defined_namespace->components.empty()) {
|
||||
code += "var ";
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + enum_def.name + "', " + enum_def.name +
|
||||
");\n";
|
||||
exports += "goog.exportSymbol('" + enum_def.name + "', " +
|
||||
enum_def.name + ");\n";
|
||||
} else {
|
||||
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
|
||||
}
|
||||
@@ -304,12 +315,19 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
}
|
||||
GenDocComment(ev.doc_comment, code_ptr, "", " ");
|
||||
}
|
||||
code += " " + ev.name + ((lang_.language == IDLOptions::kTs) ? ("= ") : (": ")) + NumToString(ev.value);
|
||||
code += " " + ev.name;
|
||||
code += lang_.language == IDLOptions::kTs ? "= " : ": ";
|
||||
code += NumToString(ev.value);
|
||||
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
|
||||
|
||||
if (ev.struct_def) {
|
||||
ReexportDescription desc = { ev.name, GetNameSpace(*ev.struct_def), GetNameSpace(enum_def) };
|
||||
reexports.insert(std::make_pair(ev.struct_def->file, std::move(desc)));
|
||||
if (ev.union_type.struct_def) {
|
||||
ReexportDescription desc = {
|
||||
ev.name,
|
||||
GetNameSpace(*ev.union_type.struct_def),
|
||||
GetNameSpace(enum_def)
|
||||
};
|
||||
reexports.insert(std::make_pair(ev.union_type.struct_def->file,
|
||||
std::move(desc)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +384,8 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
|
||||
if (auto val = value.type.enum_def->ReverseLookup(
|
||||
atoi(value.constant.c_str()), false)) {
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def), value.type.enum_def->file) + "." + val->name;
|
||||
return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def),
|
||||
value.type.enum_def->file) + "." + val->name;
|
||||
} else {
|
||||
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
|
||||
}
|
||||
@@ -448,17 +467,21 @@ static std::string MaybeScale(T value) {
|
||||
}
|
||||
|
||||
static std::string GenFileNamespacePrefix(const std::string &file) {
|
||||
return "NS" + std::to_string(static_cast<unsigned long long>(std::hash<std::string>()(file)));
|
||||
return "NS" + std::to_string(
|
||||
static_cast<unsigned long long>(std::hash<std::string>()(file)));
|
||||
}
|
||||
|
||||
static std::string GenPrefixedImport(const std::string &full_file_name,
|
||||
const std::string &base_file_name) {
|
||||
return "import * as "+ GenFileNamespacePrefix(full_file_name) + " from \"./" + base_file_name + "\";\n";
|
||||
return "import * as "+ GenFileNamespacePrefix(full_file_name) +
|
||||
" from \"./" + base_file_name + "\";\n";
|
||||
}
|
||||
|
||||
// Adds a source-dependent prefix, for of import * statements.
|
||||
std::string GenPrefixedTypeName(const std::string &typeName, const std::string &file) {
|
||||
const auto basename = flatbuffers::StripPath(flatbuffers::StripExtension(file));
|
||||
std::string GenPrefixedTypeName(const std::string &typeName,
|
||||
const std::string &file) {
|
||||
const auto basename =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(file));
|
||||
if (basename == file_name_) {
|
||||
return typeName;
|
||||
}
|
||||
@@ -483,7 +506,8 @@ void GenStructArgs(const StructDef &struct_def,
|
||||
*annotations += "} " + nameprefix + field.name + "\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
*arguments += ", " + nameprefix + field.name + ": " + GenTypeName(field.value.type, true);
|
||||
*arguments += ", " + nameprefix + field.name + ": " +
|
||||
GenTypeName(field.value.type, true);
|
||||
} else {
|
||||
*arguments += ", " + nameprefix + field.name;
|
||||
}
|
||||
@@ -521,7 +545,8 @@ static void GenStructBody(const StructDef &struct_def,
|
||||
}
|
||||
|
||||
// Generate an accessor struct with constructor for a flatbuffers struct.
|
||||
void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_ptr, std::string *exports_ptr,
|
||||
void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
std::string *code_ptr, std::string *exports_ptr,
|
||||
imported_fileset &imported_files) {
|
||||
if (struct_def.generated) return;
|
||||
std::string &code = *code_ptr;
|
||||
@@ -583,7 +608,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
code += " */\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
|
||||
code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name +
|
||||
" {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype.__init = function(i, bb) {\n";
|
||||
}
|
||||
@@ -602,7 +628,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
"@returns {" + object_name + "}");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static getRootAs" + struct_def.name;
|
||||
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" + object_name + " {\n";
|
||||
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" +
|
||||
object_name + " {\n";
|
||||
} else {
|
||||
code += object_name + ".getRootAs" + struct_def.name;
|
||||
code += " = function(bb, obj) {\n";
|
||||
@@ -618,7 +645,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
"@param {flatbuffers.ByteBuffer} bb\n"
|
||||
"@returns {boolean}");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n";
|
||||
code +=
|
||||
"static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n";
|
||||
} else {
|
||||
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
|
||||
}
|
||||
@@ -647,13 +675,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
std::string prefix = MakeCamel(field.name, false) + "(";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += prefix + "):string\n";
|
||||
code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" + GenTypeName(field.value.type, false)+"\n";
|
||||
code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" +
|
||||
GenTypeName(field.value.type, false)+"\n";
|
||||
code += prefix + "optionalEncoding?:any";
|
||||
} else {
|
||||
code += prefix;
|
||||
}
|
||||
if (field.value.type.enum_def) {
|
||||
code += "):" + GenPrefixedTypeName(GenTypeName(field.value.type, false), field.value.type.enum_def->file) + " {\n";
|
||||
code += "):" +
|
||||
GenPrefixedTypeName(GenTypeName(field.value.type, false),
|
||||
field.value.type.enum_def->file) + " {\n";
|
||||
} else {
|
||||
code += "):" + GenTypeName(field.value.type, false) + " {\n";
|
||||
}
|
||||
@@ -733,12 +764,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
std::string prefix = MakeCamel(field.name, false);
|
||||
prefix += "(index: number";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
vectortypename = GenPrefixedTypeName(vectortypename, vectortype.struct_def->file);
|
||||
vectortypename = GenPrefixedTypeName(vectortypename,
|
||||
vectortype.struct_def->file);
|
||||
code += prefix + ", obj?:" + vectortypename;
|
||||
imported_files.insert(vectortype.struct_def->file);
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += prefix + "):string\n";
|
||||
code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" + vectortypename + "\n";
|
||||
code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" +
|
||||
vectortypename + "\n";
|
||||
code += prefix + ",optionalEncoding?:any";
|
||||
} else {
|
||||
code += prefix;
|
||||
@@ -819,31 +852,37 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
|
||||
// Adds the mutable scalar value to the output
|
||||
if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) {
|
||||
std::string annotations = "@param {" + GenTypeName(field.value.type, true) + "} value\n";
|
||||
std::string annotations =
|
||||
"@param {" + GenTypeName(field.value.type, true) + "} value\n";
|
||||
GenDocComment(code_ptr, annotations +
|
||||
"@returns {boolean}");
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string type;
|
||||
if (field.value.type.enum_def) {
|
||||
type = GenPrefixedTypeName(GenTypeName(field.value.type, true), field.value.type.enum_def->file);
|
||||
type = GenPrefixedTypeName(GenTypeName(field.value.type, true),
|
||||
field.value.type.enum_def->file);
|
||||
} else {
|
||||
type = GenTypeName(field.value.type, true);
|
||||
}
|
||||
|
||||
code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype.mutate_" + field.name + " = function(value) {\n";
|
||||
code += object_name + ".prototype.mutate_" + field.name +
|
||||
" = function(value) {\n";
|
||||
}
|
||||
|
||||
code += " var offset = this.bb.__offset(this.bb_pos, " + NumToString(field.value.offset) + ");\n\n";
|
||||
code += " var offset = this.bb.__offset(this.bb_pos, " +
|
||||
NumToString(field.value.offset) + ");\n\n";
|
||||
code += " if (offset === 0) {\n";
|
||||
code += " return false;\n";
|
||||
code += " }\n\n";
|
||||
|
||||
// special case for bools, which are treated as uint8
|
||||
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, ";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL && lang_.language == IDLOptions::kTs) {
|
||||
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) +
|
||||
"(this.bb_pos + offset, ";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL &&
|
||||
lang_.language == IDLOptions::kTs) {
|
||||
code += "+";
|
||||
}
|
||||
|
||||
@@ -885,7 +924,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += MakeCamel(field.name, false);
|
||||
code += "Array():" + GenType(vectorType) + "Array {\n" + offset_prefix;
|
||||
code += "Array():" + GenType(vectorType) + "Array {\n" +
|
||||
offset_prefix;
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Array = function() {\n" + offset_prefix;
|
||||
@@ -958,13 +998,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string argType;
|
||||
if (field.value.type.enum_def) {
|
||||
argType = GenPrefixedTypeName(GenTypeName(field.value.type, true), field.value.type.enum_def->file);
|
||||
argType = GenPrefixedTypeName(GenTypeName(field.value.type, true),
|
||||
field.value.type.enum_def->file);
|
||||
} else {
|
||||
argType = GenTypeName(field.value.type, true);
|
||||
}
|
||||
|
||||
code += "static add" + MakeCamel(field.name);
|
||||
code += "(builder:flatbuffers.Builder, " + argname + ":" + argType + ") {\n";
|
||||
code += "(builder:flatbuffers.Builder, " + argname + ":" + argType +
|
||||
") {\n";
|
||||
} else {
|
||||
code += object_name + ".add" + MakeCamel(field.name);
|
||||
code += " = function(builder, " + argname + ") {\n";
|
||||
@@ -1005,7 +1047,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
if (type == "number[]") {
|
||||
type += " | Uint8Array";
|
||||
}
|
||||
code += "Vector(builder:flatbuffers.Builder, data:" + type+"):flatbuffers.Offset {\n";
|
||||
code += "Vector(builder:flatbuffers.Builder, data:" + type +
|
||||
"):flatbuffers.Offset {\n";
|
||||
code += "if(!data){\n return null\n}\n";
|
||||
} else {
|
||||
code += object_name + ".create" + MakeCamel(field.name);
|
||||
|
||||
@@ -49,7 +49,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
|
||||
// for a single FlatBuffer value into JSON format.
|
||||
// The general case for scalars:
|
||||
template<typename T> bool Print(T val, Type type, int /*indent*/,
|
||||
StructDef * /*union_sd*/,
|
||||
Type */*union_type*/,
|
||||
const IDLOptions &opts,
|
||||
std::string *_text) {
|
||||
std::string &text = *_text;
|
||||
@@ -169,22 +169,16 @@ static bool EscapeString(const String &s, std::string *_text, const IDLOptions&
|
||||
// Specialization of Print above for pointer types.
|
||||
template<> bool Print<const void *>(const void *val,
|
||||
Type type, int indent,
|
||||
StructDef *union_sd,
|
||||
Type *union_type,
|
||||
const IDLOptions &opts,
|
||||
std::string *_text) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_UNION:
|
||||
// If this assert hits, you have an corrupt buffer, a union type field
|
||||
// was not present or was out of range.
|
||||
assert(union_sd);
|
||||
if (!GenStruct(*union_sd,
|
||||
reinterpret_cast<const Table *>(val),
|
||||
indent,
|
||||
opts,
|
||||
_text)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
assert(union_type);
|
||||
return Print<const void *>(val, *union_type, indent, nullptr, opts,
|
||||
_text);
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (!GenStruct(*type.struct_def,
|
||||
reinterpret_cast<const Table *>(val),
|
||||
@@ -236,7 +230,7 @@ template<typename T> static bool GenField(const FieldDef &fd,
|
||||
|
||||
// Generate text for non-scalar field.
|
||||
static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
||||
int indent, StructDef *union_sd,
|
||||
int indent, Type *union_type,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
const void *val = nullptr;
|
||||
if (fixed) {
|
||||
@@ -249,7 +243,7 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
||||
? table->GetStruct<const void *>(fd.value.offset)
|
||||
: table->GetPointer<const void *>(fd.value.offset);
|
||||
}
|
||||
return Print(val, fd.value.type, indent, union_sd, opts, _text);
|
||||
return Print(val, fd.value.type, indent, union_type, opts, _text);
|
||||
}
|
||||
|
||||
// Generate text for a struct or table, values separated by commas, indented,
|
||||
@@ -260,7 +254,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
std::string &text = *_text;
|
||||
text += "{";
|
||||
int fieldout = 0;
|
||||
StructDef *union_sd = nullptr;
|
||||
Type *union_type = nullptr;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end();
|
||||
++it) {
|
||||
@@ -296,7 +290,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
||||
union_sd, opts, _text)) {
|
||||
union_type, opts, _text)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -305,7 +299,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
auto enum_val = fd.value.type.enum_def->ReverseLookup(
|
||||
table->GetField<uint8_t>(fd.value.offset, 0));
|
||||
assert(enum_val);
|
||||
union_sd = enum_val->struct_def;
|
||||
union_type = &enum_val->union_type;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -735,6 +735,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseString(Value &val) {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def) {
|
||||
@@ -784,16 +791,27 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
ECHECK(atot(constant.c_str(), *this, &enum_idx));
|
||||
auto enum_val = val.type.enum_def->ReverseLookup(enum_idx);
|
||||
if (!enum_val) return Error("illegal type id for: " + field->name);
|
||||
ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr));
|
||||
if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant,
|
||||
nullptr));
|
||||
if (enum_val->union_type.struct_def->fixed) {
|
||||
// All BASE_TYPE_UNION values are offsets, so turn this into one.
|
||||
SerializeStruct(*enum_val->union_type.struct_def, val);
|
||||
builder_.ClearOffsets();
|
||||
val.constant = NumToString(builder_.GetSize());
|
||||
}
|
||||
} else if (enum_val->union_type.base_type == BASE_TYPE_STRING) {
|
||||
ECHECK(ParseString(val));
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_STRUCT:
|
||||
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
|
||||
break;
|
||||
case BASE_TYPE_STRING: {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
ECHECK(ParseString(val));
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_VECTOR: {
|
||||
@@ -1290,7 +1308,16 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
|
||||
return Error("enum value already exists: " + value_name);
|
||||
ev.doc_comment = value_comment;
|
||||
if (is_union) {
|
||||
ev.struct_def = LookupCreateStruct(full_name);
|
||||
if (Is(':')) {
|
||||
NEXT();
|
||||
ECHECK(ParseType(ev.union_type));
|
||||
if (ev.union_type.base_type != BASE_TYPE_STRUCT &&
|
||||
ev.union_type.base_type != BASE_TYPE_STRING)
|
||||
return Error("union value type may only be table/struct/string");
|
||||
enum_def.uses_type_aliases = true;
|
||||
} else {
|
||||
ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name));
|
||||
}
|
||||
}
|
||||
if (Is('=')) {
|
||||
NEXT();
|
||||
@@ -1994,6 +2021,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
return Error("type referenced but not defined: " + (*it)->name);
|
||||
}
|
||||
}
|
||||
// This check has to happen here and not earlier, because only now do we
|
||||
// know for sure what the type of these are.
|
||||
for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
|
||||
auto &enum_def = **it;
|
||||
if (enum_def.is_union) {
|
||||
@@ -2001,8 +2030,11 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
val_it != enum_def.vals.vec.end();
|
||||
++val_it) {
|
||||
auto &val = **val_it;
|
||||
if (val.struct_def && val.struct_def->fixed)
|
||||
return Error("only tables can be union elements: " + val.name);
|
||||
if (opts.lang_to_generate != IDLOptions::kCpp &&
|
||||
val.union_type.struct_def && val.union_type.struct_def->fixed)
|
||||
return Error(
|
||||
"only tables can be union elements in the generated language: "
|
||||
+ val.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2145,9 +2177,11 @@ Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
|
||||
return reflection::CreateEnumVal(*builder,
|
||||
builder->CreateString(name),
|
||||
value,
|
||||
struct_def
|
||||
? struct_def->serialized_location
|
||||
: 0);
|
||||
union_type.struct_def
|
||||
? union_type.struct_def->
|
||||
serialized_location
|
||||
: 0,
|
||||
union_type.Serialize(builder));
|
||||
}
|
||||
|
||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||
|
||||
Reference in New Issue
Block a user