mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-26 07:42:39 +00:00
Trimmed vtables of trailing zeroes.
This is something the format supports, but none of the builders were doing. Can save 10-20% on FlatBuffer binary size! Also fixed the Go tests. Change-Id: I616c56ce9bbcfcaee23aa24f0532fcb60b6a8c75 Tested: on Linux.
This commit is contained in:
@@ -110,6 +110,11 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
|
|||||||
objectOffset := b.Offset()
|
objectOffset := b.Offset()
|
||||||
existingVtable := UOffsetT(0)
|
existingVtable := UOffsetT(0)
|
||||||
|
|
||||||
|
// Trim vtable of trailing zeroes.
|
||||||
|
i := len(b.vtable) - 1;
|
||||||
|
for ; i >= 0 && b.vtable[i] == 0; i-- {}
|
||||||
|
b.vtable = b.vtable[:i + 1];
|
||||||
|
|
||||||
// Search backwards through existing vtables, because similar vtables
|
// Search backwards through existing vtables, because similar vtables
|
||||||
// are likely to have been recently appended. See
|
// are likely to have been recently appended. See
|
||||||
// BenchmarkVtableDeduplication for a case in which this heuristic
|
// BenchmarkVtableDeduplication for a case in which this heuristic
|
||||||
|
|||||||
@@ -704,8 +704,8 @@ class FlatBufferBuilder
|
|||||||
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
||||||
Allocator *allocator = nullptr,
|
Allocator *allocator = nullptr,
|
||||||
bool own_allocator = false)
|
bool own_allocator = false)
|
||||||
: buf_(initial_size, allocator, own_allocator), nested(false),
|
: buf_(initial_size, allocator, own_allocator), max_voffset_(0),
|
||||||
finished(false), minalign_(1), force_defaults_(false),
|
nested(false), finished(false), minalign_(1), force_defaults_(false),
|
||||||
dedup_vtables_(true), string_pool(nullptr) {
|
dedup_vtables_(true), string_pool(nullptr) {
|
||||||
offsetbuf_.reserve(16); // Avoid first few reallocs.
|
offsetbuf_.reserve(16); // Avoid first few reallocs.
|
||||||
vtables_.reserve(16);
|
vtables_.reserve(16);
|
||||||
@@ -725,7 +725,7 @@ class FlatBufferBuilder
|
|||||||
/// to construct another buffer.
|
/// to construct another buffer.
|
||||||
void Clear() {
|
void Clear() {
|
||||||
buf_.clear();
|
buf_.clear();
|
||||||
offsetbuf_.clear();
|
ClearOffsets();
|
||||||
nested = false;
|
nested = false;
|
||||||
finished = false;
|
finished = false;
|
||||||
vtables_.clear();
|
vtables_.clear();
|
||||||
@@ -839,6 +839,7 @@ class FlatBufferBuilder
|
|||||||
void TrackField(voffset_t field, uoffset_t off) {
|
void TrackField(voffset_t field, uoffset_t off) {
|
||||||
FieldLoc fl = { off, field };
|
FieldLoc fl = { off, field };
|
||||||
offsetbuf_.push_back(fl);
|
offsetbuf_.push_back(fl);
|
||||||
|
max_voffset_ = (std::max)(max_voffset_, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Like PushElement, but additionally tracks the field this represents.
|
// Like PushElement, but additionally tracks the field this represents.
|
||||||
@@ -899,7 +900,7 @@ class FlatBufferBuilder
|
|||||||
// This finishes one serialized object by generating the vtable if it's a
|
// This finishes one serialized object by generating the vtable if it's a
|
||||||
// table, comparing it against existing vtables, and writing the
|
// table, comparing it against existing vtables, and writing the
|
||||||
// resulting vtable offset.
|
// resulting vtable offset.
|
||||||
uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
|
uoffset_t EndTable(uoffset_t start) {
|
||||||
// If you get this assert, a corresponding StartTable wasn't called.
|
// If you get this assert, a corresponding StartTable wasn't called.
|
||||||
assert(nested);
|
assert(nested);
|
||||||
// Write the vtable offset, which is the start of any Table.
|
// Write the vtable offset, which is the start of any Table.
|
||||||
@@ -908,11 +909,17 @@ class FlatBufferBuilder
|
|||||||
// Write a vtable, which consists entirely of voffset_t elements.
|
// Write a vtable, which consists entirely of voffset_t elements.
|
||||||
// It starts with the number of offsets, followed by a type id, followed
|
// It starts with the number of offsets, followed by a type id, followed
|
||||||
// by the offsets themselves. In reverse:
|
// by the offsets themselves. In reverse:
|
||||||
buf_.fill_big(numfields * sizeof(voffset_t));
|
// Include space for the last offset and ensure empty tables have a
|
||||||
|
// minimum size.
|
||||||
|
max_voffset_ = (std::max)(static_cast<voffset_t>(max_voffset_ +
|
||||||
|
sizeof(voffset_t)),
|
||||||
|
FieldIndexToOffset(0));
|
||||||
|
buf_.fill_big(max_voffset_);
|
||||||
auto table_object_size = vtableoffsetloc - start;
|
auto table_object_size = vtableoffsetloc - start;
|
||||||
assert(table_object_size < 0x10000); // Vtable use 16bit offsets.
|
assert(table_object_size < 0x10000); // Vtable use 16bit offsets.
|
||||||
PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
|
WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
|
||||||
PushElement<voffset_t>(FieldIndexToOffset(numfields));
|
static_cast<voffset_t>(table_object_size));
|
||||||
|
WriteScalar<voffset_t>(buf_.data(), max_voffset_);
|
||||||
// Write the offsets into the table
|
// Write the offsets into the table
|
||||||
for (auto field_location = offsetbuf_.begin();
|
for (auto field_location = offsetbuf_.begin();
|
||||||
field_location != offsetbuf_.end();
|
field_location != offsetbuf_.end();
|
||||||
@@ -922,7 +929,7 @@ class FlatBufferBuilder
|
|||||||
assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
|
assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
|
||||||
WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
|
WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
|
||||||
}
|
}
|
||||||
offsetbuf_.clear();
|
ClearOffsets();
|
||||||
auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
|
auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
|
||||||
auto vt1_size = ReadScalar<voffset_t>(vt1);
|
auto vt1_size = ReadScalar<voffset_t>(vt1);
|
||||||
auto vt_use = GetSize();
|
auto vt_use = GetSize();
|
||||||
@@ -955,6 +962,11 @@ class FlatBufferBuilder
|
|||||||
return vtableoffsetloc;
|
return vtableoffsetloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: call the version above instead.
|
||||||
|
uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
|
||||||
|
return EndTable(start);
|
||||||
|
}
|
||||||
|
|
||||||
// This checks a required field has been set in a given table that has
|
// This checks a required field has been set in a given table that has
|
||||||
// just been constructed.
|
// just been constructed.
|
||||||
template<typename T> void Required(Offset<T> table, voffset_t field) {
|
template<typename T> void Required(Offset<T> table, voffset_t field) {
|
||||||
@@ -973,7 +985,10 @@ class FlatBufferBuilder
|
|||||||
|
|
||||||
uoffset_t EndStruct() { return GetSize(); }
|
uoffset_t EndStruct() { return GetSize(); }
|
||||||
|
|
||||||
void ClearOffsets() { offsetbuf_.clear(); }
|
void ClearOffsets() {
|
||||||
|
offsetbuf_.clear();
|
||||||
|
max_voffset_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Aligns such that when "len" bytes are written, an object can be written
|
// Aligns such that when "len" bytes are written, an object can be written
|
||||||
// after it with "alignment" without padding.
|
// after it with "alignment" without padding.
|
||||||
@@ -1510,6 +1525,9 @@ class FlatBufferBuilder
|
|||||||
|
|
||||||
// Accumulating offsets of table members while it is being built.
|
// Accumulating offsets of table members while it is being built.
|
||||||
std::vector<FieldLoc> offsetbuf_;
|
std::vector<FieldLoc> offsetbuf_;
|
||||||
|
// Track how much of the vtable is in use, so we can output the most compact
|
||||||
|
// possible vtable.
|
||||||
|
voffset_t max_voffset_;
|
||||||
|
|
||||||
// Ensure objects are not nested.
|
// Ensure objects are not nested.
|
||||||
bool nested;
|
bool nested;
|
||||||
|
|||||||
@@ -42,6 +42,29 @@ enum BaseType {
|
|||||||
Union = 16
|
Union = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline BaseType (&EnumValuesBaseType())[17] {
|
||||||
|
static BaseType values[] = {
|
||||||
|
None,
|
||||||
|
UType,
|
||||||
|
Bool,
|
||||||
|
Byte,
|
||||||
|
UByte,
|
||||||
|
Short,
|
||||||
|
UShort,
|
||||||
|
Int,
|
||||||
|
UInt,
|
||||||
|
Long,
|
||||||
|
ULong,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
String,
|
||||||
|
Vector,
|
||||||
|
Obj,
|
||||||
|
Union
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
inline const char **EnumNamesBaseType() {
|
inline const char **EnumNamesBaseType() {
|
||||||
static const char *names[] = {
|
static const char *names[] = {
|
||||||
"None",
|
"None",
|
||||||
@@ -113,7 +136,7 @@ struct TypeBuilder {
|
|||||||
}
|
}
|
||||||
TypeBuilder &operator=(const TypeBuilder &);
|
TypeBuilder &operator=(const TypeBuilder &);
|
||||||
flatbuffers::Offset<Type> Finish() {
|
flatbuffers::Offset<Type> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 3);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Type>(end);
|
auto o = flatbuffers::Offset<Type>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -173,7 +196,7 @@ struct KeyValueBuilder {
|
|||||||
}
|
}
|
||||||
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
||||||
flatbuffers::Offset<KeyValue> Finish() {
|
flatbuffers::Offset<KeyValue> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 2);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<KeyValue>(end);
|
auto o = flatbuffers::Offset<KeyValue>(end);
|
||||||
fbb_.Required(o, KeyValue::VT_KEY);
|
fbb_.Required(o, KeyValue::VT_KEY);
|
||||||
return o;
|
return o;
|
||||||
@@ -266,7 +289,7 @@ struct EnumValBuilder {
|
|||||||
}
|
}
|
||||||
EnumValBuilder &operator=(const EnumValBuilder &);
|
EnumValBuilder &operator=(const EnumValBuilder &);
|
||||||
flatbuffers::Offset<EnumVal> Finish() {
|
flatbuffers::Offset<EnumVal> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 4);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<EnumVal>(end);
|
auto o = flatbuffers::Offset<EnumVal>(end);
|
||||||
fbb_.Required(o, EnumVal::VT_NAME);
|
fbb_.Required(o, EnumVal::VT_NAME);
|
||||||
return o;
|
return o;
|
||||||
@@ -381,7 +404,7 @@ struct EnumBuilder {
|
|||||||
}
|
}
|
||||||
EnumBuilder &operator=(const EnumBuilder &);
|
EnumBuilder &operator=(const EnumBuilder &);
|
||||||
flatbuffers::Offset<Enum> Finish() {
|
flatbuffers::Offset<Enum> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 6);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Enum>(end);
|
auto o = flatbuffers::Offset<Enum>(end);
|
||||||
fbb_.Required(o, Enum::VT_NAME);
|
fbb_.Required(o, Enum::VT_NAME);
|
||||||
fbb_.Required(o, Enum::VT_VALUES);
|
fbb_.Required(o, Enum::VT_VALUES);
|
||||||
@@ -544,7 +567,7 @@ struct FieldBuilder {
|
|||||||
}
|
}
|
||||||
FieldBuilder &operator=(const FieldBuilder &);
|
FieldBuilder &operator=(const FieldBuilder &);
|
||||||
flatbuffers::Offset<Field> Finish() {
|
flatbuffers::Offset<Field> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 11);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Field>(end);
|
auto o = flatbuffers::Offset<Field>(end);
|
||||||
fbb_.Required(o, Field::VT_NAME);
|
fbb_.Required(o, Field::VT_NAME);
|
||||||
fbb_.Required(o, Field::VT_TYPE);
|
fbb_.Required(o, Field::VT_TYPE);
|
||||||
@@ -695,7 +718,7 @@ struct ObjectBuilder {
|
|||||||
}
|
}
|
||||||
ObjectBuilder &operator=(const ObjectBuilder &);
|
ObjectBuilder &operator=(const ObjectBuilder &);
|
||||||
flatbuffers::Offset<Object> Finish() {
|
flatbuffers::Offset<Object> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 7);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Object>(end);
|
auto o = flatbuffers::Offset<Object>(end);
|
||||||
fbb_.Required(o, Object::VT_NAME);
|
fbb_.Required(o, Object::VT_NAME);
|
||||||
fbb_.Required(o, Object::VT_FIELDS);
|
fbb_.Required(o, Object::VT_FIELDS);
|
||||||
@@ -808,7 +831,7 @@ struct SchemaBuilder {
|
|||||||
}
|
}
|
||||||
SchemaBuilder &operator=(const SchemaBuilder &);
|
SchemaBuilder &operator=(const SchemaBuilder &);
|
||||||
flatbuffers::Offset<Schema> Finish() {
|
flatbuffers::Offset<Schema> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 5);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Schema>(end);
|
auto o = flatbuffers::Offset<Schema>(end);
|
||||||
fbb_.Required(o, Schema::VT_OBJECTS);
|
fbb_.Required(o, Schema::VT_OBJECTS);
|
||||||
fbb_.Required(o, Schema::VT_ENUMS);
|
fbb_.Required(o, Schema::VT_ENUMS);
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ public class FlatBufferBuilder {
|
|||||||
obj.sortTables(offsets, bb);
|
obj.sortTables(offsets, bb);
|
||||||
return createVectorOfTables(offsets);
|
return createVectorOfTables(offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
|
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
|
||||||
* already a {@link CharBuffer}, this method is allocation free.
|
* already a {@link CharBuffer}, this method is allocation free.
|
||||||
@@ -744,7 +744,11 @@ public class FlatBufferBuilder {
|
|||||||
addInt(0);
|
addInt(0);
|
||||||
int vtableloc = offset();
|
int vtableloc = offset();
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (int i = vtable_in_use - 1; i >= 0 ; i--) {
|
int i = vtable_in_use - 1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; i >= 0 && vtable[i] == 0; i--) {}
|
||||||
|
int trimmed_size = i + 1;
|
||||||
|
for (; i >= 0 ; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
||||||
addShort(off);
|
addShort(off);
|
||||||
@@ -752,12 +756,12 @@ public class FlatBufferBuilder {
|
|||||||
|
|
||||||
final int standard_fields = 2; // The fields below:
|
final int standard_fields = 2; // The fields below:
|
||||||
addShort((short)(vtableloc - object_start));
|
addShort((short)(vtableloc - object_start));
|
||||||
addShort((short)((vtable_in_use + standard_fields) * SIZEOF_SHORT));
|
addShort((short)((trimmed_size + standard_fields) * SIZEOF_SHORT));
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
int existing_vtable = 0;
|
int existing_vtable = 0;
|
||||||
outer_loop:
|
outer_loop:
|
||||||
for (int i = 0; i < num_vtables; i++) {
|
for (i = 0; i < num_vtables; i++) {
|
||||||
int vt1 = bb.capacity() - vtables[i];
|
int vt1 = bb.capacity() - vtables[i];
|
||||||
int vt2 = space;
|
int vt2 = space;
|
||||||
short len = bb.getShort(vt1);
|
short len = bb.getShort(vt1);
|
||||||
|
|||||||
@@ -604,23 +604,28 @@ flatbuffers.Builder.prototype.endObject = function() {
|
|||||||
this.addInt32(0);
|
this.addInt32(0);
|
||||||
var vtableloc = this.offset();
|
var vtableloc = this.offset();
|
||||||
|
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
var i = this.vtable_in_use - 1;
|
||||||
|
for (; i >= 0 && this.vtable[i] == 0; i--) {}
|
||||||
|
var trimmed_size = i + 1;
|
||||||
|
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (var i = this.vtable_in_use - 1; i >= 0; i--) {
|
for (; i >= 0; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var standard_fields = 2; // The fields below:
|
var standard_fields = 2; // The fields below:
|
||||||
this.addInt16(vtableloc - this.object_start);
|
this.addInt16(vtableloc - this.object_start);
|
||||||
this.addInt16((this.vtable_in_use + standard_fields) * flatbuffers.SIZEOF_SHORT);
|
var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
|
||||||
|
this.addInt16(len);
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
var existing_vtable = 0;
|
var existing_vtable = 0;
|
||||||
|
var vt1 = this.space;
|
||||||
outer_loop:
|
outer_loop:
|
||||||
for (var i = 0; i < this.vtables.length; i++) {
|
for (i = 0; i < this.vtables.length; i++) {
|
||||||
var vt1 = this.bb.capacity() - this.vtables[i];
|
var vt2 = this.bb.capacity() - this.vtables[i];
|
||||||
var vt2 = this.space;
|
|
||||||
var len = this.bb.readInt16(vt1);
|
|
||||||
if (len == this.bb.readInt16(vt2)) {
|
if (len == this.bb.readInt16(vt2)) {
|
||||||
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
||||||
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
||||||
|
|||||||
@@ -500,7 +500,11 @@ namespace FlatBuffers
|
|||||||
AddInt((int)0);
|
AddInt((int)0);
|
||||||
var vtableloc = Offset;
|
var vtableloc = Offset;
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (int i = _vtableSize - 1; i >= 0 ; i--) {
|
int i = _vtableSize - 1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; i >= 0 && _vtable[i] == 0; i--) {}
|
||||||
|
int trimmedSize = i + 1;
|
||||||
|
for (; i >= 0 ; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
short off = (short)(_vtable[i] != 0
|
short off = (short)(_vtable[i] != 0
|
||||||
? vtableloc - _vtable[i]
|
? vtableloc - _vtable[i]
|
||||||
@@ -513,12 +517,12 @@ namespace FlatBuffers
|
|||||||
|
|
||||||
const int standardFields = 2; // The fields below:
|
const int standardFields = 2; // The fields below:
|
||||||
AddShort((short)(vtableloc - _objectStart));
|
AddShort((short)(vtableloc - _objectStart));
|
||||||
AddShort((short)((_vtableSize + standardFields) *
|
AddShort((short)((trimmedSize + standardFields) *
|
||||||
sizeof(short)));
|
sizeof(short)));
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
int existingVtable = 0;
|
int existingVtable = 0;
|
||||||
for (int i = 0; i < _numVtables; i++) {
|
for (i = 0; i < _numVtables; i++) {
|
||||||
int vt1 = _bb.Length - _vtables[i];
|
int vt1 = _bb.Length - _vtables[i];
|
||||||
int vt2 = _space;
|
int vt2 = _space;
|
||||||
short len = _bb.GetShort(vt1);
|
short len = _bb.GetShort(vt1);
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ class FlatbufferBuilder
|
|||||||
if (function_exists('mb_detect_encoding')) {
|
if (function_exists('mb_detect_encoding')) {
|
||||||
return (bool) mb_detect_encoding($bytes, 'UTF-8', true);
|
return (bool) mb_detect_encoding($bytes, 'UTF-8', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$len = strlen($bytes);
|
$len = strlen($bytes);
|
||||||
if ($len < 1) {
|
if ($len < 1) {
|
||||||
/* NOTE: always return 1 when passed string is null */
|
/* NOTE: always return 1 when passed string is null */
|
||||||
@@ -812,14 +812,18 @@ class FlatbufferBuilder
|
|||||||
$this->addInt(0);
|
$this->addInt(0);
|
||||||
$vtableloc = $this->offset();
|
$vtableloc = $this->offset();
|
||||||
|
|
||||||
for ($i = $this->vtable_in_use -1; $i >= 0; $i--) {
|
$i = $this->vtable_in_use -1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; $i >= 0 && $this->vtable[$i] == 0; $i--) {}
|
||||||
|
$trimmed_size = $i + 1;
|
||||||
|
for (; $i >= 0; $i--) {
|
||||||
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
|
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
|
||||||
$this->addShort($off);
|
$this->addShort($off);
|
||||||
}
|
}
|
||||||
|
|
||||||
$standard_fields = 2; // the fields below
|
$standard_fields = 2; // the fields below
|
||||||
$this->addShort($vtableloc - $this->object_start);
|
$this->addShort($vtableloc - $this->object_start);
|
||||||
$this->addShort(($this->vtable_in_use + $standard_fields) * Constants::SIZEOF_SHORT);
|
$this->addShort(($trimmed_size + $standard_fields) * Constants::SIZEOF_SHORT);
|
||||||
|
|
||||||
// search for an existing vtable that matches the current one.
|
// search for an existing vtable that matches the current one.
|
||||||
$existing_vtable = 0;
|
$existing_vtable = 0;
|
||||||
|
|||||||
@@ -193,6 +193,10 @@ class Builder(object):
|
|||||||
objectOffset = self.Offset()
|
objectOffset = self.Offset()
|
||||||
existingVtable = None
|
existingVtable = None
|
||||||
|
|
||||||
|
# Trim trailing 0 offsets.
|
||||||
|
while self.current_vtable and self.current_vtable[-1] == 0:
|
||||||
|
self.current_vtable.pop()
|
||||||
|
|
||||||
# Search backwards through existing vtables, because similar vtables
|
# Search backwards through existing vtables, because similar vtables
|
||||||
# are likely to have been recently appended. See
|
# are likely to have been recently appended. See
|
||||||
# BenchmarkVtableDeduplication for a case in which this heuristic
|
# BenchmarkVtableDeduplication for a case in which this heuristic
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ struct MonsterBuilder {
|
|||||||
}
|
}
|
||||||
MonsterBuilder &operator=(const MonsterBuilder &);
|
MonsterBuilder &operator=(const MonsterBuilder &);
|
||||||
flatbuffers::Offset<Monster> Finish() {
|
flatbuffers::Offset<Monster> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 10);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Monster>(end);
|
auto o = flatbuffers::Offset<Monster>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -426,7 +426,7 @@ struct WeaponBuilder {
|
|||||||
}
|
}
|
||||||
WeaponBuilder &operator=(const WeaponBuilder &);
|
WeaponBuilder &operator=(const WeaponBuilder &);
|
||||||
flatbuffers::Offset<Weapon> Finish() {
|
flatbuffers::Offset<Weapon> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 2);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Weapon>(end);
|
auto o = flatbuffers::Offset<Weapon>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1531,9 +1531,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
"(const {{STRUCT_NAME}}Builder &);";
|
"(const {{STRUCT_NAME}}Builder &);";
|
||||||
|
|
||||||
// Finish() function.
|
// Finish() function.
|
||||||
auto num_fields = NumToString(struct_def.fields.vec.size());
|
|
||||||
code_ += " flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
|
code_ += " flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
|
||||||
code_ += " const auto end = fbb_.EndTable(start_, " + num_fields + ");";
|
code_ += " const auto end = fbb_.EndTable(start_);";
|
||||||
code_ += " auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
|
code_ += " auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
|
||||||
|
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
|
|||||||
@@ -1071,8 +1071,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
|||||||
builder_.PopBytes(struct_def.bytesize);
|
builder_.PopBytes(struct_def.bytesize);
|
||||||
assert(!ovalue);
|
assert(!ovalue);
|
||||||
} else {
|
} else {
|
||||||
auto val = builder_.EndTable(start,
|
auto val = builder_.EndTable(start);
|
||||||
static_cast<voffset_t>(struct_def.fields.vec.size()));
|
|
||||||
if (ovalue) *ovalue = val;
|
if (ovalue) *ovalue = val;
|
||||||
if (value) *value = NumToString(val);
|
if (value) *value = NumToString(val);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
|||||||
fbb.ClearOffsets();
|
fbb.ClearOffsets();
|
||||||
return fbb.EndStruct();
|
return fbb.EndStruct();
|
||||||
} else {
|
} else {
|
||||||
return fbb.EndTable(start, static_cast<voffset_t>(fielddefs->size()));
|
return fbb.EndTable(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -205,11 +205,11 @@ namespace FlatBuffers.Test
|
|||||||
builder.EndObject();
|
builder.EndObject();
|
||||||
Assert.ArrayEqual(new byte[]
|
Assert.ArrayEqual(new byte[]
|
||||||
{
|
{
|
||||||
0, 0, 0, 0, 0, 0, // padding to 16 bytes
|
// No padding.
|
||||||
6, 0, // vtable bytes
|
4, 0, // vtable bytes
|
||||||
4, 0, // end of object from here
|
4, 0, // end of object from here
|
||||||
0, 0, // entry 0 is empty (default value)
|
// entry 0 is not stored (trimmed end of vtable)
|
||||||
6, 0, 0, 0, // int32 offset for start of vtable
|
4, 0, 0, 0, // int32 offset for start of vtable
|
||||||
},
|
},
|
||||||
builder.DataBuffer.Data);
|
builder.DataBuffer.Data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ mkdir -p ${go_src}/github.com/google/flatbuffers/go
|
|||||||
mkdir -p ${go_src}/flatbuffers_test
|
mkdir -p ${go_src}/flatbuffers_test
|
||||||
|
|
||||||
cp -a MyGame/Example/*.go ./go_gen/src/MyGame/Example/
|
cp -a MyGame/Example/*.go ./go_gen/src/MyGame/Example/
|
||||||
|
# do not compile the gRPC generated files, which are not tested by go_test.go
|
||||||
|
# below, but have their own test.
|
||||||
|
rm ./go_gen/src/MyGame/Example/*_grpc.go
|
||||||
cp -a ../go/* ./go_gen/src/github.com/google/flatbuffers/go
|
cp -a ../go/* ./go_gen/src/github.com/google/flatbuffers/go
|
||||||
cp -a ./go_test.go ./go_gen/src/flatbuffers_test/
|
cp -a ./go_test.go ./go_gen/src/flatbuffers_test/
|
||||||
|
|
||||||
|
|||||||
@@ -715,10 +715,10 @@ func CheckByteLayout(fail func(string, ...interface{})) {
|
|||||||
b.PrependBoolSlot(0, false, false)
|
b.PrependBoolSlot(0, false, false)
|
||||||
b.EndObject()
|
b.EndObject()
|
||||||
check([]byte{
|
check([]byte{
|
||||||
6, 0, // vtable bytes
|
4, 0, // vtable bytes
|
||||||
4, 0, // end of object from here
|
4, 0, // end of object from here
|
||||||
0, 0, // entry 1 is zero
|
// entry 1 is zero and not stored.
|
||||||
6, 0, 0, 0, // offset for start of vtable (int32)
|
4, 0, 0, 0, // offset for start of vtable (int32)
|
||||||
})
|
})
|
||||||
|
|
||||||
// test 10: vtable with one int16
|
// test 10: vtable with one int16
|
||||||
@@ -1085,7 +1085,6 @@ func CheckManualBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UO
|
|||||||
b.PrependByteSlot(7, 1, 0)
|
b.PrependByteSlot(7, 1, 0)
|
||||||
b.PrependUOffsetTSlot(8, mon2, 0)
|
b.PrependUOffsetTSlot(8, mon2, 0)
|
||||||
b.PrependUOffsetTSlot(9, test4, 0)
|
b.PrependUOffsetTSlot(9, test4, 0)
|
||||||
b.PrependUOffsetTSlot(9, test5, 0)
|
|
||||||
mon := b.EndObject()
|
mon := b.EndObject()
|
||||||
|
|
||||||
b.Finish(mon)
|
b.Finish(mon)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -345,7 +345,7 @@ struct MonsterBuilder {
|
|||||||
}
|
}
|
||||||
MonsterBuilder &operator=(const MonsterBuilder &);
|
MonsterBuilder &operator=(const MonsterBuilder &);
|
||||||
flatbuffers::Offset<Monster> Finish() {
|
flatbuffers::Offset<Monster> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 0);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Monster>(end);
|
auto o = flatbuffers::Offset<Monster>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -404,7 +404,7 @@ struct TestSimpleTableWithEnumBuilder {
|
|||||||
}
|
}
|
||||||
TestSimpleTableWithEnumBuilder &operator=(const TestSimpleTableWithEnumBuilder &);
|
TestSimpleTableWithEnumBuilder &operator=(const TestSimpleTableWithEnumBuilder &);
|
||||||
flatbuffers::Offset<TestSimpleTableWithEnum> Finish() {
|
flatbuffers::Offset<TestSimpleTableWithEnum> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 1);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<TestSimpleTableWithEnum>(end);
|
auto o = flatbuffers::Offset<TestSimpleTableWithEnum>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,7 @@ struct StatBuilder {
|
|||||||
}
|
}
|
||||||
StatBuilder &operator=(const StatBuilder &);
|
StatBuilder &operator=(const StatBuilder &);
|
||||||
flatbuffers::Offset<Stat> Finish() {
|
flatbuffers::Offset<Stat> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 3);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Stat>(end);
|
auto o = flatbuffers::Offset<Stat>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -1015,7 +1015,7 @@ struct MonsterBuilder {
|
|||||||
}
|
}
|
||||||
MonsterBuilder &operator=(const MonsterBuilder &);
|
MonsterBuilder &operator=(const MonsterBuilder &);
|
||||||
flatbuffers::Offset<Monster> Finish() {
|
flatbuffers::Offset<Monster> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 34);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Monster>(end);
|
auto o = flatbuffers::Offset<Monster>(end);
|
||||||
fbb_.Required(o, Monster::VT_NAME);
|
fbb_.Required(o, Monster::VT_NAME);
|
||||||
return o;
|
return o;
|
||||||
@@ -1352,7 +1352,7 @@ struct TypeAliasesBuilder {
|
|||||||
}
|
}
|
||||||
TypeAliasesBuilder &operator=(const TypeAliasesBuilder &);
|
TypeAliasesBuilder &operator=(const TypeAliasesBuilder &);
|
||||||
flatbuffers::Offset<TypeAliases> Finish() {
|
flatbuffers::Offset<TypeAliases> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 12);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<TypeAliases>(end);
|
auto o = flatbuffers::Offset<TypeAliases>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -105,7 +105,7 @@ struct TableInNestedNSBuilder {
|
|||||||
}
|
}
|
||||||
TableInNestedNSBuilder &operator=(const TableInNestedNSBuilder &);
|
TableInNestedNSBuilder &operator=(const TableInNestedNSBuilder &);
|
||||||
flatbuffers::Offset<TableInNestedNS> Finish() {
|
flatbuffers::Offset<TableInNestedNS> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 1);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<TableInNestedNS>(end);
|
auto o = flatbuffers::Offset<TableInNestedNS>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ struct TableInFirstNSBuilder {
|
|||||||
}
|
}
|
||||||
TableInFirstNSBuilder &operator=(const TableInFirstNSBuilder &);
|
TableInFirstNSBuilder &operator=(const TableInFirstNSBuilder &);
|
||||||
flatbuffers::Offset<TableInFirstNS> Finish() {
|
flatbuffers::Offset<TableInFirstNS> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 3);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<TableInFirstNS>(end);
|
auto o = flatbuffers::Offset<TableInFirstNS>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ struct TableInCBuilder {
|
|||||||
}
|
}
|
||||||
TableInCBuilder &operator=(const TableInCBuilder &);
|
TableInCBuilder &operator=(const TableInCBuilder &);
|
||||||
flatbuffers::Offset<TableInC> Finish() {
|
flatbuffers::Offset<TableInC> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 2);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<TableInC>(end);
|
auto o = flatbuffers::Offset<TableInC>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ struct SecondTableInABuilder {
|
|||||||
}
|
}
|
||||||
SecondTableInABuilder &operator=(const SecondTableInABuilder &);
|
SecondTableInABuilder &operator=(const SecondTableInABuilder &);
|
||||||
flatbuffers::Offset<SecondTableInA> Finish() {
|
flatbuffers::Offset<SecondTableInA> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 1);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<SecondTableInA>(end);
|
auto o = flatbuffers::Offset<SecondTableInA>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -490,10 +490,10 @@ class TestByteLayout(unittest.TestCase):
|
|||||||
b.PrependBoolSlot(0, False, False)
|
b.PrependBoolSlot(0, False, False)
|
||||||
b.EndObject()
|
b.EndObject()
|
||||||
self.assertBuilderEquals(b, [
|
self.assertBuilderEquals(b, [
|
||||||
6, 0, # vtable bytes
|
4, 0, # vtable bytes
|
||||||
4, 0, # end of object from here
|
4, 0, # end of object from here
|
||||||
0, 0, # entry 1 is zero
|
# entry 1 is zero and not stored
|
||||||
6, 0, 0, 0, # offset for start of vtable (int32)
|
4, 0, 0, 0, # offset for start of vtable (int32)
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_vtable_with_one_int16(self):
|
def test_vtable_with_one_int16(self):
|
||||||
|
|||||||
@@ -863,7 +863,7 @@ void FuzzTest1() {
|
|||||||
case 10: builder.AddElement<double >(off, double_val, 0); break;
|
case 10: builder.AddElement<double >(off, double_val, 0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objects[i] = builder.EndTable(start, fields_per_object);
|
objects[i] = builder.EndTable(start);
|
||||||
}
|
}
|
||||||
builder.PreAlign<flatbuffers::largest_scalar_t>(0); // Align whole buffer.
|
builder.PreAlign<flatbuffers::largest_scalar_t>(0); // Align whole buffer.
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ struct AttackerBuilder {
|
|||||||
}
|
}
|
||||||
AttackerBuilder &operator=(const AttackerBuilder &);
|
AttackerBuilder &operator=(const AttackerBuilder &);
|
||||||
flatbuffers::Offset<Attacker> Finish() {
|
flatbuffers::Offset<Attacker> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 1);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Attacker>(end);
|
auto o = flatbuffers::Offset<Attacker>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -309,7 +309,7 @@ struct MovieBuilder {
|
|||||||
}
|
}
|
||||||
MovieBuilder &operator=(const MovieBuilder &);
|
MovieBuilder &operator=(const MovieBuilder &);
|
||||||
flatbuffers::Offset<Movie> Finish() {
|
flatbuffers::Offset<Movie> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 4);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Movie>(end);
|
auto o = flatbuffers::Offset<Movie>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user