uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
- // push() & fill() are most frequently called with small byte counts (<= 4),
- // which is why we're using loops rather than calling memcpy/memset.
void push(const uint8_t *bytes, size_t num) {
auto dest = make_space(num);
- for (size_t i = 0; i < num; i++) dest[i] = bytes[i];
+ memcpy(dest, bytes, num);
}
+ // Specialized version of push() that avoids memcpy call for small data.
+ template<typename T> void push_small(T little_endian_t) {
+ auto dest = make_space(sizeof(T));
+ *reinterpret_cast<T *>(dest) = little_endian_t;
+ }
+
+ // fill() is most frequently called with small byte counts (<= 4),
+ // which is why we're using loops rather than calling memset.
void fill(size_t zero_pad_bytes) {
auto dest = make_space(zero_pad_bytes);
for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
}
+ // Version for when we know the size is larger.
+ void fill_big(size_t zero_pad_bytes) {
+ auto dest = make_space(zero_pad_bytes);
+ memset(dest, 0, zero_pad_bytes);
+ }
+
void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
private:
AssertScalarT<T>();
T litle_endian_element = EndianScalar(element);
Align(sizeof(T));
- PushBytes(reinterpret_cast<uint8_t *>(&litle_endian_element), sizeof(T));
+ buf_.push_small(litle_endian_element);
return GetSize();
}
template<typename T> void AddStruct(voffset_t field, const T *structptr) {
if (!structptr) return; // Default, don't store.
Align(AlignOf<T>());
- PushBytes(reinterpret_cast<const uint8_t *>(structptr), sizeof(T));
+ buf_.push_small(*structptr);
TrackField(field, GetSize());
}
// 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(numfields * sizeof(voffset_t));
+ buf_.fill_big(numfields * sizeof(voffset_t));
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));
minalign_);
if (file_identifier) {
assert(strlen(file_identifier) == kFileIdentifierLength);
- buf_.push(reinterpret_cast<const uint8_t *>(file_identifier),
+ PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
kFileIdentifierLength);
}
PushElement(ReferTo(root)); // Location of root.