MCPcopy Create free account
hub / github.com/bytedance/Fastbot_Android / ResizeContext

Class ResizeContext

native/thirdpart/flatbuffers/reflection.cpp:177–305  ·  view source on GitHub ↗

Resize a FlatBuffer in-place by iterating through all offsets in the buffer and adjusting them by "delta" if they straddle the start offset. Once that is done, bytes can now be inserted/deleted safely. "delta" may be negative (shrinking). Unless "delta" is a multiple of the largest alignment, you'll create a small amount of garbage space in the buffer (usually 0..7 bytes). If your FlatBuffer's roo

Source from the content-addressed store, hash-verified

175// If your FlatBuffer's root table is not the schema's root table, you should
176// pass in your root_table type as well.
177class ResizeContext {
178 public:
179 ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta,
180 std::vector<uint8_t> *flatbuf,
181 const reflection::Object *root_table = nullptr)
182 : schema_(schema),
183 startptr_(vector_data(*flatbuf) + start),
184 delta_(delta),
185 buf_(*flatbuf),
186 dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
187 auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1);
188 delta_ = (delta_ + mask) & ~mask;
189 if (!delta_) return; // We can't shrink by less than largest_scalar_t.
190 // Now change all the offsets by delta_.
191 auto root = GetAnyRoot(vector_data(buf_));
192 Straddle<uoffset_t, 1>(vector_data(buf_), root, vector_data(buf_));
193 ResizeTable(root_table ? *root_table : *schema.root_table(), root);
194 // We can now add or remove bytes at start.
195 if (delta_ > 0)
196 buf_.insert(buf_.begin() + start, delta_, 0);
197 else
198 buf_.erase(buf_.begin() + start + delta_, buf_.begin() + start);
199 }
200
201 // Check if the range between first (lower address) and second straddles
202 // the insertion point. If it does, change the offset at offsetloc (of
203 // type T, with direction D).
204 template<typename T, int D>
205 void Straddle(const void *first, const void *second, void *offsetloc) {
206 if (first <= startptr_ && second >= startptr_) {
207 WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
208 DagCheck(offsetloc) = true;
209 }
210 }
211
212 // This returns a boolean that records if the corresponding offset location
213 // has been modified already. If so, we can't even read the corresponding
214 // offset, since it is pointing to a location that is illegal until the
215 // resize actually happens.
216 // This must be checked for every offset, since we can't know which offsets
217 // will straddle and which won't.
218 uint8_t &DagCheck(const void *offsetloc) {
219 auto dag_idx = reinterpret_cast<const uoffset_t *>(offsetloc) -
220 reinterpret_cast<const uoffset_t *>(vector_data(buf_));
221 return dag_check_[dag_idx];
222 }
223
224 void ResizeTable(const reflection::Object &objectdef, Table *table) {
225 if (DagCheck(table)) return; // Table already visited.
226 auto vtable = table->GetVTable();
227 // Early out: since all fields inside the table must point forwards in
228 // memory, if the insertion point is before the table we can stop here.
229 auto tableloc = reinterpret_cast<uint8_t *>(table);
230 if (startptr_ <= tableloc) {
231 // Check if insertion point is between the table and a vtable that
232 // precedes it. This can't happen in current construction code, but check
233 // just in case we ever change the way flatbuffers are built.
234 Straddle<soffset_t, -1>(vtable, table, table);

Callers 2

SetStringFunction · 0.85
ResizeAnyVectorFunction · 0.85

Calls 1

vector_dataFunction · 0.85

Tested by

no test coverage detected