Documentation clarifications.
authorWouter van Oortmerssen <wvo@google.com>
Mon, 5 Jan 2015 22:50:23 +0000 (14:50 -0800)
committerWouter van Oortmerssen <wvo@google.com>
Wed, 7 Jan 2015 18:34:17 +0000 (10:34 -0800)
Change-Id: I7dc4bb3bbe32c6fe83a013790391fba0df8f4888

docs/html/md__cpp_usage.html
docs/html/md__go_usage.html
docs/html/md__internals.html
docs/html/md__schemas.html
docs/source/CppUsage.md
docs/source/GoUsage.md
docs/source/Internals.md
docs/source/Schemas.md

index 0a7ac1f..1163e5e 100644 (file)
@@ -65,6 +65,7 @@ $(document).ready(function(){initNavTree('md__cpp_usage.html','');});
 </div><!-- fragment --><p><code>CreateString</code> and <code>CreateVector</code> serialize these two built-in datatypes, and return offsets into the serialized data indicating where they are stored, such that <code>Monster</code> below can refer to them.</p>
 <p><code>CreateString</code> can also take an <code>std::string</code>, or a <code>const char *</code> with an explicit length, and is suitable for holding UTF-8 and binary data if needed.</p>
 <p><code>CreateVector</code> can also take an <code>std::vector</code>. The offset it returns is typed, i.e. can only be used to set fields of the correct type below. To create a vector of struct objects (which will be stored as contiguous memory in the buffer, use <code>CreateVectorOfStructs</code> instead.</p>
+<p>To create a vector of nested objects (e.g. tables, strings or other vectors) collect their offsets in a temporary array/vector, then call <code>CreateVector</code> on that (see e.g. the array of strings example in <code>test.cpp</code> <code>CreateFlatBufferTest</code>).</p>
 <div class="fragment"><div class="line">Vec3 vec(1, 2, 3);</div>
 </div><!-- fragment --><p><code>Vec3</code> is the first example of code from our generated header. Structs (unlike tables) translate to simple structs in C++, so we can construct them in a familiar way.</p>
 <p>We have now serialized the non-scalar components of of the monster example, so we could create the monster something like this:</p>
index 3ebc8b6..33f7297 100644 (file)
@@ -94,7 +94,7 @@ $(document).ready(function(){initNavTree('md__go_usage.html','');});
 <div class="line">    builder.PrependByte(byte(i))</div>
 <div class="line">}</div>
 <div class="line">inv := builder.EndVector(5)</div>
-</div><!-- fragment --><p>The generated method 'StartInventoryVector' is provided as a convenience function which calls 'StartVector' with the correct element size of the vector type which in this case is 'ubyte' or 1 byte per vector element. You pass the number of elements you want to write. You write the elements backwards since the buffer is being constructed back to front. You then pass <code>inv</code> to the corresponding <code>Add</code> call when you construct the table containing it afterwards.</p>
+</div><!-- fragment --><p>The generated method 'StartInventoryVector' is provided as a convenience function which calls 'StartVector' with the correct element size of the vector type which in this case is 'ubyte' or 1 byte per vector element. You pass the number of elements you want to write. You write the elements backwards since the buffer is being constructed back to front. Use the correct <code>Prepend</code> call for the type, or <code>PrependUOffsetT</code> for offsets. You then pass <code>inv</code> to the corresponding <code>Add</code> call when you construct the table containing it afterwards.</p>
 <p>There are <code>Prepend</code> functions for all the scalar types. You use <code>PrependUOffset</code> for any previously constructed objects (such as other tables, strings, vectors). For structs, you use the appropriate <code>create</code> function in-line, as shown above in the <code>Monster</code> example.</p>
 <p>Once you're done constructing a buffer, you call <code>Finish</code> with the root object offset (<code>mon</code> in the example above). Your data now resides in Builder.Bytes. Important to note is that the real data starts at the index indicated by Head(), for Offset() bytes (this is because the buffer is constructed backwards). If you wanted to read the buffer right after creating it (using <code>GetRootAsMonster</code> above), the second argument, instead of <code>0</code> would thus also be <code>Head()</code>.</p>
 <h2>Text Parsing</h2>
index b4da59f..c51c2d3 100644 (file)
@@ -67,9 +67,9 @@ $(document).ready(function(){initNavTree('md__internals.html','');});
 <h3>Structs</h3>
 <p>These are the simplest, and as mentioned, intended for simple data that benefits from being extra efficient and doesn't need versioning / extensibility. They are always stored inline in their parent (a struct, table, or vector) for maximum compactness. Structs define a consistent memory layout where all components are aligned to their size, and structs aligned to their largest scalar member. This is done independent of the alignment rules of the underlying compiler to guarantee a cross platform compatible layout. This layout is then enforced in the generated code.</p>
 <h3>Tables</h3>
-<p>These start with an <code>soffset_t</code> to a vtable (signed version of <code>uoffset_t</code>, since vtables may be stored anywhere), followed by all the fields as aligned scalars (or offsets). Unlike structs, not all fields need to be present. There is no set order and layout.</p>
+<p>These start with an <code>soffset_t</code> to a vtable. This is a signed version of <code>uoffset_t</code>, since vtables may be stored anywhere relative to the object. This offset is substracted (not added) from the object start to arrive at the vtable start. This offset is followed by all the fields as aligned scalars (or offsets). Unlike structs, not all fields need to be present. There is no set order and layout.</p>
 <p>To be able to access fields regardless of these uncertainties, we go through a vtable of offsets. Vtables are shared between any objects that happen to have the same vtable values.</p>
-<p>The elements of a vtable are all of type <code>voffset_t</code>, which is a <code>uint16_t</code>. The first element is the number of elements of the vtable, including this one. The second one is the size of the object, in bytes (including the vtable offset). This size is used for streaming, to know how many bytes to read to be able to access all fields of the object. The remaining elements are the N offsets, where N is the amount of fields declared in the schema when the code that constructed this buffer was compiled (thus, the size of the table is N + 2).</p>
+<p>The elements of a vtable are all of type <code>voffset_t</code>, which is a <code>uint16_t</code>. The first element is the size of the vtable in bytes, including the size element. The second one is the size of the object, in bytes (including the vtable offset). This size could be used for streaming, to know how many bytes to read to be able to access all fields of the object. The remaining elements are the N offsets, where N is the amount of fields declared in the schema when the code that constructed this buffer was compiled (thus, the size of the table is N + 2).</p>
 <p>All accessor functions in the generated code for tables contain the offset into this table as a constant. This offset is checked against the first field (the number of elements), to protect against newer code reading older data. If this offset is out of range, or the vtable entry is 0, that means the field is not present in this object, and the default value is return. Otherwise, the entry is used as offset to the field to be read.</p>
 <h3>Strings and Vectors</h3>
 <p>Strings are simply a vector of bytes, and are always null-terminated. Vectors are stored as contiguous aligned scalar elements prefixed by a 32bit element count (not including any null termination).</p>
index e154a20..aee2bd0 100644 (file)
@@ -145,7 +145,7 @@ root_type Monster;
 <li><code>original_order</code> (on a table): since elements in a table do not need to be stored in any particular order, they are often optimized for space by sorting them to size. This attribute stops that from happening.</li>
 <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>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>
 </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>
index 62c45d8..91332d2 100755 (executable)
@@ -42,6 +42,11 @@ correct type below. To create a vector of struct objects (which will
 be stored as contiguous memory in the buffer, use `CreateVectorOfStructs`
 instead.
 
+To create a vector of nested objects (e.g. tables, strings or other vectors)
+collect their offsets in a temporary array/vector, then call `CreateVector`
+on that (see e.g. the array of strings example in `test.cpp`
+`CreateFlatBufferTest`).
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
     Vec3 vec(1, 2, 3);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index 10dbd5e..c2a7495 100644 (file)
@@ -98,7 +98,8 @@ function which calls 'StartVector' with the correct element size of the vector
 type which in this case is 'ubyte' or 1 byte per vector element.
 You pass the number of elements you want to write.
 You write the elements backwards since the buffer
-is being constructed back to front. You then pass `inv` to the corresponding
+is being constructed back to front. Use the correct `Prepend` call for the type,
+or `PrependUOffsetT` for offsets. You then pass `inv` to the corresponding
 `Add` call when you construct the table containing it afterwards.
 
 There are `Prepend` functions for all the scalar types. You use
index bf4b58b..bf1a980 100755 (executable)
@@ -73,8 +73,10 @@ code.
 
 ### Tables
 
-These start with an `soffset_t` to a vtable (signed version of
-`uoffset_t`, since vtables may be stored anywhere), followed by all the
+These start with an `soffset_t` to a vtable. This is a signed version of
+`uoffset_t`, since vtables may be stored anywhere relative to the object.
+This offset is substracted (not added) from the object start to arrive at
+the vtable start. This offset is followed by all the
 fields as aligned scalars (or offsets). Unlike structs, not all fields
 need to be present. There is no set order and layout.
 
@@ -83,9 +85,9 @@ through a vtable of offsets. Vtables are shared between any objects that
 happen to have the same vtable values.
 
 The elements of a vtable are all of type `voffset_t`, which is
-a `uint16_t`. The first element is the number of elements of the vtable,
-including this one. The second one is the size of the object, in bytes
-(including the vtable offset). This size is used for streaming, to know
+a `uint16_t`. The first element is the size of the vtable in bytes,
+including the size element. The second one is the size of the object, in bytes
+(including the vtable offset). This size could be used for streaming, to know
 how many bytes to read to be able to access all fields of the object.
 The remaining elements are the N offsets, where N is the amount of fields
 declared in the schema when the code that constructed this buffer was
index 9fce336..1329f9e 100755 (executable)
@@ -271,7 +271,7 @@ Current understood attributes:
     meaning that any value N specified in the schema will end up
     representing 1<<N, or if you don't specify values at all, you'll get
     the sequence 1, 2, 4, 8, ...
--   `nested_flatbuffer: table_name` (on a field): this indicates that the field
+-   `nested_flatbuffer: "table_name"` (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 `table_name`. The generated code will then produce
     a convenient accessor for the nested FlatBuffer.