1 /*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef FLATBUFFERS_IDL_H_
18 #define FLATBUFFERS_IDL_H_
19
20 #include <algorithm>
21 #include <functional>
22 #include <map>
23 #include <memory>
24 #include <stack>
25
26 #include "flatbuffers/base.h"
27 #include "flatbuffers/flatbuffers.h"
28 #include "flatbuffers/flexbuffers.h"
29 #include "flatbuffers/hash.h"
30 #include "flatbuffers/reflection.h"
31
32 // This file defines the data types representing a parsed IDL (Interface
33 // Definition Language) / schema file.
34
35 // Limits maximum depth of nested objects.
36 // Prevents stack overflow while parse scheme, or json, or flexbuffer.
37 #if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
38 # define FLATBUFFERS_MAX_PARSING_DEPTH 64
39 #endif
40
41 namespace flatbuffers {
42
43 // The order of these matters for Is*() functions below.
44 // Additionally, Parser::ParseType assumes bool..string is a contiguous range
45 // of type tokens.
46 // clang-format off
47 #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
48 TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 0) \
49 TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 1) /* begin scalar/int */ \
50 TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool, 2) \
51 TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8, 3) \
52 TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 4) \
53 TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16, 5) \
54 TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16, 6) \
55 TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32, 7) \
56 TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32, 8) \
57 TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64, 9) \
58 TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64, 10) /* end int */ \
59 TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32, 11) /* begin float */ \
60 TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double, 12) /* end float/scalar */
61 #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
62 TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>, 13) \
63 TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 14) \
64 TD(VECTOR64, "", Offset64<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 18) \
65 TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 15) \
66 TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 16)
67 #define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
68 TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>, 17)
69 // The fields are:
70 // - enum
71 // - FlatBuffers schema type.
72 // - C++ type.
73 // - Java type.
74 // - Go type.
75 // - C# / .Net type.
76 // - Python type.
77 // - Kotlin type.
78 // - Rust type.
79 // - Swift type.
80 // - enum value (matches the reflected values)
81
82 // using these macros, we can now write code dealing with types just once, e.g.
83
84 /*
85 switch (type) {
86 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
87 RTYPE, KTYPE, STYPE, ...) \
88 case BASE_TYPE_ ## ENUM: \
89 // do something specific to CTYPE here
90 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
91 #undef FLATBUFFERS_TD
92 }
93 */
94
95 // If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
96 // of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
97 // In the above example, only CTYPE is used to generate the code, it can be rewritten:
98
99 /*
100 switch (type) {
101 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
102 case BASE_TYPE_ ## ENUM: \
103 // do something specific to CTYPE here
104 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
105 #undef FLATBUFFERS_TD
106 }
107 */
108
109 #define FLATBUFFERS_GEN_TYPES(TD) \
110 FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
111 FLATBUFFERS_GEN_TYPES_POINTER(TD) \
112 FLATBUFFERS_GEN_TYPE_ARRAY(TD)
113
114 // Create an enum for all the types above.
115 #ifdef __GNUC__
116 __extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
117 #endif
118 enum BaseType {
119 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
120 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE, ENUM_VALUE) \
121 BASE_TYPE_ ## ENUM = ENUM_VALUE,
122 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
123 #undef FLATBUFFERS_TD
124 };
125
126 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
127 static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
128 "define largest_scalar_t as " #CTYPE);
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)129 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
130 #undef FLATBUFFERS_TD
131
132 inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
133 t <= BASE_TYPE_DOUBLE; }
IsInteger(BaseType t)134 inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
135 t <= BASE_TYPE_ULONG; }
IsFloat(BaseType t)136 inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
137 t == BASE_TYPE_DOUBLE; }
IsLong(BaseType t)138 inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
139 t == BASE_TYPE_ULONG; }
IsBool(BaseType t)140 inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
IsOneByte(BaseType t)141 inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
142 t <= BASE_TYPE_UCHAR; }
IsVector(BaseType t)143 inline bool IsVector (BaseType t) { return t == BASE_TYPE_VECTOR ||
144 t == BASE_TYPE_VECTOR64; }
145
IsUnsigned(BaseType t)146 inline bool IsUnsigned(BaseType t) {
147 return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
148 (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
149 (t == BASE_TYPE_ULONG);
150 }
151
SizeOf(const BaseType t)152 inline size_t SizeOf(const BaseType t) {
153 switch (t) {
154 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
155 case BASE_TYPE_##ENUM: return sizeof(CTYPE);
156 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
157 #undef FLATBUFFERS_TD
158 default: FLATBUFFERS_ASSERT(0);
159 }
160 return 0;
161 }
162
TypeName(const BaseType t)163 inline const char* TypeName(const BaseType t) {
164 switch (t) {
165 #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
166 case BASE_TYPE_##ENUM: return IDLTYPE;
167 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
168 #undef FLATBUFFERS_TD
169 default: FLATBUFFERS_ASSERT(0);
170 }
171 return nullptr;
172 }
173
StringOf(const BaseType t)174 inline const char* StringOf(const BaseType t) {
175 switch (t) {
176 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
177 case BASE_TYPE_##ENUM: return #CTYPE;
178 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
179 #undef FLATBUFFERS_TD
180 default: FLATBUFFERS_ASSERT(0);
181 }
182 return "";
183 }
184
185 // clang-format on
186
187 struct StructDef;
188 struct EnumDef;
189 class Parser;
190
191 // Represents any type in the IDL, which is a combination of the BaseType
192 // and additional information for vectors/structs_.
193 struct Type {
194 explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
195 EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
base_typeType196 : base_type(_base_type),
197 element(BASE_TYPE_NONE),
198 struct_def(_sd),
199 enum_def(_ed),
200 fixed_length(_fixed_length) {}
201
202 bool operator==(const Type &o) const {
203 return base_type == o.base_type && element == o.element &&
204 struct_def == o.struct_def && enum_def == o.enum_def;
205 }
206
VectorTypeType207 Type VectorType() const {
208 return Type(element, struct_def, enum_def, fixed_length);
209 }
210
211 Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
212
213 bool Deserialize(const Parser &parser, const reflection::Type *type);
214
215 BaseType base_type;
216 BaseType element; // only set if t == BASE_TYPE_VECTOR or
217 // BASE_TYPE_VECTOR64
218 StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
219 EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
220 // or for an integral type derived from an enum.
221 uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
222 };
223
224 // Represents a parsed scalar value, it's type, and field offset.
225 struct Value {
ValueValue226 Value()
227 : constant("0"),
228 offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
229 Type type;
230 std::string constant;
231 voffset_t offset;
232 };
233
234 // Helper class that retains the original order of a set of identifiers and
235 // also provides quick lookup.
236 template<typename T> class SymbolTable {
237 public:
~SymbolTable()238 ~SymbolTable() {
239 for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
240 }
241
Add(const std::string & name,T * e)242 bool Add(const std::string &name, T *e) {
243 vec.emplace_back(e);
244 auto it = dict.find(name);
245 if (it != dict.end()) return true;
246 dict[name] = e;
247 return false;
248 }
249
Move(const std::string & oldname,const std::string & newname)250 void Move(const std::string &oldname, const std::string &newname) {
251 auto it = dict.find(oldname);
252 if (it != dict.end()) {
253 auto obj = it->second;
254 dict.erase(it);
255 dict[newname] = obj;
256 } else {
257 FLATBUFFERS_ASSERT(false);
258 }
259 }
260
Lookup(const std::string & name)261 T *Lookup(const std::string &name) const {
262 auto it = dict.find(name);
263 return it == dict.end() ? nullptr : it->second;
264 }
265
266 public:
267 std::map<std::string, T *> dict; // quick lookup
268 std::vector<T *> vec; // Used to iterate in order of insertion
269 };
270
271 // A name space, as set in the schema.
272 struct Namespace {
NamespaceNamespace273 Namespace() : from_table(0) {}
274
275 // Given a (potentially unqualified) name, return the "fully qualified" name
276 // which has a full namespaced descriptor.
277 // With max_components you can request less than the number of components
278 // the current namespace has.
279 std::string GetFullyQualifiedName(const std::string &name,
280 size_t max_components = 1000) const;
281
282 std::vector<std::string> components;
283 size_t from_table; // Part of the namespace corresponds to a message/table.
284 };
285
286 inline bool operator<(const Namespace &a, const Namespace &b) {
287 size_t min_size = std::min(a.components.size(), b.components.size());
288 for (size_t i = 0; i < min_size; ++i) {
289 if (a.components[i] != b.components[i])
290 return a.components[i] < b.components[i];
291 }
292 return a.components.size() < b.components.size();
293 }
294
295 // Base class for all definition types (fields, structs_, enums_).
296 struct Definition {
DefinitionDefinition297 Definition()
298 : generated(false),
299 defined_namespace(nullptr),
300 serialized_location(0),
301 index(-1),
302 refcount(1),
303 declaration_file(nullptr) {}
304
305 flatbuffers::Offset<
306 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
307 SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
308
309 bool DeserializeAttributes(Parser &parser,
310 const Vector<Offset<reflection::KeyValue>> *attrs);
311
312 std::string name;
313 std::string file;
314 std::vector<std::string> doc_comment;
315 SymbolTable<Value> attributes;
316 bool generated; // did we already output code for this definition?
317 Namespace *defined_namespace; // Where it was defined.
318
319 // For use with Serialize()
320 uoffset_t serialized_location;
321 int index; // Inside the vector it is stored.
322 int refcount;
323 const std::string *declaration_file;
324 };
325
326 struct FieldDef : public Definition {
FieldDefFieldDef327 FieldDef()
328 : deprecated(false),
329 key(false),
330 shared(false),
331 native_inline(false),
332 flexbuffer(false),
333 offset64(false),
334 presence(kDefault),
335 nested_flatbuffer(nullptr),
336 padding(0),
337 sibling_union_field(nullptr) {}
338
339 Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
340 const Parser &parser) const;
341
342 bool Deserialize(Parser &parser, const reflection::Field *field);
343
IsScalarOptionalFieldDef344 bool IsScalarOptional() const {
345 return IsScalar() && IsOptional();
346 }
IsScalarFieldDef347 bool IsScalar() const {
348 return ::flatbuffers::IsScalar(value.type.base_type);
349 }
IsOptionalFieldDef350 bool IsOptional() const { return presence == kOptional; }
IsRequiredFieldDef351 bool IsRequired() const { return presence == kRequired; }
IsDefaultFieldDef352 bool IsDefault() const { return presence == kDefault; }
353
354 Value value;
355 bool deprecated; // Field is allowed to be present in old data, but can't be.
356 // written in new data nor accessed in new code.
357 bool key; // Field functions as a key for creating sorted vectors.
358 bool shared; // Field will be using string pooling (i.e. CreateSharedString)
359 // as default serialization behavior if field is a string.
360 bool native_inline; // Field will be defined inline (instead of as a pointer)
361 // for native tables if field is a struct.
362 bool flexbuffer; // This field contains FlexBuffer data.
363 bool offset64; // If the field uses 64-bit offsets.
364
365 enum Presence {
366 // Field must always be present.
367 kRequired,
368 // Non-presence should be signalled to and controlled by users.
369 kOptional,
370 // Non-presence is hidden from users.
371 // Implementations may omit writing default values.
372 kDefault,
373 };
MakeFieldPresenceFieldDef374 Presence static MakeFieldPresence(bool optional, bool required) {
375 FLATBUFFERS_ASSERT(!(required && optional));
376 // clang-format off
377 return required ? FieldDef::kRequired
378 : optional ? FieldDef::kOptional
379 : FieldDef::kDefault;
380 // clang-format on
381 }
382 Presence presence;
383
384 StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
385 size_t padding; // Bytes to always pad after this field.
386
387 // sibling_union_field is always set to nullptr. The only exception is
388 // when FieldDef is a union field or an union type field. Therefore,
389 // sibling_union_field on a union field points to the union type field
390 // and vice-versa.
391 FieldDef *sibling_union_field;
392 };
393
394 struct StructDef : public Definition {
StructDefStructDef395 StructDef()
396 : fixed(false),
397 predecl(true),
398 sortbysize(true),
399 has_key(false),
400 minalign(1),
401 bytesize(0) {}
402
PadLastFieldStructDef403 void PadLastField(size_t min_align) {
404 auto padding = PaddingBytes(bytesize, min_align);
405 bytesize += padding;
406 if (fields.vec.size()) fields.vec.back()->padding = padding;
407 }
408
409 Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
410 const Parser &parser) const;
411
412 bool Deserialize(Parser &parser, const reflection::Object *object);
413
414 SymbolTable<FieldDef> fields;
415
416 bool fixed; // If it's struct, not a table.
417 bool predecl; // If it's used before it was defined.
418 bool sortbysize; // Whether fields come in the declaration or size order.
419 bool has_key; // It has a key field.
420 size_t minalign; // What the whole object needs to be aligned to.
421 size_t bytesize; // Size if fixed.
422
423 flatbuffers::unique_ptr<std::string> original_location;
424 std::vector<voffset_t> reserved_ids;
425 };
426
427 struct EnumDef;
428 struct EnumValBuilder;
429
430 struct EnumVal {
431 Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
432 const Parser &parser) const;
433
434 bool Deserialize(Parser &parser, const reflection::EnumVal *val);
435
436 flatbuffers::Offset<
437 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
438 SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
439
440 bool DeserializeAttributes(Parser &parser,
441 const Vector<Offset<reflection::KeyValue>> *attrs);
442
GetAsUInt64EnumVal443 uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
GetAsInt64EnumVal444 int64_t GetAsInt64() const { return value; }
IsZeroEnumVal445 bool IsZero() const { return 0 == value; }
IsNonZeroEnumVal446 bool IsNonZero() const { return !IsZero(); }
447
448 std::string name;
449 std::vector<std::string> doc_comment;
450 Type union_type;
451 SymbolTable<Value> attributes;
452
453 private:
454 friend EnumDef;
455 friend EnumValBuilder;
456 friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
457
EnumValEnumVal458 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumValEnumVal459 EnumVal() : value(0) {}
460
461 int64_t value;
462 };
463
464 struct EnumDef : public Definition {
EnumDefEnumDef465 EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
466
467 Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
468 const Parser &parser) const;
469
470 bool Deserialize(Parser &parser, const reflection::Enum *values);
471
472 template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
473 void SortByValue();
474 void RemoveDuplicates();
475
476 std::string AllFlags() const;
477 const EnumVal *MinValue() const;
478 const EnumVal *MaxValue() const;
479 // Returns the number of integer steps from v1 to v2.
480 uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
481 // Returns the number of integer steps from Min to Max.
DistanceEnumDef482 uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
483
484 EnumVal *ReverseLookup(int64_t enum_idx,
485 bool skip_union_default = false) const;
486 EnumVal *FindByValue(const std::string &constant) const;
487
ToStringEnumDef488 std::string ToString(const EnumVal &ev) const {
489 return IsUInt64() ? NumToString(ev.GetAsUInt64())
490 : NumToString(ev.GetAsInt64());
491 }
492
sizeEnumDef493 size_t size() const { return vals.vec.size(); }
494
ValsEnumDef495 const std::vector<EnumVal *> &Vals() const { return vals.vec; }
496
LookupEnumDef497 const EnumVal *Lookup(const std::string &enum_name) const {
498 return vals.Lookup(enum_name);
499 }
500
501 bool is_union;
502 // Type is a union which uses type aliases where at least one type is
503 // available under two different names.
504 bool uses_multiple_type_instances;
505 Type underlying_type;
506
507 private:
IsUInt64EnumDef508 bool IsUInt64() const {
509 return (BASE_TYPE_ULONG == underlying_type.base_type);
510 }
511
512 friend EnumValBuilder;
513 SymbolTable<EnumVal> vals;
514 };
515
IsString(const Type & type)516 inline bool IsString(const Type &type) {
517 return type.base_type == BASE_TYPE_STRING;
518 }
519
IsStruct(const Type & type)520 inline bool IsStruct(const Type &type) {
521 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
522 }
523
IsIncompleteStruct(const Type & type)524 inline bool IsIncompleteStruct(const Type &type) {
525 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->predecl;
526 }
527
IsTable(const Type & type)528 inline bool IsTable(const Type &type) {
529 return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
530 }
531
IsUnion(const Type & type)532 inline bool IsUnion(const Type &type) {
533 return type.enum_def != nullptr && type.enum_def->is_union;
534 }
535
IsUnionType(const Type & type)536 inline bool IsUnionType(const Type &type) {
537 return IsUnion(type) && IsInteger(type.base_type);
538 }
539
IsVector(const Type & type)540 inline bool IsVector(const Type &type) { return IsVector(type.base_type); }
541
IsVectorOfStruct(const Type & type)542 inline bool IsVectorOfStruct(const Type &type) {
543 return IsVector(type) && IsStruct(type.VectorType());
544 }
545
IsVectorOfTable(const Type & type)546 inline bool IsVectorOfTable(const Type &type) {
547 return IsVector(type) && IsTable(type.VectorType());
548 }
549
IsArray(const Type & type)550 inline bool IsArray(const Type &type) {
551 return type.base_type == BASE_TYPE_ARRAY;
552 }
553
IsSeries(const Type & type)554 inline bool IsSeries(const Type &type) {
555 return IsVector(type) || IsArray(type);
556 }
557
IsEnum(const Type & type)558 inline bool IsEnum(const Type &type) {
559 return type.enum_def != nullptr && IsInteger(type.base_type);
560 }
561
InlineSize(const Type & type)562 inline size_t InlineSize(const Type &type) {
563 return IsStruct(type)
564 ? type.struct_def->bytesize
565 : (IsArray(type)
566 ? InlineSize(type.VectorType()) * type.fixed_length
567 : SizeOf(type.base_type));
568 }
569
InlineAlignment(const Type & type)570 inline size_t InlineAlignment(const Type &type) {
571 if (IsStruct(type)) {
572 return type.struct_def->minalign;
573 } else if (IsArray(type)) {
574 return IsStruct(type.VectorType()) ? type.struct_def->minalign
575 : SizeOf(type.element);
576 } else {
577 return SizeOf(type.base_type);
578 }
579 }
580 inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
581 return lhs.value == rhs.value;
582 }
583 inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
584 return !(lhs == rhs);
585 }
586
EqualByName(const Type & a,const Type & b)587 inline bool EqualByName(const Type &a, const Type &b) {
588 return a.base_type == b.base_type && a.element == b.element &&
589 (a.struct_def == b.struct_def ||
590 (a.struct_def != nullptr && b.struct_def != nullptr &&
591 a.struct_def->name == b.struct_def->name)) &&
592 (a.enum_def == b.enum_def ||
593 (a.enum_def != nullptr && b.enum_def != nullptr &&
594 a.enum_def->name == b.enum_def->name));
595 }
596
597 struct RPCCall : public Definition {
598 Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
599 const Parser &parser) const;
600
601 bool Deserialize(Parser &parser, const reflection::RPCCall *call);
602
603 StructDef *request, *response;
604 };
605
606 struct ServiceDef : public Definition {
607 Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
608 const Parser &parser) const;
609 bool Deserialize(Parser &parser, const reflection::Service *service);
610
611 SymbolTable<RPCCall> calls;
612 };
613
614 struct IncludedFile {
615 // The name of the schema file being included, as defined in the .fbs file.
616 // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this
617 // value is "foo/bar/baz.fbs").
618 std::string schema_name;
619
620 // The filename of where the included file was found, after searching the
621 // relative paths plus any other paths included with `flatc -I ...`. Note,
622 // while this is sometimes the same as schema_name, it is not always, since it
623 // can be defined relative to where flatc was invoked.
624 std::string filename;
625 };
626
627 // Since IncludedFile is contained within a std::set, need to provide ordering.
628 inline bool operator<(const IncludedFile &a, const IncludedFile &b) {
629 return a.filename < b.filename;
630 }
631
632 // Container of options that may apply to any of the source/text generators.
633 struct IDLOptions {
634 // field case style options for C++
635 enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower };
636 enum class ProtoIdGapAction { NO_OP, WARNING, ERROR };
637 bool gen_jvmstatic;
638 // Use flexbuffers instead for binary and text generation
639 bool use_flexbuffers;
640 bool strict_json;
641 bool output_default_scalars_in_json;
642 int indent_step;
643 bool cpp_minify_enums;
644 bool output_enum_identifiers;
645 bool prefixed_enums;
646 bool scoped_enums;
647 bool emit_min_max_enum_values;
648 bool swift_implementation_only;
649 bool include_dependence_headers;
650 bool mutable_buffer;
651 bool one_file;
652 bool proto_mode;
653 bool proto_oneof_union;
654 bool generate_all;
655 bool skip_unexpected_fields_in_json;
656 bool generate_name_strings;
657 bool generate_object_based_api;
658 bool gen_compare;
659 std::string cpp_object_api_pointer_type;
660 std::string cpp_object_api_string_type;
661 bool cpp_object_api_string_flexible_constructor;
662 CaseStyle cpp_object_api_field_case_style;
663 bool cpp_direct_copy;
664 bool gen_nullable;
665 std::string java_package_prefix;
666 bool java_checkerframework;
667 bool gen_generated;
668 bool gen_json_coders;
669 std::string object_prefix;
670 std::string object_suffix;
671 bool union_value_namespacing;
672 bool allow_non_utf8;
673 bool natural_utf8;
674 std::string include_prefix;
675 bool keep_prefix;
676 bool binary_schema_comments;
677 bool binary_schema_builtins;
678 bool binary_schema_gen_embed;
679 bool binary_schema_absolute_paths;
680 std::string go_import;
681 std::string go_namespace;
682 std::string go_module_name;
683 bool protobuf_ascii_alike;
684 bool size_prefixed;
685 std::string root_type;
686 bool force_defaults;
687 bool java_primitive_has_method;
688 bool cs_gen_json_serializer;
689 std::vector<std::string> cpp_includes;
690 std::string cpp_std;
691 bool cpp_static_reflection;
692 std::string proto_namespace_suffix;
693 std::string filename_suffix;
694 std::string filename_extension;
695 bool no_warnings;
696 bool warnings_as_errors;
697 std::string project_root;
698 bool cs_global_alias;
699 bool json_nested_flatbuffers;
700 bool json_nested_flexbuffers;
701 bool json_nested_legacy_flatbuffers;
702 bool ts_flat_files;
703 bool ts_entry_points;
704 bool ts_no_import_ext;
705 bool no_leak_private_annotations;
706 bool require_json_eof;
707 bool keep_proto_id;
708 bool python_no_type_prefix_suffix;
709 bool python_typing;
710 bool ts_omit_entrypoint;
711 ProtoIdGapAction proto_id_gap_action;
712
713 // Possible options for the more general generator below.
714 enum Language {
715 kJava = 1 << 0,
716 kCSharp = 1 << 1,
717 kGo = 1 << 2,
718 kCpp = 1 << 3,
719 kPython = 1 << 5,
720 kPhp = 1 << 6,
721 kJson = 1 << 7,
722 kBinary = 1 << 8,
723 kTs = 1 << 9,
724 kJsonSchema = 1 << 10,
725 kDart = 1 << 11,
726 kLua = 1 << 12,
727 kLobster = 1 << 13,
728 kRust = 1 << 14,
729 kKotlin = 1 << 15,
730 kSwift = 1 << 16,
731 kNim = 1 << 17,
732 kProto = 1 << 18,
733 kKotlinKmp = 1 << 19,
734 kMAX
735 };
736
737 enum MiniReflect { kNone, kTypes, kTypesAndNames };
738
739 MiniReflect mini_reflect;
740
741 // If set, require all fields in a table to be explicitly numbered.
742 bool require_explicit_ids;
743
744 // If set, implement serde::Serialize for generated Rust types
745 bool rust_serialize;
746
747 // If set, generate rust types in individual files with a root module file.
748 bool rust_module_root_file;
749
750 // The corresponding language bit will be set if a language is included
751 // for code generation.
752 unsigned long lang_to_generate;
753
754 // If set (default behavior), empty string fields will be set to nullptr to
755 // make the flatbuffer more compact.
756 bool set_empty_strings_to_null;
757
758 // If set (default behavior), empty vector fields will be set to nullptr to
759 // make the flatbuffer more compact.
760 bool set_empty_vectors_to_null;
761
IDLOptionsIDLOptions762 IDLOptions()
763 : gen_jvmstatic(false),
764 use_flexbuffers(false),
765 strict_json(false),
766 output_default_scalars_in_json(false),
767 indent_step(2),
768 cpp_minify_enums(false),
769 output_enum_identifiers(true),
770 prefixed_enums(true),
771 scoped_enums(false),
772 emit_min_max_enum_values(true),
773 swift_implementation_only(false),
774 include_dependence_headers(true),
775 mutable_buffer(false),
776 one_file(false),
777 proto_mode(false),
778 proto_oneof_union(false),
779 generate_all(false),
780 skip_unexpected_fields_in_json(false),
781 generate_name_strings(false),
782 generate_object_based_api(false),
783 gen_compare(false),
784 cpp_object_api_pointer_type("std::unique_ptr"),
785 cpp_object_api_string_flexible_constructor(false),
786 cpp_object_api_field_case_style(CaseStyle_Unchanged),
787 cpp_direct_copy(true),
788 gen_nullable(false),
789 java_checkerframework(false),
790 gen_generated(false),
791 gen_json_coders(false),
792 object_suffix("T"),
793 union_value_namespacing(true),
794 allow_non_utf8(false),
795 natural_utf8(false),
796 keep_prefix(false),
797 binary_schema_comments(false),
798 binary_schema_builtins(false),
799 binary_schema_gen_embed(false),
800 binary_schema_absolute_paths(false),
801 protobuf_ascii_alike(false),
802 size_prefixed(false),
803 force_defaults(false),
804 java_primitive_has_method(false),
805 cs_gen_json_serializer(false),
806 cpp_static_reflection(false),
807 filename_suffix("_generated"),
808 filename_extension(),
809 no_warnings(false),
810 warnings_as_errors(false),
811 project_root(""),
812 cs_global_alias(false),
813 json_nested_flatbuffers(true),
814 json_nested_flexbuffers(true),
815 json_nested_legacy_flatbuffers(false),
816 ts_flat_files(false),
817 ts_entry_points(false),
818 ts_no_import_ext(false),
819 no_leak_private_annotations(false),
820 require_json_eof(true),
821 keep_proto_id(false),
822 python_no_type_prefix_suffix(false),
823 python_typing(false),
824 ts_omit_entrypoint(false),
825 proto_id_gap_action(ProtoIdGapAction::WARNING),
826 mini_reflect(IDLOptions::kNone),
827 require_explicit_ids(false),
828 rust_serialize(false),
829 rust_module_root_file(false),
830 lang_to_generate(0),
831 set_empty_strings_to_null(true),
832 set_empty_vectors_to_null(true) {}
833 };
834
835 // This encapsulates where the parser is in the current source file.
836 struct ParserState {
ParserStateParserState837 ParserState()
838 : prev_cursor_(nullptr),
839 cursor_(nullptr),
840 line_start_(nullptr),
841 line_(0),
842 token_(-1),
843 attr_is_trivial_ascii_string_(true) {}
844
845 protected:
ResetStateParserState846 void ResetState(const char *source) {
847 prev_cursor_ = source;
848 cursor_ = source;
849 line_ = 0;
850 MarkNewLine();
851 }
852
MarkNewLineParserState853 void MarkNewLine() {
854 line_start_ = cursor_;
855 line_ += 1;
856 }
857
CursorPositionParserState858 int64_t CursorPosition() const {
859 FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
860 return static_cast<int64_t>(cursor_ - line_start_);
861 }
862
863 const char *prev_cursor_;
864 const char *cursor_;
865 const char *line_start_;
866 int line_; // the current line being parsed
867 int token_;
868
869 // Flag: text in attribute_ is true ASCII string without escape
870 // sequences. Only printable ASCII (without [\t\r\n]).
871 // Used for number-in-string (and base64 string in future).
872 bool attr_is_trivial_ascii_string_;
873 std::string attribute_;
874 std::vector<std::string> doc_comment_;
875 };
876
877 // A way to make error propagation less error prone by requiring values to be
878 // checked.
879 // Once you create a value of this type you must either:
880 // - Call Check() on it.
881 // - Copy or assign it to another value.
882 // Failure to do so leads to an assert.
883 // This guarantees that this as return value cannot be ignored.
884 class CheckedError {
885 public:
CheckedError(bool error)886 explicit CheckedError(bool error)
887 : is_error_(error), has_been_checked_(false) {}
888
889 CheckedError &operator=(const CheckedError &other) {
890 is_error_ = other.is_error_;
891 has_been_checked_ = false;
892 other.has_been_checked_ = true;
893 return *this;
894 }
895
CheckedError(const CheckedError & other)896 CheckedError(const CheckedError &other) {
897 *this = other; // Use assignment operator.
898 }
899
~CheckedError()900 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
901
Check()902 bool Check() {
903 has_been_checked_ = true;
904 return is_error_;
905 }
906
907 private:
908 bool is_error_;
909 mutable bool has_been_checked_;
910 };
911
912 // Additionally, in GCC we can get these errors statically, for additional
913 // assurance:
914 // clang-format off
915 #ifdef __GNUC__
916 #define FLATBUFFERS_CHECKED_ERROR CheckedError \
917 __attribute__((warn_unused_result))
918 #else
919 #define FLATBUFFERS_CHECKED_ERROR CheckedError
920 #endif
921 // clang-format on
922
923 class Parser : public ParserState {
924 public:
925 explicit Parser(const IDLOptions &options = IDLOptions())
current_namespace_(nullptr)926 : current_namespace_(nullptr),
927 empty_namespace_(nullptr),
928 flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
929 root_struct_def_(nullptr),
930 opts(options),
931 uses_flexbuffers_(false),
932 has_warning_(false),
933 advanced_features_(0),
934 source_(nullptr),
935 anonymous_counter_(0),
936 parse_depth_counter_(0) {
937 if (opts.force_defaults) { builder_.ForceDefaults(true); }
938 // Start out with the empty namespace being current.
939 empty_namespace_ = new Namespace();
940 namespaces_.push_back(empty_namespace_);
941 current_namespace_ = empty_namespace_;
942 known_attributes_["deprecated"] = true;
943 known_attributes_["required"] = true;
944 known_attributes_["key"] = true;
945 known_attributes_["shared"] = true;
946 known_attributes_["hash"] = true;
947 known_attributes_["id"] = true;
948 known_attributes_["force_align"] = true;
949 known_attributes_["bit_flags"] = true;
950 known_attributes_["original_order"] = true;
951 known_attributes_["nested_flatbuffer"] = true;
952 known_attributes_["csharp_partial"] = true;
953 known_attributes_["streaming"] = true;
954 known_attributes_["idempotent"] = true;
955 known_attributes_["cpp_type"] = true;
956 known_attributes_["cpp_ptr_type"] = true;
957 known_attributes_["cpp_ptr_type_get"] = true;
958 known_attributes_["cpp_str_type"] = true;
959 known_attributes_["cpp_str_flex_ctor"] = true;
960 known_attributes_["native_inline"] = true;
961 known_attributes_["native_custom_alloc"] = true;
962 known_attributes_["native_type"] = true;
963 known_attributes_["native_type_pack_name"] = true;
964 known_attributes_["native_default"] = true;
965 known_attributes_["flexbuffer"] = true;
966 known_attributes_["private"] = true;
967
968 // An attribute added to a field to indicate that is uses 64-bit addressing.
969 known_attributes_["offset64"] = true;
970
971 // An attribute added to a vector field to indicate that it uses 64-bit
972 // addressing and it has a 64-bit length.
973 known_attributes_["vector64"] = true;
974 }
975
976 // Copying is not allowed
977 Parser(const Parser &) = delete;
978 Parser &operator=(const Parser &) = delete;
979
980 Parser(Parser &&) = default;
981 Parser &operator=(Parser &&) = default;
982
~Parser()983 ~Parser() {
984 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
985 delete *it;
986 }
987 }
988
989 // Parse the string containing either schema or JSON data, which will
990 // populate the SymbolTable's or the FlatBufferBuilder above.
991 // include_paths is used to resolve any include statements, and typically
992 // should at least include the project path (where you loaded source_ from).
993 // include_paths must be nullptr terminated if specified.
994 // If include_paths is nullptr, it will attempt to load from the current
995 // directory.
996 // If the source was loaded from a file and isn't an include file,
997 // supply its name in source_filename.
998 // All paths specified in this call must be in posix format, if you accept
999 // paths from user input, please call PosixPath on them first.
1000 bool Parse(const char *_source, const char **include_paths = nullptr,
1001 const char *source_filename = nullptr);
1002
1003 bool ParseJson(const char *json, const char *json_filename = nullptr);
1004
1005 // Returns the number of characters were consumed when parsing a JSON string.
1006 std::ptrdiff_t BytesConsumed() const;
1007
1008 // Set the root type. May override the one set in the schema.
1009 bool SetRootType(const char *name);
1010
1011 // Mark all definitions as already having code generated.
1012 void MarkGenerated();
1013
1014 // Get the files recursively included by the given file. The returned
1015 // container will have at least the given file.
1016 std::set<std::string> GetIncludedFilesRecursive(
1017 const std::string &file_name) const;
1018
1019 // Fills builder_ with a binary version of the schema parsed.
1020 // See reflection/reflection.fbs
1021 void Serialize();
1022
1023 // Deserialize a schema buffer
1024 bool Deserialize(const uint8_t *buf, const size_t size);
1025
1026 // Fills internal structure as if the schema passed had been loaded by parsing
1027 // with Parse except that included filenames will not be populated.
1028 bool Deserialize(const reflection::Schema *schema);
1029
1030 Type *DeserializeType(const reflection::Type *type);
1031
1032 // Checks that the schema represented by this parser is a safe evolution
1033 // of the schema provided. Returns non-empty error on any problems.
1034 std::string ConformTo(const Parser &base);
1035
1036 // Similar to Parse(), but now only accepts JSON to be parsed into a
1037 // FlexBuffer.
1038 bool ParseFlexBuffer(const char *source, const char *source_filename,
1039 flexbuffers::Builder *builder);
1040
1041 StructDef *LookupStruct(const std::string &id) const;
1042 StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
1043
1044 std::string UnqualifiedName(const std::string &fullQualifiedName);
1045
1046 FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
1047
1048 // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
1049 // in a schema.
1050 // @param opts Options used to parce a schema and generate code.
1051 static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
1052
1053 // Get the set of included files that are directly referenced by the file
1054 // being parsed. This does not include files that are transitively included by
1055 // others includes.
1056 std::vector<IncludedFile> GetIncludedFiles() const;
1057
1058 private:
1059 class ParseDepthGuard;
1060
1061 void Message(const std::string &msg);
1062 void Warning(const std::string &msg);
1063 FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
1064 FLATBUFFERS_CHECKED_ERROR Next();
1065 FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
1066 bool Is(int t) const;
1067 bool IsIdent(const char *id) const;
1068 FLATBUFFERS_CHECKED_ERROR Expect(int t);
1069 std::string TokenToStringId(int t) const;
1070 EnumDef *LookupEnum(const std::string &id);
1071 FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
1072 std::string *last);
1073 FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
1074 FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
1075 FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
1076 const std::string &name, const Type &type,
1077 FieldDef **dest);
1078 FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
1079 FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
1080 FLATBUFFERS_CHECKED_ERROR ParseComma();
1081 FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
1082 size_t parent_fieldn,
1083 const StructDef *parent_struct_def,
1084 size_t count,
1085 bool inside_vector = false);
1086 template<typename F>
1087 FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
1088 const StructDef *struct_def,
1089 F body);
1090 FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
1091 std::string *value, uoffset_t *ovalue);
1092 void SerializeStruct(const StructDef &struct_def, const Value &val);
1093 void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
1094 const Value &val);
1095 template<typename F>
1096 FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, F body);
1097 FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
1098 FieldDef *field, size_t fieldn);
1099 FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
1100 FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
1101 Value &val, FieldDef *field, size_t fieldn,
1102 const StructDef *parent_struct_def);
1103 FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
1104 FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
1105 bool check, Value &e, BaseType req,
1106 bool *destmatch);
1107 FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
1108 FLATBUFFERS_CHECKED_ERROR TokenError();
1109 FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
1110 bool check_now);
1111 FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
1112 FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
1113 std::string *result);
1114 StructDef *LookupCreateStruct(const std::string &name,
1115 bool create_if_new = true,
1116 bool definition = false);
1117 FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest,
1118 const char *filename);
1119 FLATBUFFERS_CHECKED_ERROR ParseNamespace();
1120 FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
1121 StructDef **dest);
1122 FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
1123 EnumDef **dest);
1124 FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename);
1125 FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
1126 FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
1127 bool isextend, bool inside_oneof);
1128 FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
1129 FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
1130 FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
1131 FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
1132 FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
1133 FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
1134 FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
1135 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
1136 flexbuffers::Builder *builder);
1137 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
1138 FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
1139 const char *source_filename);
1140 FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
1141 const char **include_paths,
1142 const char *source_filename);
1143 FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak();
1144 FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields(
1145 const Definition &def, const Definition &value_type);
1146 FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
1147 const char **include_paths,
1148 const char *source_filename,
1149 const char *include_filename);
1150 FLATBUFFERS_CHECKED_ERROR DoParseJson();
1151 FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
1152 StructDef *struct_def,
1153 const char *suffix, BaseType baseType);
1154 FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
1155 const std::string &align_constant, size_t min_align, size_t *align);
1156
1157 bool SupportsAdvancedUnionFeatures() const;
1158 bool SupportsAdvancedArrayFeatures() const;
1159 bool SupportsOptionalScalars() const;
1160 bool SupportsDefaultVectorsAndStrings() const;
1161 bool Supports64BitOffsets() const;
1162 bool SupportsUnionUnderlyingType() const;
1163 Namespace *UniqueNamespace(Namespace *ns);
1164
1165 FLATBUFFERS_CHECKED_ERROR RecurseError();
1166 template<typename F> CheckedError Recurse(F f);
1167
1168 const std::string &GetPooledString(const std::string &s) const;
1169
1170 public:
1171 SymbolTable<Type> types_;
1172 SymbolTable<StructDef> structs_;
1173 SymbolTable<EnumDef> enums_;
1174 SymbolTable<ServiceDef> services_;
1175 std::vector<Namespace *> namespaces_;
1176 Namespace *current_namespace_;
1177 Namespace *empty_namespace_;
1178 std::string error_; // User readable error_ if Parse() == false
1179
1180 FlatBufferBuilder builder_; // any data contained in the file
1181 flexbuffers::Builder flex_builder_;
1182 flexbuffers::Reference flex_root_;
1183 StructDef *root_struct_def_;
1184 std::string file_identifier_;
1185 std::string file_extension_;
1186
1187 std::map<uint64_t, std::string> included_files_;
1188 std::map<std::string, std::set<IncludedFile>> files_included_per_file_;
1189 std::vector<std::string> native_included_files_;
1190
1191 std::map<std::string, bool> known_attributes_;
1192
1193 IDLOptions opts;
1194 bool uses_flexbuffers_;
1195 bool has_warning_;
1196
1197 uint64_t advanced_features_;
1198
1199 std::string file_being_parsed_;
1200
1201 private:
1202 const char *source_;
1203
1204 std::vector<std::pair<Value, FieldDef *>> field_stack_;
1205
1206 // TODO(cneo): Refactor parser to use string_cache more often to save
1207 // on memory usage.
1208 mutable std::set<std::string> string_cache_;
1209
1210 int anonymous_counter_;
1211 int parse_depth_counter_; // stack-overflow guard
1212 };
1213
1214 // Utility functions for multiple generators:
1215
1216 // Generate text (JSON) from a given FlatBuffer, and a given Parser
1217 // object that has been populated with the corresponding schema.
1218 // If ident_step is 0, no indentation will be generated. Additionally,
1219 // if it is less than 0, no linefeeds will be generated either.
1220 // See idl_gen_text.cpp.
1221 // strict_json adds "quotes" around field names if true.
1222 // These functions return nullptr on success, or an error string,
1223 // which may happen if the flatbuffer cannot be encoded in JSON (e.g.,
1224 // it contains non-UTF-8 byte arrays in String values).
1225 extern bool GenerateTextFromTable(const Parser &parser,
1226 const void *table,
1227 const std::string &tablename,
1228 std::string *text);
1229 extern const char *GenerateText(const Parser &parser, const void *flatbuffer,
1230 std::string *text);
1231 extern const char *GenerateTextFile(const Parser &parser,
1232 const std::string &path,
1233 const std::string &file_name);
1234
1235 extern const char *GenTextFromTable(const Parser &parser, const void *table,
1236 const std::string &tablename,
1237 std::string *text);
1238 extern const char *GenText(const Parser &parser, const void *flatbuffer,
1239 std::string *text);
1240 extern const char *GenTextFile(const Parser &parser, const std::string &path,
1241 const std::string &file_name);
1242
1243 // Generate GRPC Cpp interfaces.
1244 // See idl_gen_grpc.cpp.
1245 bool GenerateCppGRPC(const Parser &parser, const std::string &path,
1246 const std::string &file_name);
1247
1248 // Generate GRPC Go interfaces.
1249 // See idl_gen_grpc.cpp.
1250 bool GenerateGoGRPC(const Parser &parser, const std::string &path,
1251 const std::string &file_name);
1252
1253 // Generate GRPC Java classes.
1254 // See idl_gen_grpc.cpp
1255 bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
1256 const std::string &file_name);
1257
1258 // Generate GRPC Python interfaces.
1259 // See idl_gen_grpc.cpp.
1260 bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
1261 const std::string &file_name);
1262
1263 // Generate GRPC Swift interfaces.
1264 // See idl_gen_grpc.cpp.
1265 extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
1266 const std::string &file_name);
1267
1268 extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
1269 const std::string &file_name);
1270 } // namespace flatbuffers
1271
1272 #endif // FLATBUFFERS_IDL_H_
1273