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 | |
36 | namespace 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. |
42 | inline 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. |
77 | inline 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. |
84 | struct 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. |
94 | typedef uint64_t hash_value_t; |
95 | typedef std::function<void(void **pointer_adr, hash_value_t hash)> |
96 | resolver_function_t; |
97 | typedef 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). |
106 | template<typename T> |
107 | bool 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. |
116 | inline 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. |
162 | enum 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 | |
182 | enum ElementaryType { |
183 | #define FLATBUFFERS_ET(E) E, |
184 | FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) |
185 | #undef FLATBUFFERS_ET |
186 | }; |
187 | |
188 | inline 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. |
202 | struct 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 | |
211 | static_assert(sizeof(TypeCode) == 2, "TypeCode" ); |
212 | |
213 | struct TypeTable; |
214 | |
215 | // Signature of the static method present in each type. |
216 | typedef const TypeTable *(*TypeFunction)(); |
217 | |
218 | struct 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. |
229 | inline 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 | |