Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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 | |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 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" |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 23 | #include "flatbuffers/base.h" |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 24 | #include "flatbuffers/buffer.h" |
| 25 | #include "flatbuffers/buffer_ref.h" |
| 26 | #include "flatbuffers/detached_buffer.h" |
| 27 | #include "flatbuffers/flatbuffer_builder.h" |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 28 | #include "flatbuffers/stl_emulation.h" |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 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" |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 35 | |
| 36 | namespace flatbuffers { |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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. |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 59 | static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t), |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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. |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 77 | inline uoffset_t GetPrefixedSize(const uint8_t *buf) { |
| 78 | return ReadScalar<uoffset_t>(buf); |
| 79 | } |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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; |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 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; |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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 |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 154 | // loading schemas (see idl.h), we can also have code generation for minimal |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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! |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 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. |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 202 | struct TypeCode { |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 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; |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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). |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 221 | const TypeCode *type_codes; // num_elems count |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 222 | const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 223 | const int16_t *array_sizes; // less than num_elems entries (see TypeCode). |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 224 | const int64_t *values; // Only set for non-consecutive enum/union or structs. |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 225 | const char *const *names; // Only set if compiled with --reflect-names. |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 226 | }; |
| 227 | |
| 228 | // String which identifies the current version of FlatBuffers. |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame] | 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 | } |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 234 | |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 235 | // clang-format off |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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_ |