File indexing completed on 2025-08-28 08:27:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #pragma once
0019
0020 #include <algorithm>
0021 #include <cassert>
0022 #include <cstddef>
0023 #include <initializer_list>
0024 #include <iterator>
0025 #include <limits>
0026 #include <new>
0027 #include <type_traits>
0028 #include <utility>
0029
0030 #include "arrow/util/aligned_storage.h"
0031 #include "arrow/util/macros.h"
0032
0033 namespace arrow {
0034 namespace internal {
0035
0036 template <typename T, size_t N, bool NonTrivialDestructor>
0037 struct StaticVectorStorageBase {
0038 using storage_type = AlignedStorage<T>;
0039
0040 storage_type static_data_[N];
0041 size_t size_ = 0;
0042
0043 void destroy() noexcept {}
0044 };
0045
0046 template <typename T, size_t N>
0047 struct StaticVectorStorageBase<T, N, true> {
0048 using storage_type = AlignedStorage<T>;
0049
0050 storage_type static_data_[N];
0051 size_t size_ = 0;
0052
0053 ~StaticVectorStorageBase() noexcept { destroy(); }
0054
0055 void destroy() noexcept { storage_type::destroy_several(static_data_, size_); }
0056 };
0057
0058 template <typename T, size_t N, bool D = !std::is_trivially_destructible<T>::value>
0059 struct StaticVectorStorage : public StaticVectorStorageBase<T, N, D> {
0060 using Base = StaticVectorStorageBase<T, N, D>;
0061 using typename Base::storage_type;
0062
0063 using Base::size_;
0064 using Base::static_data_;
0065
0066 StaticVectorStorage() noexcept = default;
0067
0068 constexpr storage_type* storage_ptr() { return static_data_; }
0069
0070 constexpr const storage_type* const_storage_ptr() const { return static_data_; }
0071
0072
0073 void bump_size(size_t addend) {
0074 assert(size_ + addend <= N);
0075 size_ += addend;
0076 }
0077
0078 void ensure_capacity(size_t min_capacity) { assert(min_capacity <= N); }
0079
0080
0081 void reduce_size(size_t reduce_by) {
0082 assert(reduce_by <= size_);
0083 size_ -= reduce_by;
0084 }
0085
0086
0087
0088
0089
0090 void move_construct(StaticVectorStorage&& other) noexcept {
0091 size_ = other.size_;
0092 if (size_ != 0) {
0093
0094 storage_type::move_construct_several(other.static_data_, static_data_, size_, N);
0095 }
0096 }
0097
0098 constexpr size_t capacity() const { return N; }
0099
0100 constexpr size_t max_size() const { return N; }
0101
0102 void reserve(size_t n) {}
0103
0104 void clear() {
0105 storage_type::destroy_several(static_data_, size_);
0106 size_ = 0;
0107 }
0108 };
0109
0110 template <typename T, size_t N>
0111 struct SmallVectorStorage {
0112 using storage_type = AlignedStorage<T>;
0113
0114 storage_type static_data_[N];
0115 size_t size_ = 0;
0116 storage_type* data_ = static_data_;
0117 size_t dynamic_capacity_ = 0;
0118
0119 SmallVectorStorage() noexcept = default;
0120
0121 ~SmallVectorStorage() { destroy(); }
0122
0123 constexpr storage_type* storage_ptr() { return data_; }
0124
0125 constexpr const storage_type* const_storage_ptr() const { return data_; }
0126
0127 void bump_size(size_t addend) {
0128 const size_t new_size = size_ + addend;
0129 ensure_capacity(new_size);
0130 size_ = new_size;
0131 }
0132
0133 void ensure_capacity(size_t min_capacity) {
0134 if (dynamic_capacity_) {
0135
0136 if (min_capacity > dynamic_capacity_) {
0137 size_t new_capacity = std::max(dynamic_capacity_ * 2, min_capacity);
0138 reallocate_dynamic(new_capacity);
0139 }
0140 } else if (min_capacity > N) {
0141 switch_to_dynamic(min_capacity);
0142 }
0143 }
0144
0145 void reduce_size(size_t reduce_by) {
0146 assert(reduce_by <= size_);
0147 size_ -= reduce_by;
0148 }
0149
0150 void destroy() noexcept {
0151 storage_type::destroy_several(data_, size_);
0152 if (dynamic_capacity_) {
0153 delete[] data_;
0154 }
0155 }
0156
0157 void move_construct(SmallVectorStorage&& other) noexcept {
0158 size_ = other.size_;
0159 dynamic_capacity_ = other.dynamic_capacity_;
0160 if (dynamic_capacity_) {
0161 data_ = other.data_;
0162 other.data_ = other.static_data_;
0163 other.dynamic_capacity_ = 0;
0164 other.size_ = 0;
0165 } else if (size_ != 0) {
0166
0167 storage_type::move_construct_several(other.static_data_, static_data_, size_, N);
0168 }
0169 }
0170
0171 constexpr size_t capacity() const { return dynamic_capacity_ ? dynamic_capacity_ : N; }
0172
0173 constexpr size_t max_size() const { return std::numeric_limits<size_t>::max(); }
0174
0175 void reserve(size_t n) {
0176 if (dynamic_capacity_) {
0177 if (n > dynamic_capacity_) {
0178 reallocate_dynamic(n);
0179 }
0180 } else if (n > N) {
0181 switch_to_dynamic(n);
0182 }
0183 }
0184
0185 void clear() {
0186 storage_type::destroy_several(data_, size_);
0187 size_ = 0;
0188 }
0189
0190 private:
0191 void switch_to_dynamic(size_t new_capacity) {
0192 dynamic_capacity_ = new_capacity;
0193 data_ = new storage_type[new_capacity];
0194 storage_type::move_construct_several_and_destroy_source(static_data_, data_, size_);
0195 }
0196
0197 void reallocate_dynamic(size_t new_capacity) {
0198 assert(new_capacity >= size_);
0199 auto new_data = new storage_type[new_capacity];
0200 storage_type::move_construct_several_and_destroy_source(data_, new_data, size_);
0201 delete[] data_;
0202 dynamic_capacity_ = new_capacity;
0203 data_ = new_data;
0204 }
0205 };
0206
0207 template <typename T, size_t N, typename Storage>
0208 class StaticVectorImpl {
0209 private:
0210 Storage storage_;
0211
0212 T* data_ptr() { return storage_.storage_ptr()->get(); }
0213
0214 constexpr const T* const_data_ptr() const {
0215 return storage_.const_storage_ptr()->get();
0216 }
0217
0218 public:
0219 using size_type = size_t;
0220 using difference_type = ptrdiff_t;
0221 using value_type = T;
0222 using pointer = T*;
0223 using const_pointer = const T*;
0224 using reference = T&;
0225 using const_reference = const T&;
0226 using iterator = T*;
0227 using const_iterator = const T*;
0228 using reverse_iterator = std::reverse_iterator<iterator>;
0229 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0230
0231 constexpr StaticVectorImpl() noexcept = default;
0232
0233
0234 StaticVectorImpl(StaticVectorImpl&& other) noexcept {
0235 storage_.move_construct(std::move(other.storage_));
0236 }
0237
0238 StaticVectorImpl& operator=(StaticVectorImpl&& other) noexcept {
0239 if (ARROW_PREDICT_TRUE(&other != this)) {
0240
0241 storage_.destroy();
0242 storage_.move_construct(std::move(other.storage_));
0243 }
0244 return *this;
0245 }
0246
0247 StaticVectorImpl(const StaticVectorImpl& other) {
0248 init_by_copying(other.storage_.size_, other.const_data_ptr());
0249 }
0250
0251 StaticVectorImpl& operator=(const StaticVectorImpl& other) noexcept {
0252 if (ARROW_PREDICT_TRUE(&other != this)) {
0253 assign_by_copying(other.storage_.size_, other.data());
0254 }
0255 return *this;
0256 }
0257
0258
0259 StaticVectorImpl(const std::vector<T>& other) {
0260 init_by_copying(other.size(), other.data());
0261 }
0262
0263 StaticVectorImpl(std::vector<T>&& other) noexcept {
0264 init_by_moving(other.size(), other.data());
0265 }
0266
0267 StaticVectorImpl& operator=(const std::vector<T>& other) {
0268 assign_by_copying(other.size(), other.data());
0269 return *this;
0270 }
0271
0272 StaticVectorImpl& operator=(std::vector<T>&& other) noexcept {
0273 assign_by_moving(other.size(), other.data());
0274 return *this;
0275 }
0276
0277
0278 explicit StaticVectorImpl(size_t count) {
0279 storage_.bump_size(count);
0280 auto* p = storage_.storage_ptr();
0281 for (size_t i = 0; i < count; ++i) {
0282 p[i].construct();
0283 }
0284 }
0285
0286 StaticVectorImpl(size_t count, const T& value) {
0287 storage_.bump_size(count);
0288 auto* p = storage_.storage_ptr();
0289 for (size_t i = 0; i < count; ++i) {
0290 p[i].construct(value);
0291 }
0292 }
0293
0294 StaticVectorImpl(std::initializer_list<T> values) {
0295 storage_.bump_size(values.size());
0296 auto* p = storage_.storage_ptr();
0297 for (auto&& v : values) {
0298
0299 p++->construct(v);
0300 }
0301 }
0302
0303
0304
0305 constexpr bool empty() const { return storage_.size_ == 0; }
0306
0307 constexpr size_t size() const { return storage_.size_; }
0308
0309 constexpr size_t capacity() const { return storage_.capacity(); }
0310
0311 constexpr size_t max_size() const { return storage_.max_size(); }
0312
0313
0314
0315 T& operator[](size_t i) { return data_ptr()[i]; }
0316
0317 constexpr const T& operator[](size_t i) const { return const_data_ptr()[i]; }
0318
0319 T& front() { return data_ptr()[0]; }
0320
0321 constexpr const T& front() const { return const_data_ptr()[0]; }
0322
0323 T& back() { return data_ptr()[storage_.size_ - 1]; }
0324
0325 constexpr const T& back() const { return const_data_ptr()[storage_.size_ - 1]; }
0326
0327 T* data() { return data_ptr(); }
0328
0329 constexpr const T* data() const { return const_data_ptr(); }
0330
0331
0332
0333 iterator begin() { return iterator(data_ptr()); }
0334
0335 constexpr const_iterator begin() const { return const_iterator(const_data_ptr()); }
0336
0337 constexpr const_iterator cbegin() const { return const_iterator(const_data_ptr()); }
0338
0339 iterator end() { return iterator(data_ptr() + storage_.size_); }
0340
0341 constexpr const_iterator end() const {
0342 return const_iterator(const_data_ptr() + storage_.size_);
0343 }
0344
0345 constexpr const_iterator cend() const {
0346 return const_iterator(const_data_ptr() + storage_.size_);
0347 }
0348
0349 reverse_iterator rbegin() { return reverse_iterator(end()); }
0350
0351 constexpr const_reverse_iterator rbegin() const {
0352 return const_reverse_iterator(end());
0353 }
0354
0355 constexpr const_reverse_iterator crbegin() const {
0356 return const_reverse_iterator(end());
0357 }
0358
0359 reverse_iterator rend() { return reverse_iterator(begin()); }
0360
0361 constexpr const_reverse_iterator rend() const {
0362 return const_reverse_iterator(begin());
0363 }
0364
0365 constexpr const_reverse_iterator crend() const {
0366 return const_reverse_iterator(begin());
0367 }
0368
0369
0370
0371 void reserve(size_t n) { storage_.reserve(n); }
0372
0373 void clear() { storage_.clear(); }
0374
0375 void push_back(const T& value) {
0376 storage_.bump_size(1);
0377 storage_.storage_ptr()[storage_.size_ - 1].construct(value);
0378 }
0379
0380 void push_back(T&& value) {
0381 storage_.bump_size(1);
0382 storage_.storage_ptr()[storage_.size_ - 1].construct(std::move(value));
0383 }
0384
0385 template <typename... Args>
0386 void emplace_back(Args&&... args) {
0387 storage_.bump_size(1);
0388 storage_.storage_ptr()[storage_.size_ - 1].construct(std::forward<Args>(args)...);
0389 }
0390
0391 template <typename InputIt>
0392 iterator insert(const_iterator insert_at, InputIt first, InputIt last) {
0393 const size_t n = storage_.size_;
0394 const size_t it_size = static_cast<size_t>(last - first);
0395 const size_t pos = static_cast<size_t>(insert_at - const_data_ptr());
0396 storage_.bump_size(it_size);
0397 auto* p = storage_.storage_ptr();
0398 if (it_size == 0) {
0399 return p[pos].get();
0400 }
0401 const size_t end_pos = pos + it_size;
0402
0403
0404 size_t i = n;
0405 size_t j = end_pos + n - pos;
0406 while (j > std::max(n, end_pos)) {
0407 p[--j].move_construct(&p[--i]);
0408 }
0409 while (j > end_pos) {
0410 p[--j].move_assign(&p[--i]);
0411 }
0412 assert(j == end_pos);
0413
0414 j = pos;
0415 while (j < std::min(n, end_pos)) {
0416 p[j++].assign(*first++);
0417 }
0418 while (j < end_pos) {
0419 p[j++].construct(*first++);
0420 }
0421 assert(first == last);
0422 return p[pos].get();
0423 }
0424
0425 void resize(size_t n) {
0426 const size_t old_size = storage_.size_;
0427 if (n > storage_.size_) {
0428 storage_.bump_size(n - old_size);
0429 auto* p = storage_.storage_ptr();
0430 for (size_t i = old_size; i < n; ++i) {
0431 p[i].construct(T{});
0432 }
0433 } else {
0434 auto* p = storage_.storage_ptr();
0435 for (size_t i = n; i < old_size; ++i) {
0436 p[i].destroy();
0437 }
0438 storage_.reduce_size(old_size - n);
0439 }
0440 }
0441
0442 void resize(size_t n, const T& value) {
0443 const size_t old_size = storage_.size_;
0444 if (n > storage_.size_) {
0445 storage_.bump_size(n - old_size);
0446 auto* p = storage_.storage_ptr();
0447 for (size_t i = old_size; i < n; ++i) {
0448 p[i].construct(value);
0449 }
0450 } else {
0451 auto* p = storage_.storage_ptr();
0452 for (size_t i = n; i < old_size; ++i) {
0453 p[i].destroy();
0454 }
0455 storage_.reduce_size(old_size - n);
0456 }
0457 }
0458
0459 private:
0460 template <typename InputIt>
0461 void init_by_copying(size_t n, InputIt src) {
0462 storage_.bump_size(n);
0463 auto* dest = storage_.storage_ptr();
0464 for (size_t i = 0; i < n; ++i, ++src) {
0465 dest[i].construct(*src);
0466 }
0467 }
0468
0469 template <typename InputIt>
0470 void init_by_moving(size_t n, InputIt src) {
0471 init_by_copying(n, std::make_move_iterator(src));
0472 }
0473
0474 template <typename InputIt>
0475 void assign_by_copying(size_t n, InputIt src) {
0476 const size_t old_size = storage_.size_;
0477 if (n > old_size) {
0478 storage_.bump_size(n - old_size);
0479 auto* dest = storage_.storage_ptr();
0480 for (size_t i = 0; i < old_size; ++i, ++src) {
0481 dest[i].assign(*src);
0482 }
0483 for (size_t i = old_size; i < n; ++i, ++src) {
0484 dest[i].construct(*src);
0485 }
0486 } else {
0487 auto* dest = storage_.storage_ptr();
0488 for (size_t i = 0; i < n; ++i, ++src) {
0489 dest[i].assign(*src);
0490 }
0491 for (size_t i = n; i < old_size; ++i) {
0492 dest[i].destroy();
0493 }
0494 storage_.reduce_size(old_size - n);
0495 }
0496 }
0497
0498 template <typename InputIt>
0499 void assign_by_moving(size_t n, InputIt src) {
0500 assign_by_copying(n, std::make_move_iterator(src));
0501 }
0502 };
0503
0504 template <typename T, size_t N>
0505 using StaticVector = StaticVectorImpl<T, N, StaticVectorStorage<T, N>>;
0506
0507 template <typename T, size_t N>
0508 using SmallVector = StaticVectorImpl<T, N, SmallVectorStorage<T, N>>;
0509
0510 }
0511 }