Internals.md revision 66de19ace80bae3bf377e43e9698597170bc9031
126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen# FlatBuffer Internals 226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThis section is entirely optional for the use of FlatBuffers. In normal 426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenusage, you should never need the information contained herein. If you're 526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmersseninterested however, it should give you more of an appreciation of why 626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenFlatBuffers is both efficient and convenient. 726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Format components 926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenA FlatBuffer is a binary file and in-memory format consisting mostly of 1126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenscalars of various sizes, all aligned to their own size. Each scalar is 1226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenalso always represented in little-endian format, as this corresponds to 1326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenall commonly used CPUs today. FlatBuffers will also work on big-endian 1426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenmachines, but will be slightly slower because of additional 1526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbyte-swap intrinsics. 1626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenOn purpose, the format leaves a lot of details about where exactly 1826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthings live in memory undefined, e.g. fields in a table can have any 1926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenorder, and objects to some extend can be stored in many orders. This is 2026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbecause the format doesn't need this information to be efficient, and it 2126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenleaves room for optimization and extension (for example, fields can be 2226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenpacked in a way that is most compact). Instead, the format is defined in 2326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenterms of offsets and adjacency only. 2426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Format identification 2626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThe format also doesn't contain information for format identification 2826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenand versioning, which is also by design. FlatBuffers is a statically typed 2926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssensystem, meaning the user of a buffer needs to know what kind of buffer 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenit is. FlatBuffers can of course be wrapped inside other containers 3126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenwhere needed, or you can use its union feature to dynamically identify 3226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenmultiple possible sub-objects stored. Additionally, it can be used 3326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentogether with the schema parser if full reflective capabilities are 3426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssendesired. 3526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenVersioning is something that is intrinsically part of the format (the 3726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenoptionality / extensibility of fields), so the format itself does not 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenneed a version number (it's a meta-format, in a sense). We're hoping 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthat this format can accommodate all data needed. If format breaking 4026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenchanges are ever necessary, it would become a new kind of format rather 4126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthan just a variation. 4226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Offsets 4426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThe most important and generic offset type (see `flatbuffers.h`) is 4666de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssen`uoffset_t`, which is currently always a `uint32_t`, and is used to 4766de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenrefer to all tables/unions/strings/vectors (these are never stored 4866de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenin-line). 32bit is 4926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenintentional, since we want to keep the format binary compatible between 5026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen32 and 64bit systems, and a 64bit offset would bloat the size for almost 5126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenall uses. A version of this format with 64bit (or 16bit) offsets is easy to set 5226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenwhen needed. Unsigned means they can only point in one direction, which 5326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentypically is forward (towards a higher memory location). Any backwards 5426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenoffsets will be explicitly marked as such. 5526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5666de19ace80bae3bf377e43e9698597170bc9031Wouter van OortmerssenThe format starts with an `uoffset_t` to the root object in the buffer. 5726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenWe have two kinds of objects, structs and tables. 5926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Structs 6126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThese are the simplest, and as mentioned, intended for simple data that 6326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbenefits from being extra efficient and doesn't need versioning / 6426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenextensibility. They are always stored inline in their parent (a struct, 6526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentable, or vector) for maximum compactness. Structs define a consistent 6626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenmemory layout where all components are aligned to their size, and 6726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstructs aligned to their largest scalar member. This is done independent 6826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenof the alignment rules of the underlying compiler to guarantee a cross 6926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenplatform compatible layout. This layout is then enforced in the generated 7026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssencode. 7126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 7226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Tables 7326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 7426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThese start with an `soffset_t` to a vtable (signed version of 7566de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssen`uoffset_t`, since vtables may be stored anywhere), followed by all the 7666de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenfields as aligned scalars (or offsets). Unlike structs, not all fields 7766de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenneed to be present. There is no set order and layout. 7826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 7926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenTo be able to access fields regardless of these uncertainties, we go 8026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthrough a vtable of offsets. Vtables are shared between any objects that 8126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenhappen to have the same vtable values. 8226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8366de19ace80bae3bf377e43e9698597170bc9031Wouter van OortmerssenThe elements of a vtable are all of type `voffset_t`, which is 8426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssena `uint16_t`. The first element is the number of elements of the vtable, 8526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenincluding this one. The second one is the size of the object, in bytes 8626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen(including the vtable offset). This size is used for streaming, to know 8726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenhow many bytes to read to be able to access all fields of the object. 8866de19ace80bae3bf377e43e9698597170bc9031Wouter van OortmerssenThe remaining elements are the N offsets, where N is the amount of fields 8926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssendeclared in the schema when the code that constructed this buffer was 9026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssencompiled (thus, the size of the table is N + 2). 9126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 9226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenAll accessor functions in the generated code for tables contain the 9326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenoffset into this table as a constant. This offset is checked against the 9426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenfirst field (the number of elements), to protect against newer code 9526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenreading older data. If this offset is out of range, or the vtable entry 9626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenis 0, that means the field is not present in this object, and the 9726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssendefault value is return. Otherwise, the entry is used as offset to the 9826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenfield to be read. 9926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Strings and Vectors 10126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenStrings are simply a vector of bytes, and are always 10326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennull-terminated. Vectors are stored as contiguous aligned scalar 10466de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenelements prefixed by a 32bit element count (not including any 10566de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssennull termination). 10626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Construction 10826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10966de19ace80bae3bf377e43e9698597170bc9031Wouter van OortmerssenThe current implementation constructs these buffers backwards (starting 11066de19ace80bae3bf377e43e9698597170bc9031Wouter van Oortmerssenat the highest memory address of the buffer), since 11126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthat significantly reduces the amount of bookkeeping and simplifies the 11226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconstruction API. 11326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 11426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen### Code example 11526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 11626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenHere's an example of the code that gets generated for the `samples/monster.fbs`. 11726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenWhat follows is the entire file, broken up by comments: 11826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 11926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // automatically generated, do not modify 12026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 12126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #include "flatbuffers/flatbuffers.h" 12226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 12326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen namespace MyGame { 12426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen namespace Sample { 12526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 12626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenNested namespace support. 12726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 12826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum { 12926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Color_Red = 0, 13026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Color_Green = 1, 13126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Color_Blue = 2, 13226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 13326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline const char **EnumNamesColor() { 13526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *names[] = { "Red", "Green", "Blue", nullptr }; 13626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return names; 13726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 13826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline const char *EnumNameColor(int e) { return EnumNamesColor()[e]; } 14026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenEnums and convenient reverse lookup. 14226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum { 14426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Any_NONE = 0, 14526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Any_Monster = 1, 14626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 14726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline const char **EnumNamesAny() { 14926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *names[] = { "NONE", "Monster", nullptr }; 15026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return names; 15126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 15226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline const char *EnumNameAny(int e) { return EnumNamesAny()[e]; } 15426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenUnions share a lot with enums. 15626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct Vec3; 15826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct Monster; 15926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 16026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenPredeclare all datatypes since there may be circular references. 16126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 16226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen MANUALLY_ALIGNED_STRUCT(4) Vec3 { 16326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen private: 16426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float x_; 16526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float y_; 16626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float z_; 16726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 16826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen public: 16926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Vec3(float x, float y, float z) 17026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) {} 17126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 17226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float x() const { return flatbuffers::EndianScalar(x_); } 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float y() const { return flatbuffers::EndianScalar(y_); } 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen float z() const { return flatbuffers::EndianScalar(z_); } 17526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 17626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen STRUCT_END(Vec3, 12); 17726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 17826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThese ugly macros do a couple of things: they turn off any padding the compiler 17926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenmight normally do, since we add padding manually (though none in this example), 18026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenand they enforce alignment chosen by FlatBuffers. This ensures the layout of 18126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthis struct will look the same regardless of compiler and platform. Note that 18226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthe fields are private: this is because these store little endian scalars 18326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenregardless of platform (since this is part of the serialized data). 18426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen`EndianScalar` then converts back and forth, which is a no-op on all current 18526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenmobile and desktop platforms, and a single machine instruction on the few 18626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenremaining big endian platforms. 18726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct Monster : private flatbuffers::Table { 18926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const Vec3 *pos() const { return GetStruct<const Vec3 *>(4); } 19026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int16_t mana() const { return GetField<int16_t>(6, 150); } 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int16_t hp() const { return GetField<int16_t>(8, 100); } 19226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(10); } 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(14); } 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int8_t color() const { return GetField<int8_t>(16, 2); } 19526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 19626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenTables are a bit more complicated. A table accessor struct is used to point at 19826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthe serialized data for a table, which always starts with an offset to its 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvtable. It derives from `Table`, which contains the `GetField` helper functions. 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenGetField takes a vtable offset, and a default value. It will look in the vtable 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenat that offset. If the offset is out of bounds (data from an older version) or 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenthe vtable entry is 0, the field is not present and the default is returned. 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenOtherwise, it uses the entry as an offset into the table to locate the field. 20426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct MonsterBuilder { 20626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen flatbuffers::FlatBufferBuilder &fbb_; 20726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen flatbuffers::uoffset_t start_; 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); } 20926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_mana(int16_t mana) { fbb_.AddElement<int16_t>(6, mana, 150); } 21026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(8, hp, 100); } 21126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(10, name); } 21226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(14, inventory); } 21326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen void add_color(int8_t color) { fbb_.AddElement<int8_t>(16, color, 2); } 21426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } 21526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen flatbuffers::Offset<Monster> Finish() { return flatbuffers::Offset<Monster>(fbb_.EndTable(start_, 7)); } 21626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 21726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 21826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen`MonsterBuilder` is the base helper struct to construct a table using a 21926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen`FlatBufferBuilder`. You can add the fields in any order, and the `Finish` 22026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssencall will ensure the correct vtable gets generated. 22126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 22226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const Vec3 *pos, int16_t mana, int16_t hp, flatbuffers::Offset<flatbuffers::String> name, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory, int8_t color) { 22326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen MonsterBuilder builder_(_fbb); 22426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_inventory(inventory); 22526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_name(name); 22626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_pos(pos); 22726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_hp(hp); 22826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_mana(mana); 22926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.add_color(color); 23026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return builder_.Finish(); 23126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 23226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 23326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen`CreateMonster` is a convenience function that calls all functions in 23426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen`MonsterBuilder` above for you. Note that if you pass values which are 23526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssendefaults as arguments, it will not actually construct that field, so 23626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenyou can probably use this function instead of the builder class in 23726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenalmost all cases. 23826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 23926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen inline const Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<Monster>(buf); } 24026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 24126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenThis function is only generated for the root table type, to be able to 24226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstart traversing a FlatBuffer from a raw buffer pointer. 24326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 24426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; // namespace MyGame 24526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; // namespace Sample 24626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 24726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 248