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_H_
18#define FLATBUFFERS_H_
19
20// TODO: These includes are for mitigating the pains of users editing their
21// source because they relied on flatbuffers.h to include everything for them.
22#include "flatbuffers/array.h"
23#include "flatbuffers/base.h"
24#include "flatbuffers/buffer.h"
25#include "flatbuffers/buffer_ref.h"
26#include "flatbuffers/detached_buffer.h"
27#include "flatbuffers/flatbuffer_builder.h"
28#include "flatbuffers/stl_emulation.h"
29#include "flatbuffers/string.h"
30#include "flatbuffers/struct.h"
31#include "flatbuffers/table.h"
32#include "flatbuffers/vector.h"
33#include "flatbuffers/vector_downward.h"
34#include "flatbuffers/verifier.h"
35
36namespace flatbuffers {
37
38/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
39/// it is the opposite transformation of GetRoot().
40/// This may be useful if you want to pass on a root and have the recipient
41/// delete the buffer afterwards.
42inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
43 auto table = reinterpret_cast<const Table *>(root);
44 auto vtable = table->GetVTable();
45 // Either the vtable is before the root or after the root.
46 auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
47 // Align to at least sizeof(uoffset_t).
48 start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
49 ~(sizeof(uoffset_t) - 1));
50 // Additionally, there may be a file_identifier in the buffer, and the root
51 // offset. The buffer may have been aligned to any size between
52 // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
53 // Sadly, the exact alignment is only known when constructing the buffer,
54 // since it depends on the presence of values with said alignment properties.
55 // So instead, we simply look at the next uoffset_t values (root,
56 // file_identifier, and alignment padding) to see which points to the root.
57 // None of the other values can "impersonate" the root since they will either
58 // be 0 or four ASCII characters.
59 static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t),
60 "file_identifier is assumed to be the same size as uoffset_t");
61 for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
62 possible_roots; possible_roots--) {
63 start -= sizeof(uoffset_t);
64 if (ReadScalar<uoffset_t>(start) + start ==
65 reinterpret_cast<const uint8_t *>(root))
66 return start;
67 }
68 // We didn't find the root, either the "root" passed isn't really a root,
69 // or the buffer is corrupt.
70 // Assert, because calling this function with bad data may cause reads
71 // outside of buffer boundaries.
72 FLATBUFFERS_ASSERT(false);
73 return nullptr;
74}
75
76/// @brief This return the prefixed size of a FlatBuffer.
77inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
78 return ReadScalar<uoffset_t>(buf);
79}
80
81// Base class for native objects (FlatBuffer data de-serialized into native
82// C++ data structures).
83// Contains no functionality, purely documentative.
84struct NativeTable {};
85
86/// @brief Function types to be used with resolving hashes into objects and
87/// back again. The resolver gets a pointer to a field inside an object API
88/// object that is of the type specified in the schema using the attribute
89/// `cpp_type` (it is thus important whatever you write to this address
90/// matches that type). The value of this field is initially null, so you
91/// may choose to implement a delayed binding lookup using this function
92/// if you wish. The resolver does the opposite lookup, for when the object
93/// is being serialized again.
94typedef uint64_t hash_value_t;
95typedef std::function<void(void **pointer_adr, hash_value_t hash)>
96 resolver_function_t;
97typedef std::function<hash_value_t(void *pointer)> rehasher_function_t;
98
99// Helper function to test if a field is present, using any of the field
100// enums in the generated code.
101// `table` must be a generated table type. Since this is a template parameter,
102// this is not typechecked to be a subclass of Table, so beware!
103// Note: this function will return false for fields equal to the default
104// value, since they're not stored in the buffer (unless force_defaults was
105// used).
106template<typename T>
107bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
108 // Cast, since Table is a private baseclass of any table types.
109 return reinterpret_cast<const Table *>(table)->CheckField(
110 static_cast<voffset_t>(field));
111}
112
113// Utility function for reverse lookups on the EnumNames*() functions
114// (in the generated C++ code)
115// names must be NULL terminated.
116inline int LookupEnum(const char **names, const char *name) {
117 for (const char **p = names; *p; p++)
118 if (!strcmp(*p, name)) return static_cast<int>(p - names);
119 return -1;
120}
121
122// These macros allow us to layout a struct with a guarantee that they'll end
123// up looking the same on different compilers and platforms.
124// It does this by disallowing the compiler to do any padding, and then
125// does padding itself by inserting extra padding fields that make every
126// element aligned to its own size.
127// Additionally, it manually sets the alignment of the struct as a whole,
128// which is typically its largest element, or a custom size set in the schema
129// by the force_align attribute.
130// These are used in the generated code only.
131
132// clang-format off
133#if defined(_MSC_VER)
134 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
135 __pragma(pack(1)) \
136 struct __declspec(align(alignment))
137 #define FLATBUFFERS_STRUCT_END(name, size) \
138 __pragma(pack()) \
139 static_assert(sizeof(name) == size, "compiler breaks packing rules")
140#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
141 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
142 _Pragma("pack(1)") \
143 struct __attribute__((aligned(alignment)))
144 #define FLATBUFFERS_STRUCT_END(name, size) \
145 _Pragma("pack()") \
146 static_assert(sizeof(name) == size, "compiler breaks packing rules")
147#else
148 #error Unknown compiler, please define structure alignment macros
149#endif
150// clang-format on
151
152// Minimal reflection via code generation.
153// Besides full-fat reflection (see reflection.h) and parsing/printing by
154// loading schemas (see idl.h), we can also have code generation for minimal
155// reflection data which allows pretty-printing and other uses without needing
156// a schema or a parser.
157// Generate code with --reflect-types (types only) or --reflect-names (names
158// also) to enable.
159// See minireflect.h for utilities using this functionality.
160
161// These types are organized slightly differently as the ones in idl.h.
162enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
163
164// Scalars have the same order as in idl.h
165// clang-format off
166#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
167 ET(ET_UTYPE) \
168 ET(ET_BOOL) \
169 ET(ET_CHAR) \
170 ET(ET_UCHAR) \
171 ET(ET_SHORT) \
172 ET(ET_USHORT) \
173 ET(ET_INT) \
174 ET(ET_UINT) \
175 ET(ET_LONG) \
176 ET(ET_ULONG) \
177 ET(ET_FLOAT) \
178 ET(ET_DOUBLE) \
179 ET(ET_STRING) \
180 ET(ET_SEQUENCE) // See SequenceType.
181
182enum ElementaryType {
183 #define FLATBUFFERS_ET(E) E,
184 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
185 #undef FLATBUFFERS_ET
186};
187
188inline const char * const *ElementaryTypeNames() {
189 static const char * const names[] = {
190 #define FLATBUFFERS_ET(E) #E,
191 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
192 #undef FLATBUFFERS_ET
193 };
194 return names;
195}
196// clang-format on
197
198// Basic type info cost just 16bits per field!
199// We're explicitly defining the signedness since the signedness of integer
200// bitfields is otherwise implementation-defined and causes warnings on older
201// GCC compilers.
202struct TypeCode {
203 // ElementaryType
204 unsigned short base_type : 4;
205 // Either vector (in table) or array (in struct)
206 unsigned short is_repeating : 1;
207 // Index into type_refs below, or -1 for none.
208 signed short sequence_ref : 11;
209};
210
211static_assert(sizeof(TypeCode) == 2, "TypeCode");
212
213struct TypeTable;
214
215// Signature of the static method present in each type.
216typedef const TypeTable *(*TypeFunction)();
217
218struct TypeTable {
219 SequenceType st;
220 size_t num_elems; // of type_codes, values, names (but not type_refs).
221 const TypeCode *type_codes; // num_elems count
222 const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
223 const int16_t *array_sizes; // less than num_elems entries (see TypeCode).
224 const int64_t *values; // Only set for non-consecutive enum/union or structs.
225 const char *const *names; // Only set if compiled with --reflect-names.
226};
227
228// String which identifies the current version of FlatBuffers.
229inline const char *flatbuffers_version_string() {
230 return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
231 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
232 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
233}
234
235// clang-format off
236#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
237 inline E operator | (E lhs, E rhs){\
238 return E(T(lhs) | T(rhs));\
239 }\
240 inline E operator & (E lhs, E rhs){\
241 return E(T(lhs) & T(rhs));\
242 }\
243 inline E operator ^ (E lhs, E rhs){\
244 return E(T(lhs) ^ T(rhs));\
245 }\
246 inline E operator ~ (E lhs){\
247 return E(~T(lhs));\
248 }\
249 inline E operator |= (E &lhs, E rhs){\
250 lhs = lhs | rhs;\
251 return lhs;\
252 }\
253 inline E operator &= (E &lhs, E rhs){\
254 lhs = lhs & rhs;\
255 return lhs;\
256 }\
257 inline E operator ^= (E &lhs, E rhs){\
258 lhs = lhs ^ rhs;\
259 return lhs;\
260 }\
261 inline bool operator !(E rhs) \
262 {\
263 return !bool(T(rhs)); \
264 }
265/// @endcond
266} // namespace flatbuffers
267
268// clang-format on
269
270#endif // FLATBUFFERS_H_
271