File indexing completed on 2025-08-27 09:30:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
0018 #define FLATBUFFERS_VECTOR_DOWNWARD_H_
0019
0020 #include <algorithm>
0021 #include <cstdint>
0022
0023 #include "flatbuffers/base.h"
0024 #include "flatbuffers/default_allocator.h"
0025 #include "flatbuffers/detached_buffer.h"
0026
0027 namespace flatbuffers {
0028
0029
0030
0031
0032
0033
0034
0035 template<typename SizeT = uoffset_t> class vector_downward {
0036 public:
0037 explicit vector_downward(size_t initial_size, Allocator *allocator,
0038 bool own_allocator, size_t buffer_minalign,
0039 const SizeT max_size = FLATBUFFERS_MAX_BUFFER_SIZE)
0040 : allocator_(allocator),
0041 own_allocator_(own_allocator),
0042 initial_size_(initial_size),
0043 max_size_(max_size),
0044 buffer_minalign_(buffer_minalign),
0045 reserved_(0),
0046 size_(0),
0047 buf_(nullptr),
0048 cur_(nullptr),
0049 scratch_(nullptr) {}
0050
0051 vector_downward(vector_downward &&other) noexcept
0052
0053 : allocator_(other.allocator_),
0054 own_allocator_(other.own_allocator_),
0055 initial_size_(other.initial_size_),
0056 max_size_(other.max_size_),
0057 buffer_minalign_(other.buffer_minalign_),
0058 reserved_(other.reserved_),
0059 size_(other.size_),
0060 buf_(other.buf_),
0061 cur_(other.cur_),
0062 scratch_(other.scratch_) {
0063
0064
0065
0066 other.own_allocator_ = false;
0067 other.reserved_ = 0;
0068 other.buf_ = nullptr;
0069 other.cur_ = nullptr;
0070 other.scratch_ = nullptr;
0071 }
0072
0073 vector_downward &operator=(vector_downward &&other) noexcept {
0074
0075 vector_downward temp(std::move(other));
0076 swap(temp);
0077 return *this;
0078 }
0079
0080 ~vector_downward() {
0081 clear_buffer();
0082 clear_allocator();
0083 }
0084
0085 void reset() {
0086 clear_buffer();
0087 clear();
0088 }
0089
0090 void clear() {
0091 if (buf_) {
0092 cur_ = buf_ + reserved_;
0093 } else {
0094 reserved_ = 0;
0095 cur_ = nullptr;
0096 }
0097 size_ = 0;
0098 clear_scratch();
0099 }
0100
0101 void clear_scratch() { scratch_ = buf_; }
0102
0103 void clear_allocator() {
0104 if (own_allocator_ && allocator_) { delete allocator_; }
0105 allocator_ = nullptr;
0106 own_allocator_ = false;
0107 }
0108
0109 void clear_buffer() {
0110 if (buf_) Deallocate(allocator_, buf_, reserved_);
0111 buf_ = nullptr;
0112 }
0113
0114
0115 uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
0116 auto *buf = buf_;
0117 allocated_bytes = reserved_;
0118 offset = vector_downward::offset();
0119
0120
0121
0122 buf_ = nullptr;
0123 clear();
0124 return buf;
0125 }
0126
0127
0128 DetachedBuffer release() {
0129
0130 DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
0131 size());
0132 if (own_allocator_) {
0133 allocator_ = nullptr;
0134 own_allocator_ = false;
0135 }
0136 buf_ = nullptr;
0137 clear();
0138 return fb;
0139 }
0140
0141 size_t ensure_space(size_t len) {
0142 FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
0143
0144
0145 if (len > unused_buffer_size()) { reallocate(len); }
0146 FLATBUFFERS_ASSERT(size() < max_size_);
0147 return len;
0148 }
0149
0150 inline uint8_t *make_space(size_t len) {
0151 if (len) {
0152 ensure_space(len);
0153 cur_ -= len;
0154 size_ += static_cast<SizeT>(len);
0155 }
0156 return cur_;
0157 }
0158
0159
0160 Allocator *get_custom_allocator() { return allocator_; }
0161
0162
0163 size_t offset() const { return cur_ - buf_; }
0164
0165
0166 inline SizeT size() const { return size_; }
0167
0168
0169 SizeT unused_buffer_size() const {
0170 return static_cast<SizeT>(cur_ - scratch_);
0171 }
0172
0173
0174 SizeT scratch_size() const { return static_cast<SizeT>(scratch_ - buf_); }
0175
0176 size_t capacity() const { return reserved_; }
0177
0178 uint8_t *data() const {
0179 FLATBUFFERS_ASSERT(cur_);
0180 return cur_;
0181 }
0182
0183 uint8_t *scratch_data() const {
0184 FLATBUFFERS_ASSERT(buf_);
0185 return buf_;
0186 }
0187
0188 uint8_t *scratch_end() const {
0189 FLATBUFFERS_ASSERT(scratch_);
0190 return scratch_;
0191 }
0192
0193 uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
0194
0195 void push(const uint8_t *bytes, size_t num) {
0196 if (num > 0) { memcpy(make_space(num), bytes, num); }
0197 }
0198
0199
0200 template<typename T> void push_small(const T &little_endian_t) {
0201 make_space(sizeof(T));
0202 *reinterpret_cast<T *>(cur_) = little_endian_t;
0203 }
0204
0205 template<typename T> void scratch_push_small(const T &t) {
0206 ensure_space(sizeof(T));
0207 *reinterpret_cast<T *>(scratch_) = t;
0208 scratch_ += sizeof(T);
0209 }
0210
0211
0212
0213 void fill(size_t zero_pad_bytes) {
0214 make_space(zero_pad_bytes);
0215 for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
0216 }
0217
0218
0219
0220 void fill_big(size_t zero_pad_bytes) {
0221 memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
0222 }
0223
0224 void pop(size_t bytes_to_remove) {
0225 cur_ += bytes_to_remove;
0226 size_ -= static_cast<SizeT>(bytes_to_remove);
0227 }
0228
0229 void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
0230
0231 void swap(vector_downward &other) {
0232 using std::swap;
0233 swap(allocator_, other.allocator_);
0234 swap(own_allocator_, other.own_allocator_);
0235 swap(initial_size_, other.initial_size_);
0236 swap(buffer_minalign_, other.buffer_minalign_);
0237 swap(reserved_, other.reserved_);
0238 swap(size_, other.size_);
0239 swap(max_size_, other.max_size_);
0240 swap(buf_, other.buf_);
0241 swap(cur_, other.cur_);
0242 swap(scratch_, other.scratch_);
0243 }
0244
0245 void swap_allocator(vector_downward &other) {
0246 using std::swap;
0247 swap(allocator_, other.allocator_);
0248 swap(own_allocator_, other.own_allocator_);
0249 }
0250
0251 private:
0252
0253 FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &));
0254 FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &));
0255
0256 Allocator *allocator_;
0257 bool own_allocator_;
0258 size_t initial_size_;
0259
0260
0261 SizeT max_size_;
0262 size_t buffer_minalign_;
0263 size_t reserved_;
0264 SizeT size_;
0265 uint8_t *buf_;
0266 uint8_t *cur_;
0267 uint8_t *scratch_;
0268
0269 void reallocate(size_t len) {
0270 auto old_reserved = reserved_;
0271 auto old_size = size();
0272 auto old_scratch_size = scratch_size();
0273 reserved_ +=
0274 (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
0275 reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
0276 if (buf_) {
0277 buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
0278 old_size, old_scratch_size);
0279 } else {
0280 buf_ = Allocate(allocator_, reserved_);
0281 }
0282 cur_ = buf_ + reserved_ - old_size;
0283 scratch_ = buf_ + old_scratch_size;
0284 }
0285 };
0286
0287 }
0288
0289 #endif