/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FLATBUFFERS_IDL_H_ #define FLATBUFFERS_IDL_H_ #include #include #include #include #include "flatbuffers/base.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/flexbuffers.h" #include "flatbuffers/hash.h" #include "flatbuffers/reflection.h" // This file defines the data types representing a parsed IDL (Interface // Definition Language) / schema file. // Limits maximum depth of nested objects. // Prevents stack overflow while parse scheme, or json, or flexbuffer. #if !defined(FLATBUFFERS_MAX_PARSING_DEPTH) # define FLATBUFFERS_MAX_PARSING_DEPTH 64 #endif namespace flatbuffers { // The order of these matters for Is*() functions below. // Additionally, Parser::ParseType assumes bool..string is a contiguous range // of type tokens. // clang-format off #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \ TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \ TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \ TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \ TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \ TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \ TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \ TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \ TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \ TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \ TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \ TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */ #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ TD(STRING, "string", Offset, int, int, StringOffset, int, unused, Int, Offset) \ TD(VECTOR, "", Offset, int, int, VectorOffset, int, unused, Int, Offset) \ TD(STRUCT, "", Offset, int, int, int, int, unused, Int, Offset) \ TD(UNION, "", Offset, int, int, int, int, unused, Int, Offset) #define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \ TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset) // The fields are: // - enum // - FlatBuffers schema type. // - C++ type. // - Java type. // - Go type. // - C# / .Net type. // - Python type. // - Kotlin type. // - Rust type. // using these macros, we can now write code dealing with types just once, e.g. /* switch (type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ RTYPE, KTYPE) \ case BASE_TYPE_ ## ENUM: \ // do something specific to CTYPE here FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD } */ // If not all FLATBUFFERS_GEN_() arguments are necessary for implementation // of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed). // In the above example, only CTYPE is used to generate the code, it can be rewritten: /* switch (type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ // do something specific to CTYPE here FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD } */ #define FLATBUFFERS_GEN_TYPES(TD) \ FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ FLATBUFFERS_GEN_TYPES_POINTER(TD) \ FLATBUFFERS_GEN_TYPE_ARRAY(TD) // Create an enum for all the types above. #ifdef __GNUC__ __extension__ // Stop GCC complaining about trailing comma with -Wpendantic. #endif enum BaseType { #define FLATBUFFERS_TD(ENUM, ...) \ BASE_TYPE_ ## ENUM, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD }; #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ "define largest_scalar_t as " #CTYPE); FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE && t <= BASE_TYPE_DOUBLE; } inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE && t <= BASE_TYPE_ULONG; } inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT || t == BASE_TYPE_DOUBLE; } inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG || t == BASE_TYPE_ULONG; } inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; } inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE && t <= BASE_TYPE_UCHAR; } inline bool IsUnsigned(BaseType t) { return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) || (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) || (t == BASE_TYPE_ULONG); } // clang-format on extern const char *const kTypeNames[]; extern const char kTypeSizes[]; inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; } struct StructDef; struct EnumDef; class Parser; // Represents any type in the IDL, which is a combination of the BaseType // and additional information for vectors/structs_. struct Type { explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr, EnumDef *_ed = nullptr, uint16_t _fixed_length = 0) : base_type(_base_type), element(BASE_TYPE_NONE), struct_def(_sd), enum_def(_ed), fixed_length(_fixed_length) {} bool operator==(const Type &o) const { return base_type == o.base_type && element == o.element && struct_def == o.struct_def && enum_def == o.enum_def; } Type VectorType() const { return Type(element, struct_def, enum_def, fixed_length); } Offset Serialize(FlatBufferBuilder *builder) const; bool Deserialize(const Parser &parser, const reflection::Type *type); BaseType base_type; BaseType element; // only set if t == BASE_TYPE_VECTOR StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE, // or for an integral type derived from an enum. uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY }; // Represents a parsed scalar value, it's type, and field offset. struct Value { Value() : constant("0"), offset(static_cast(~(static_cast(0U)))) {} Type type; std::string constant; voffset_t offset; }; // Helper class that retains the original order of a set of identifiers and // also provides quick lookup. template class SymbolTable { public: ~SymbolTable() { for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; } } bool Add(const std::string &name, T *e) { vec.emplace_back(e); auto it = dict.find(name); if (it != dict.end()) return true; dict[name] = e; return false; } void Move(const std::string &oldname, const std::string &newname) { auto it = dict.find(oldname); if (it != dict.end()) { auto obj = it->second; dict.erase(it); dict[newname] = obj; } else { FLATBUFFERS_ASSERT(false); } } T *Lookup(const std::string &name) const { auto it = dict.find(name); return it == dict.end() ? nullptr : it->second; } public: std::map dict; // quick lookup std::vector vec; // Used to iterate in order of insertion }; // A name space, as set in the schema. struct Namespace { Namespace() : from_table(0) {} // Given a (potentially unqualified) name, return the "fully qualified" name // which has a full namespaced descriptor. // With max_components you can request less than the number of components // the current namespace has. std::string GetFullyQualifiedName(const std::string &name, size_t max_components = 1000) const; std::vector components; size_t from_table; // Part of the namespace corresponds to a message/table. }; inline bool operator<(const Namespace &a, const Namespace &b) { size_t min_size = std::min(a.components.size(), b.components.size()); for (size_t i = 0; i < min_size; ++i) { if (a.components[i] != b.components[i]) return a.components[i] < b.components[i]; } return a.components.size() < b.components.size(); } // Base class for all definition types (fields, structs_, enums_). struct Definition { Definition() : generated(false), defined_namespace(nullptr), serialized_location(0), index(-1), refcount(1), declaration_file(nullptr) {} flatbuffers::Offset< flatbuffers::Vector>> SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const; bool DeserializeAttributes(Parser &parser, const Vector> *attrs); std::string name; std::string file; std::vector doc_comment; SymbolTable attributes; bool generated; // did we already output code for this definition? Namespace *defined_namespace; // Where it was defined. // For use with Serialize() uoffset_t serialized_location; int index; // Inside the vector it is stored. int refcount; const std::string *declaration_file; }; struct FieldDef : public Definition { FieldDef() : deprecated(false), key(false), shared(false), native_inline(false), flexbuffer(false), presence(kDefault), nested_flatbuffer(nullptr), padding(0) {} Offset Serialize(FlatBufferBuilder *builder, uint16_t id, const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::Field *field); bool IsScalarOptional() const { return IsScalar(value.type.base_type) && IsOptional(); } bool IsOptional() const { return presence == kOptional; } bool IsRequired() const { return presence == kRequired; } bool IsDefault() const { return presence == kDefault; } Value value; bool deprecated; // Field is allowed to be present in old data, but can't be. // written in new data nor accessed in new code. 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) // for native tables if field is a struct. bool flexbuffer; // This field contains FlexBuffer data. enum Presence { // Field must always be present. kRequired, // Non-presence should be signalled to and controlled by users. kOptional, // Non-presence is hidden from users. // Implementations may omit writing default values. kDefault, }; Presence static MakeFieldPresence(bool optional, bool required) { FLATBUFFERS_ASSERT(!(required && optional)); // clang-format off return required ? FieldDef::kRequired : optional ? FieldDef::kOptional : FieldDef::kDefault; // clang-format on } Presence presence; StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data. size_t padding; // Bytes to always pad after this field. }; struct StructDef : public Definition { StructDef() : fixed(false), predecl(true), sortbysize(true), has_key(false), minalign(1), bytesize(0) {} void PadLastField(size_t min_align) { auto padding = PaddingBytes(bytesize, min_align); bytesize += padding; if (fields.vec.size()) fields.vec.back()->padding = padding; } Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::Object *object); SymbolTable fields; bool fixed; // If it's struct, not a table. bool predecl; // If it's used before it was defined. bool sortbysize; // Whether fields come in the declaration or size order. bool has_key; // It has a key field. size_t minalign; // What the whole object needs to be aligned to. size_t bytesize; // Size if fixed. flatbuffers::unique_ptr original_location; }; struct EnumDef; struct EnumValBuilder; struct EnumVal { Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; bool Deserialize(const Parser &parser, const reflection::EnumVal *val); uint64_t GetAsUInt64() const { return static_cast(value); } int64_t GetAsInt64() const { return value; } bool IsZero() const { return 0 == value; } bool IsNonZero() const { return !IsZero(); } std::string name; std::vector doc_comment; Type union_type; private: friend EnumDef; friend EnumValBuilder; friend bool operator==(const EnumVal &lhs, const EnumVal &rhs); EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {} EnumVal() : value(0) {} int64_t value; }; struct EnumDef : public Definition { EnumDef() : is_union(false), uses_multiple_type_instances(false) {} Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::Enum *values); template void ChangeEnumValue(EnumVal *ev, T new_val); void SortByValue(); void RemoveDuplicates(); std::string AllFlags() const; const EnumVal *MinValue() const; const EnumVal *MaxValue() const; // Returns the number of integer steps from v1 to v2. uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const; // Returns the number of integer steps from Min to Max. uint64_t Distance() const { return Distance(MinValue(), MaxValue()); } EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = false) const; EnumVal *FindByValue(const std::string &constant) const; std::string ToString(const EnumVal &ev) const { return IsUInt64() ? NumToString(ev.GetAsUInt64()) : NumToString(ev.GetAsInt64()); } size_t size() const { return vals.vec.size(); } const std::vector &Vals() const { return vals.vec; } const EnumVal *Lookup(const std::string &enum_name) const { return vals.Lookup(enum_name); } bool is_union; // Type is a union which uses type aliases where at least one type is // available under two different names. bool uses_multiple_type_instances; Type underlying_type; private: bool IsUInt64() const { return (BASE_TYPE_ULONG == underlying_type.base_type); } friend EnumValBuilder; SymbolTable vals; }; inline bool IsString(const Type &type) { return type.base_type == BASE_TYPE_STRING; } inline bool IsStruct(const Type &type) { return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; } inline bool IsUnion(const Type &type) { return type.enum_def != nullptr && type.enum_def->is_union; } inline bool IsUnionType(const Type &type) { return IsUnion(type) && IsInteger(type.base_type); } inline bool IsVector(const Type &type) { return type.base_type == BASE_TYPE_VECTOR; } inline bool IsArray(const Type &type) { return type.base_type == BASE_TYPE_ARRAY; } inline bool IsSeries(const Type &type) { return IsVector(type) || IsArray(type); } inline bool IsEnum(const Type &type) { return type.enum_def != nullptr && IsInteger(type.base_type); } inline size_t InlineSize(const Type &type) { return IsStruct(type) ? type.struct_def->bytesize : (IsArray(type) ? InlineSize(type.VectorType()) * type.fixed_length : SizeOf(type.base_type)); } inline size_t InlineAlignment(const Type &type) { if (IsStruct(type)) { return type.struct_def->minalign; } else if (IsArray(type)) { return IsStruct(type.VectorType()) ? type.struct_def->minalign : SizeOf(type.element); } else { return SizeOf(type.base_type); } } inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) { return lhs.value == rhs.value; } inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) { return !(lhs == rhs); } inline bool EqualByName(const Type &a, const Type &b) { return a.base_type == b.base_type && a.element == b.element && (a.struct_def == b.struct_def || a.struct_def->name == b.struct_def->name) && (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name); } struct RPCCall : public Definition { Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::RPCCall *call); StructDef *request, *response; }; struct ServiceDef : public Definition { Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::Service *service); SymbolTable calls; }; struct IncludedFile { // The name of the schema file being included, as defined in the .fbs file. // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this // value is "foo/bar/baz.fbs"). std::string schema_name; // The filename of where the included file was found, after searching the // relative paths plus any other paths included with `flatc -I ...`. Note, // while this is sometimes the same as schema_name, it is not always, since it // can be defined relative to where flatc was invoked. std::string filename; }; // Since IncludedFile is contained within a std::set, need to provide ordering. inline bool operator<(const IncludedFile &a, const IncludedFile &b) { return a.filename < b.filename; } // Container of options that may apply to any of the source/text generators. struct IDLOptions { // field case style options for C++ enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower }; bool gen_jvmstatic; // Use flexbuffers instead for binary and text generation bool use_flexbuffers; bool strict_json; bool output_default_scalars_in_json; int indent_step; bool output_enum_identifiers; bool prefixed_enums; bool scoped_enums; bool swift_implementation_only; bool include_dependence_headers; bool mutable_buffer; bool one_file; bool proto_mode; bool proto_oneof_union; bool generate_all; bool skip_unexpected_fields_in_json; bool generate_name_strings; bool generate_object_based_api; bool gen_compare; std::string cpp_object_api_pointer_type; std::string cpp_object_api_string_type; bool cpp_object_api_string_flexible_constructor; CaseStyle cpp_object_api_field_case_style; bool cpp_direct_copy; bool gen_nullable; bool java_checkerframework; bool gen_generated; bool gen_json_coders; std::string object_prefix; std::string object_suffix; bool union_value_namespacing; bool allow_non_utf8; bool natural_utf8; std::string include_prefix; bool keep_prefix; bool binary_schema_comments; bool binary_schema_builtins; bool binary_schema_gen_embed; std::string go_import; std::string go_namespace; bool protobuf_ascii_alike; bool size_prefixed; std::string root_type; bool force_defaults; bool java_primitive_has_method; bool cs_gen_json_serializer; std::vector cpp_includes; std::string cpp_std; bool cpp_static_reflection; std::string proto_namespace_suffix; std::string filename_suffix; std::string filename_extension; bool no_warnings; bool warnings_as_errors; std::string project_root; bool cs_global_alias; bool json_nested_flatbuffers; bool json_nested_flexbuffers; bool json_nested_legacy_flatbuffers; bool ts_flat_file; bool no_leak_private_annotations; // Possible options for the more general generator below. enum Language { kJava = 1 << 0, kCSharp = 1 << 1, kGo = 1 << 2, kCpp = 1 << 3, kPython = 1 << 5, kPhp = 1 << 6, kJson = 1 << 7, kBinary = 1 << 8, kTs = 1 << 9, kJsonSchema = 1 << 10, kDart = 1 << 11, kLua = 1 << 12, kLobster = 1 << 13, kRust = 1 << 14, kKotlin = 1 << 15, kSwift = 1 << 16, kMAX }; enum MiniReflect { kNone, kTypes, kTypesAndNames }; MiniReflect mini_reflect; // If set, require all fields in a table to be explicitly numbered. bool require_explicit_ids; // If set, implement serde::Serialize for generated Rust types bool rust_serialize; // If set, generate rust types in individual files with a root module file. bool rust_module_root_file; // The corresponding language bit will be set if a language is included // for code generation. unsigned long lang_to_generate; // If set (default behavior), empty string fields will be set to nullptr to // make the flatbuffer more compact. bool set_empty_strings_to_null; // If set (default behavior), empty vector fields will be set to nullptr to // make the flatbuffer more compact. bool set_empty_vectors_to_null; IDLOptions() : gen_jvmstatic(false), use_flexbuffers(false), strict_json(false), output_default_scalars_in_json(false), indent_step(2), output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false), swift_implementation_only(false), include_dependence_headers(true), mutable_buffer(false), one_file(false), proto_mode(false), proto_oneof_union(false), generate_all(false), skip_unexpected_fields_in_json(false), generate_name_strings(false), generate_object_based_api(false), gen_compare(false), cpp_object_api_pointer_type("std::unique_ptr"), cpp_object_api_string_flexible_constructor(false), cpp_object_api_field_case_style(CaseStyle_Unchanged), cpp_direct_copy(true), gen_nullable(false), java_checkerframework(false), gen_generated(false), gen_json_coders(false), object_suffix("T"), union_value_namespacing(true), allow_non_utf8(false), natural_utf8(false), keep_prefix(false), binary_schema_comments(false), binary_schema_builtins(false), binary_schema_gen_embed(false), protobuf_ascii_alike(false), size_prefixed(false), force_defaults(false), java_primitive_has_method(false), cs_gen_json_serializer(false), cpp_static_reflection(false), filename_suffix("_generated"), filename_extension(), no_warnings(false), warnings_as_errors(false), project_root(""), cs_global_alias(false), json_nested_flatbuffers(true), json_nested_flexbuffers(true), json_nested_legacy_flatbuffers(false), ts_flat_file(false), no_leak_private_annotations(false), mini_reflect(IDLOptions::kNone), require_explicit_ids(false), rust_serialize(false), rust_module_root_file(false), lang_to_generate(0), set_empty_strings_to_null(true), set_empty_vectors_to_null(true) {} }; // This encapsulates where the parser is in the current source file. struct ParserState { ParserState() : cursor_(nullptr), line_start_(nullptr), line_(0), token_(-1), attr_is_trivial_ascii_string_(true) {} protected: void ResetState(const char *source) { cursor_ = source; line_ = 0; MarkNewLine(); } void MarkNewLine() { line_start_ = cursor_; line_ += 1; } int64_t CursorPosition() const { FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_); return static_cast(cursor_ - line_start_); } const char *cursor_; const char *line_start_; int line_; // the current line being parsed int token_; // Flag: text in attribute_ is true ASCII string without escape // sequences. Only printable ASCII (without [\t\r\n]). // Used for number-in-string (and base64 string in future). bool attr_is_trivial_ascii_string_; std::string attribute_; std::vector doc_comment_; }; // A way to make error propagation less error prone by requiring values to be // checked. // Once you create a value of this type you must either: // - Call Check() on it. // - Copy or assign it to another value. // Failure to do so leads to an assert. // This guarantees that this as return value cannot be ignored. class CheckedError { public: explicit CheckedError(bool error) : is_error_(error), has_been_checked_(false) {} CheckedError &operator=(const CheckedError &other) { is_error_ = other.is_error_; has_been_checked_ = false; other.has_been_checked_ = true; return *this; } CheckedError(const CheckedError &other) { *this = other; // Use assignment operator. } ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); } bool Check() { has_been_checked_ = true; return is_error_; } private: bool is_error_; mutable bool has_been_checked_; }; // Additionally, in GCC we can get these errors statically, for additional // assurance: // clang-format off #ifdef __GNUC__ #define FLATBUFFERS_CHECKED_ERROR CheckedError \ __attribute__((warn_unused_result)) #else #define FLATBUFFERS_CHECKED_ERROR CheckedError #endif // clang-format on class Parser : public ParserState { public: explicit Parser(const IDLOptions &options = IDLOptions()) : current_namespace_(nullptr), empty_namespace_(nullptr), flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL), root_struct_def_(nullptr), opts(options), uses_flexbuffers_(false), has_warning_(false), advanced_features_(0), source_(nullptr), anonymous_counter_(0), parse_depth_counter_(0) { if (opts.force_defaults) { builder_.ForceDefaults(true); } // Start out with the empty namespace being current. empty_namespace_ = new Namespace(); namespaces_.push_back(empty_namespace_); current_namespace_ = empty_namespace_; known_attributes_["deprecated"] = true; known_attributes_["required"] = true; known_attributes_["key"] = true; known_attributes_["shared"] = true; known_attributes_["hash"] = true; known_attributes_["id"] = true; known_attributes_["force_align"] = true; known_attributes_["bit_flags"] = true; known_attributes_["original_order"] = true; known_attributes_["nested_flatbuffer"] = true; known_attributes_["csharp_partial"] = true; known_attributes_["streaming"] = true; known_attributes_["idempotent"] = true; known_attributes_["cpp_type"] = true; known_attributes_["cpp_ptr_type"] = true; known_attributes_["cpp_ptr_type_get"] = true; known_attributes_["cpp_str_type"] = true; known_attributes_["cpp_str_flex_ctor"] = true; known_attributes_["native_inline"] = true; known_attributes_["native_custom_alloc"] = true; known_attributes_["native_type"] = true; known_attributes_["native_type_pack_name"] = true; known_attributes_["native_default"] = true; known_attributes_["flexbuffer"] = true; known_attributes_["private"] = true; } ~Parser() { for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { delete *it; } } // Parse the string containing either schema or JSON data, which will // populate the SymbolTable's or the FlatBufferBuilder above. // include_paths is used to resolve any include statements, and typically // should at least include the project path (where you loaded source_ from). // include_paths must be nullptr terminated if specified. // If include_paths is nullptr, it will attempt to load from the current // directory. // If the source was loaded from a file and isn't an include file, // supply its name in source_filename. // All paths specified in this call must be in posix format, if you accept // paths from user input, please call PosixPath on them first. bool Parse(const char *_source, const char **include_paths = nullptr, const char *source_filename = nullptr); bool ParseJson(const char *json, const char *json_filename = nullptr); // Set the root type. May override the one set in the schema. bool SetRootType(const char *name); // Mark all definitions as already having code generated. void MarkGenerated(); // Get the files recursively included by the given file. The returned // container will have at least the given file. std::set GetIncludedFilesRecursive( const std::string &file_name) const; // Fills builder_ with a binary version of the schema parsed. // See reflection/reflection.fbs void Serialize(); // Deserialize a schema buffer bool Deserialize(const uint8_t *buf, const size_t size); // Fills internal structure as if the schema passed had been loaded by parsing // with Parse except that included filenames will not be populated. bool Deserialize(const reflection::Schema *schema); Type *DeserializeType(const reflection::Type *type); // Checks that the schema represented by this parser is a safe evolution // of the schema provided. Returns non-empty error on any problems. std::string ConformTo(const Parser &base); // Similar to Parse(), but now only accepts JSON to be parsed into a // FlexBuffer. bool ParseFlexBuffer(const char *source, const char *source_filename, flexbuffers::Builder *builder); StructDef *LookupStruct(const std::string &id) const; StructDef *LookupStructThruParentNamespaces(const std::string &id) const; std::string UnqualifiedName(const std::string &fullQualifiedName); FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars // in a schema. // @param opts Options used to parce a schema and generate code. static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts); // Get the set of included files that are directly referenced by the file // being parsed. This does not include files that are transitively included by // others includes. std::vector GetIncludedFiles() const; private: class ParseDepthGuard; void Message(const std::string &msg); void Warning(const std::string &msg); FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val); FLATBUFFERS_CHECKED_ERROR Next(); FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark(); bool Is(int t) const; bool IsIdent(const char *id) const; FLATBUFFERS_CHECKED_ERROR Expect(int t); std::string TokenToStringId(int t) const; EnumDef *LookupEnum(const std::string &id); FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id, std::string *last); FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type); FLATBUFFERS_CHECKED_ERROR ParseType(Type &type); FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def, const std::string &name, const Type &type, FieldDef **dest); FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def); FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling); FLATBUFFERS_CHECKED_ERROR ParseComma(); FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, size_t parent_fieldn, const StructDef *parent_struct_def, uoffset_t count, bool inside_vector = false); template FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, const StructDef *struct_def, F body); FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, std::string *value, uoffset_t *ovalue); void SerializeStruct(const StructDef &struct_def, const Value &val); void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def, const Value &val); template FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body); FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, FieldDef *field, size_t fieldn); FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array); FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer( Value &val, FieldDef *field, size_t fieldn, const StructDef *parent_struct_def); FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable *attributes); FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e, BaseType req, bool *destmatch); FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field); FLATBUFFERS_CHECKED_ERROR TokenError(); FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now); FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e); FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result); StructDef *LookupCreateStruct(const std::string &name, bool create_if_new = true, bool definition = false); FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest, const char *filename); FLATBUFFERS_CHECKED_ERROR ParseNamespace(); FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name, StructDef **dest); FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union, EnumDef **dest); FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename); FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename); FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, bool isextend, bool inside_oneof); FLATBUFFERS_CHECKED_ERROR ParseProtoOption(); FLATBUFFERS_CHECKED_ERROR ParseProtoKey(); FLATBUFFERS_CHECKED_ERROR ParseProtoDecl(); FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent(); FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type); FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue(); FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant( flexbuffers::Builder *builder); FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder); FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source, const char *source_filename); FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source, const char **include_paths, const char *source_filename); FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak(); FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields( const Definition &def, const Definition &value_type); FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source, const char **include_paths, const char *source_filename, const char *include_filename); FLATBUFFERS_CHECKED_ERROR DoParseJson(); FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector &fields, StructDef *struct_def, const char *suffix, BaseType baseType); FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute( const std::string &align_constant, size_t min_align, size_t *align); bool SupportsAdvancedUnionFeatures() const; bool SupportsAdvancedArrayFeatures() const; bool SupportsOptionalScalars() const; bool SupportsDefaultVectorsAndStrings() const; Namespace *UniqueNamespace(Namespace *ns); FLATBUFFERS_CHECKED_ERROR RecurseError(); template CheckedError Recurse(F f); const std::string &GetPooledString(const std::string &s) const; public: SymbolTable types_; SymbolTable structs_; SymbolTable enums_; SymbolTable services_; std::vector namespaces_; Namespace *current_namespace_; Namespace *empty_namespace_; std::string error_; // User readable error_ if Parse() == false FlatBufferBuilder builder_; // any data contained in the file flexbuffers::Builder flex_builder_; flexbuffers::Reference flex_root_; StructDef *root_struct_def_; std::string file_identifier_; std::string file_extension_; std::map included_files_; std::map> files_included_per_file_; std::vector native_included_files_; std::map known_attributes_; IDLOptions opts; bool uses_flexbuffers_; bool has_warning_; uint64_t advanced_features_; std::string file_being_parsed_; private: const char *source_; std::vector> field_stack_; // TODO(cneo): Refactor parser to use string_cache more often to save // on memory usage. mutable std::set string_cache_; int anonymous_counter_; int parse_depth_counter_; // stack-overflow guard }; // Utility functions for multiple generators: // Generate text (JSON) from a given FlatBuffer, and a given Parser // object that has been populated with the corresponding schema. // If ident_step is 0, no indentation will be generated. Additionally, // if it is less than 0, no linefeeds will be generated either. // See idl_gen_text.cpp. // strict_json adds "quotes" around field names if true. // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8 // byte arrays in String values), returns false. extern bool GenerateTextFromTable(const Parser &parser, const void *table, const std::string &tablename, std::string *text); extern bool GenerateText(const Parser &parser, const void *flatbuffer, std::string *text); extern bool GenerateTextFile(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Json schema to string // See idl_gen_json_schema.cpp. extern bool GenerateJsonSchema(const Parser &parser, std::string *json); // Generate binary files from a given FlatBuffer, and a given Parser // object that has been populated with the corresponding schema. // See code_generators.cpp. extern bool GenerateBinary(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a C++ header from the definitions in the Parser object. // See idl_gen_cpp. extern bool GenerateCPP(const Parser &parser, const std::string &path, const std::string &file_name); // Generate C# files from the definitions in the Parser object. // See idl_gen_csharp.cpp. extern bool GenerateCSharp(const Parser &parser, const std::string &path, const std::string &file_name); extern bool GenerateDart(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Java files from the definitions in the Parser object. // See idl_gen_java.cpp. extern bool GenerateJava(const Parser &parser, const std::string &path, const std::string &file_name); // Generate JavaScript or TypeScript code from the definitions in the Parser // object. See idl_gen_js. extern bool GenerateTS(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Go files from the definitions in the Parser object. // See idl_gen_go.cpp. extern bool GenerateGo(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Php code from the definitions in the Parser object. // See idl_gen_php. extern bool GeneratePhp(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Python files from the definitions in the Parser object. // See idl_gen_python.cpp. extern bool GeneratePython(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Lobster files from the definitions in the Parser object. // See idl_gen_lobster.cpp. extern bool GenerateLobster(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Lua files from the definitions in the Parser object. // See idl_gen_lua.cpp. extern bool GenerateLua(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Rust files from the definitions in the Parser object. // See idl_gen_rust.cpp. extern bool GenerateRust(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Json schema file // See idl_gen_json_schema.cpp. extern bool GenerateJsonSchema(const Parser &parser, const std::string &path, const std::string &file_name); extern bool GenerateKotlin(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Swift classes. // See idl_gen_swift.cpp extern bool GenerateSwift(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a schema file from the internal representation, useful after // parsing a .proto schema. extern std::string GenerateFBS(const Parser &parser, const std::string &file_name); extern bool GenerateFBS(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated TypeScript code. // See idl_gen_ts.cpp. extern std::string TSMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated C++ header. // See idl_gen_cpp.cpp. extern std::string CPPMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated Dart code // see idl_gen_dart.cpp extern std::string DartMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated Rust code. // See idl_gen_rust.cpp. extern std::string RustMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for generated Java or C# files. // See code_generators.cpp. extern std::string CSharpMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); extern std::string JavaMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated text (JSON) files. // See idl_gen_text.cpp. extern std::string TextMakeRule(const Parser &parser, const std::string &path, const std::string &file_names); // Generate a make rule for the generated binary files. // See code_generators.cpp. extern std::string BinaryMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Cpp interfaces. // See idl_gen_grpc.cpp. bool GenerateCppGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Go interfaces. // See idl_gen_grpc.cpp. bool GenerateGoGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Java classes. // See idl_gen_grpc.cpp bool GenerateJavaGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Python interfaces. // See idl_gen_grpc.cpp. bool GeneratePythonGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Swift interfaces. // See idl_gen_grpc.cpp. extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path, const std::string &file_name); extern bool GenerateTSGRPC(const Parser &parser, const std::string &path, const std::string &file_name); extern bool GenerateRustModuleRootFile(const Parser &parser, const std::string &path); } // namespace flatbuffers #endif // FLATBUFFERS_IDL_H_