flatbuffers.h 11 KB

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