Sorted Vector & binary search functionality.

Bug: 16659276
Tested: on Linux & Windows.

Change-Id: Ie7a73810345fad4cf0a3ad03dfaa5464e3ed5ac8
This commit is contained in:
Wouter van Oortmerssen
2015-01-07 17:51:31 -08:00
parent 73582b145c
commit 3550899987
11 changed files with 166 additions and 30 deletions

View File

@@ -101,7 +101,15 @@ $(document).ready(function(){initNavTree('md__cpp_usage.html','');});
<div class="fragment"><div class="line"><span class="keyword">auto</span> inv = monster-&gt;inventory();</div>
<div class="line">assert(inv);</div>
<div class="line">assert(inv-&gt;Get(9) == 9);</div>
</div><!-- fragment --><h3>Direct memory access</h3>
</div><!-- fragment --><h3>Storing maps / dictionaries in a FlatBuffer</h3>
<p>FlatBuffers doesn't support maps natively, but there is support to emulate their behavior with vectors and binary search, which means you can have fast lookups directly from a FlatBuffer without having to unpack your data into a <code>std::map</code> or similar.</p>
<p>To use it:</p><ul>
<li>Designate one of the fields in a table as they "key" field. You do this by setting the <code>key</code> attribute on this field, e.g. <code>name:string (key)</code>. You may only have one key field, and it must be of string or scalar type.</li>
<li>Write out tables of this type as usual, collect their offsets in an array or vector.</li>
<li>Instead of <code>CreateVector</code>, call <code>CreateVectorOfSortedTables</code>, which will first sort all offsets such that the tables they refer to are sorted by the key field, then serialize it.</li>
<li>Now when you're accessing the FlatBuffer, you can use <code>Vector::LookupByKey</code> instead of just <code>Vector::Get</code> to access elements of the vector, e.g.: <code>myvector-&gt;LookupByKey("Fred")</code>, which returns a pointer to the corresponding table type, or <code>nullptr</code> if not found. <code>LookupByKey</code> performs a binary search, so should have a similar speed to <code>std::map</code>, though may be faster because of better caching. <code>LookupByKey</code> only works if the vector has been sorted, it will likely not find elements if it hasn't been sorted.</li>
</ul>
<h3>Direct memory access</h3>
<p>As you can see from the above examples, all elements in a buffer are accessed through generated accessors. This is because everything is stored in little endian format on all platforms (the accessor performs a swap operation on big endian machines), and also because the layout of things is generally not known to the user.</p>
<p>For structs, layout is deterministic and guaranteed to be the same accross platforms (scalars are aligned to their own size, and structs themselves to their largest member), and you are allowed to access this memory directly by using <code>sizeof()</code> and <code>memcpy</code> on the pointer to a struct, or even an array of structs.</p>
<p>To compute offsets to sub-elements of a struct, make sure they are a structs themselves, as then you can use the pointers to figure out the offset without having to hardcode it. This is handy for use of arrays of structs with calls like <code>glVertexAttribPointer</code> in OpenGL or similar APIs.</p>

View File

@@ -146,6 +146,7 @@ root_type Monster;
<li><code>force_align: size</code> (on a struct): force the alignment of this struct to be something higher than what it is naturally aligned to. Causes these structs to be aligned to that amount inside a buffer, IF that buffer is allocated with that alignment (which is not necessarily the case for buffers accessed directly inside a <code>FlatBufferBuilder</code>).</li>
<li><code>bit_flags</code> (on an enum): the values of this field indicate bits, meaning that any value N specified in the schema will end up representing 1&lt;&lt;N, or if you don't specify values at all, you'll get the sequence 1, 2, 4, 8, ...</li>
<li><code>nested_flatbuffer: "table_name"</code> (on a field): this indicates that the field (which must be a vector of ubyte) contains flatbuffer data, for which the root type is given by <code>table_name</code>. The generated code will then produce a convenient accessor for the nested FlatBuffer.</li>
<li><code>key</code> (on a field): this field is meant to be used as a key when sorting a vector of the type of table it sits in. Can be used for in-place binary search.</li>
</ul>
<h2>JSON Parsing</h2>
<p>The same parser that parses the schema declarations above is also able to parse JSON objects that conform to this schema. So, unlike other JSON parsers, this parser is strongly typed, and parses directly into a FlatBuffer (see the compiler documentation on how to do this from the command line, or the C++ documentation on how to do this at runtime).</p>