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