• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
GetBufferStartFromRootPointer(const void * root)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.
GetPrefixedSize(const uint8_t * buf)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>
IsFieldPresent(const T * table,typename T::FlatBuffersVTableOffset field)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.
LookupEnum(const char ** names,const char * name)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 
ElementaryTypeNames()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.
flatbuffers_version_string()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