mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-06 21:37:36 +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:
@@ -704,8 +704,8 @@ class FlatBufferBuilder
|
||||
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
||||
Allocator *allocator = nullptr,
|
||||
bool own_allocator = false)
|
||||
: buf_(initial_size, allocator, own_allocator), nested(false),
|
||||
finished(false), minalign_(1), force_defaults_(false),
|
||||
: buf_(initial_size, allocator, own_allocator), max_voffset_(0),
|
||||
nested(false), finished(false), minalign_(1), force_defaults_(false),
|
||||
dedup_vtables_(true), string_pool(nullptr) {
|
||||
offsetbuf_.reserve(16); // Avoid first few reallocs.
|
||||
vtables_.reserve(16);
|
||||
@@ -725,7 +725,7 @@ class FlatBufferBuilder
|
||||
/// to construct another buffer.
|
||||
void Clear() {
|
||||
buf_.clear();
|
||||
offsetbuf_.clear();
|
||||
ClearOffsets();
|
||||
nested = false;
|
||||
finished = false;
|
||||
vtables_.clear();
|
||||
@@ -839,6 +839,7 @@ class FlatBufferBuilder
|
||||
void TrackField(voffset_t field, uoffset_t off) {
|
||||
FieldLoc fl = { off, field };
|
||||
offsetbuf_.push_back(fl);
|
||||
max_voffset_ = (std::max)(max_voffset_, field);
|
||||
}
|
||||
|
||||
// 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
|
||||
// table, comparing it against existing vtables, and writing the
|
||||
// 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.
|
||||
assert(nested);
|
||||
// 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.
|
||||
// It starts with the number of offsets, followed by a type id, followed
|
||||
// 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;
|
||||
assert(table_object_size < 0x10000); // Vtable use 16bit offsets.
|
||||
PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
|
||||
PushElement<voffset_t>(FieldIndexToOffset(numfields));
|
||||
WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
|
||||
static_cast<voffset_t>(table_object_size));
|
||||
WriteScalar<voffset_t>(buf_.data(), max_voffset_);
|
||||
// Write the offsets into the table
|
||||
for (auto field_location = offsetbuf_.begin();
|
||||
field_location != offsetbuf_.end();
|
||||
@@ -922,7 +929,7 @@ class FlatBufferBuilder
|
||||
assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
|
||||
WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
|
||||
}
|
||||
offsetbuf_.clear();
|
||||
ClearOffsets();
|
||||
auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
|
||||
auto vt1_size = ReadScalar<voffset_t>(vt1);
|
||||
auto vt_use = GetSize();
|
||||
@@ -955,6 +962,11 @@ class FlatBufferBuilder
|
||||
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
|
||||
// just been constructed.
|
||||
template<typename T> void Required(Offset<T> table, voffset_t field) {
|
||||
@@ -973,7 +985,10 @@ class FlatBufferBuilder
|
||||
|
||||
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
|
||||
// after it with "alignment" without padding.
|
||||
@@ -1510,6 +1525,9 @@ class FlatBufferBuilder
|
||||
|
||||
// Accumulating offsets of table members while it is being built.
|
||||
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.
|
||||
bool nested;
|
||||
|
||||
@@ -42,6 +42,29 @@ enum BaseType {
|
||||
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() {
|
||||
static const char *names[] = {
|
||||
"None",
|
||||
@@ -113,7 +136,7 @@ struct TypeBuilder {
|
||||
}
|
||||
TypeBuilder &operator=(const TypeBuilder &);
|
||||
flatbuffers::Offset<Type> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 3);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Type>(end);
|
||||
return o;
|
||||
}
|
||||
@@ -173,7 +196,7 @@ struct KeyValueBuilder {
|
||||
}
|
||||
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
||||
flatbuffers::Offset<KeyValue> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 2);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<KeyValue>(end);
|
||||
fbb_.Required(o, KeyValue::VT_KEY);
|
||||
return o;
|
||||
@@ -266,7 +289,7 @@ struct EnumValBuilder {
|
||||
}
|
||||
EnumValBuilder &operator=(const EnumValBuilder &);
|
||||
flatbuffers::Offset<EnumVal> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 4);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<EnumVal>(end);
|
||||
fbb_.Required(o, EnumVal::VT_NAME);
|
||||
return o;
|
||||
@@ -381,7 +404,7 @@ struct EnumBuilder {
|
||||
}
|
||||
EnumBuilder &operator=(const EnumBuilder &);
|
||||
flatbuffers::Offset<Enum> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 6);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Enum>(end);
|
||||
fbb_.Required(o, Enum::VT_NAME);
|
||||
fbb_.Required(o, Enum::VT_VALUES);
|
||||
@@ -544,7 +567,7 @@ struct FieldBuilder {
|
||||
}
|
||||
FieldBuilder &operator=(const FieldBuilder &);
|
||||
flatbuffers::Offset<Field> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 11);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Field>(end);
|
||||
fbb_.Required(o, Field::VT_NAME);
|
||||
fbb_.Required(o, Field::VT_TYPE);
|
||||
@@ -695,7 +718,7 @@ struct ObjectBuilder {
|
||||
}
|
||||
ObjectBuilder &operator=(const ObjectBuilder &);
|
||||
flatbuffers::Offset<Object> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 7);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Object>(end);
|
||||
fbb_.Required(o, Object::VT_NAME);
|
||||
fbb_.Required(o, Object::VT_FIELDS);
|
||||
@@ -808,7 +831,7 @@ struct SchemaBuilder {
|
||||
}
|
||||
SchemaBuilder &operator=(const SchemaBuilder &);
|
||||
flatbuffers::Offset<Schema> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 5);
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Schema>(end);
|
||||
fbb_.Required(o, Schema::VT_OBJECTS);
|
||||
fbb_.Required(o, Schema::VT_ENUMS);
|
||||
|
||||
Reference in New Issue
Block a user