Coverage Report

Created: 2026-05-16 06:39

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