62 static constexpr std::size_t SIZES_SIZE =
sizeof(SIZE_T) /
sizeof(T);
63 static constexpr std::size_t SIZES_OFFSET = N * SIZES_SIZE;
66 using size_type = SIZE_T;
67 using difference_type = std::ptrdiff_t;
68 using reference = std::conditional_t<1 == T_NUM, T&, std::array<T, T_NUM>&>;
69 using const_reference =
70 std::conditional_t<1 == T_NUM, T const&, std::array<T, T_NUM>
const&>;
71 using pointer = std::conditional_t<1 == T_NUM, T*, std::array<T, T_NUM>*>;
73 std::conditional_t<1 == T_NUM, T const*, std::array<T, T_NUM>
const*>;
74 using iterator = std::conditional_t<1 == T_NUM, T*, std::array<T, T_NUM>*>;
75 using const_iterator =
76 std::conditional_t<1 == T_NUM, T const*, std::array<T, T_NUM>
const*>;
77 using reverse_iterator = std::reverse_iterator<iterator>;
78 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
79 using Query = IteratorWrapper<iterator>;
80 using ConstQuery = IteratorWrapper<const_iterator>;
81 using ReverseQuery = IteratorWrapper<reverse_iterator>;
82 using ReverseConstQuery = IteratorWrapper<const_reverse_iterator>;
101 [[nodiscard]] iterator begin() {
return begin(0); }
103 [[nodiscard]] const_iterator begin()
const {
return begin(0); }
105 [[nodiscard]] const_iterator cbegin()
const {
return cbegin(); }
107 [[nodiscard]] iterator end() {
return end(N - 1); }
109 [[nodiscard]] const_iterator end()
const {
return end(N - 1); }
111 [[nodiscard]] const_iterator cend()
const {
return end(); }
113 [[nodiscard]] iterator begin(std::size_t pos)
115 return reinterpret_cast<iterator
>(data_ ? data_.get() + offset(pos) :
nullptr);
118 [[nodiscard]] const_iterator begin(std::size_t pos)
const
120 return reinterpret_cast<const_iterator
>(data_ ? data_.get() + offset(pos) :
nullptr);
123 [[nodiscard]] const_iterator cbegin(std::size_t pos)
const {
return begin(pos); }
125 [[nodiscard]] iterator end(std::size_t pos)
127 return reinterpret_cast<iterator
>(data_ ? data_.get() + offset(pos + 1) :
nullptr);
130 [[nodiscard]] const_iterator end(std::size_t pos)
const
132 return reinterpret_cast<const_iterator
>(data_ ? data_.get() + offset(pos + 1)
136 [[nodiscard]] const_iterator cend(std::size_t pos)
const {
return end(pos); }
138 [[nodiscard]] reverse_iterator rbegin() {
return std::make_reverse_iterator(end()); }
140 [[nodiscard]] const_iterator rbegin()
const
142 return std::make_reverse_iterator(end());
145 [[nodiscard]] const_iterator crbegin()
const {
return crbegin(); }
147 [[nodiscard]] iterator rend() {
return std::make_reverse_iterator(begin()); }
149 [[nodiscard]] const_iterator rend()
const
151 return std::make_reverse_iterator(begin());
154 [[nodiscard]] const_iterator crend()
const {
return rend(); }
156 [[nodiscard]] iterator rbegin(std::size_t pos)
158 return std::make_reverse_iterator(end(pos));
161 [[nodiscard]] const_iterator rbegin(std::size_t pos)
const
163 return std::make_reverse_iterator(end(pos));
166 [[nodiscard]] const_iterator crbegin(std::size_t pos)
const {
return rbegin(pos); }
168 [[nodiscard]] iterator rend(std::size_t pos)
170 return std::make_reverse_iterator(begin(pos));
173 [[nodiscard]] const_iterator rend(std::size_t pos)
const
175 return std::make_reverse_iterator(begin(pos));
178 [[nodiscard]] const_iterator crend(std::size_t pos)
const {
return rend(pos); }
184 [[nodiscard]] Query query() {
return {begin(), end()}; }
186 [[nodiscard]] Query query(std::size_t pos) {
return {begin(pos), end(pos)}; }
188 [[nodiscard]] ConstQuery query()
const {
return {begin(), end()}; }
190 [[nodiscard]] ConstQuery query(std::size_t pos)
const {
return {begin(pos), end(pos)}; }
192 [[nodiscard]] ReverseQuery rquery() {
return {rbegin(), rend()}; }
194 [[nodiscard]] ReverseQuery rquery(std::size_t pos) {
return {rbegin(pos), rend(pos)}; }
196 [[nodiscard]] ReverseConstQuery rquery()
const {
return {rbegin(), rend()}; }
198 [[nodiscard]] ReverseConstQuery rquery(std::size_t pos)
const
200 return {rbegin(pos), rend(pos)};
207 T* data() {
return data(0); }
209 T
const* data()
const {
return data(0); }
211 T* data(std::size_t pos) {
return data_.get() + offset(pos); }
213 T
const* data(std::size_t pos)
const {
return data_.get() + offset(pos); }
219 reference operator()(std::size_t idx) {
return operator()(0, idx); }
221 const_reference operator()(std::size_t idx)
const {
return operator()(0, idx); }
223 reference operator()(std::size_t pos, std::size_t idx)
225 return reinterpret_cast<reference
>(data_[offset(pos) + T_NUM * idx]);
228 const_reference operator()(std::size_t pos, std::size_t idx)
const
230 return reinterpret_cast<const_reference
>(data_[offset(pos) + T_NUM * idx]);
244 void clear(std::size_t pos)
246 if (size() == size(pos)) {
257 [[nodiscard]]
bool empty()
const {
return nullptr == data_; }
259 [[nodiscard]]
bool empty(std::size_t pos)
const {
return 0 == size(pos); }
265 [[nodiscard]] std::size_t size()
const
268 return std::accumulate(std::cbegin(s), std::cend(s), std::size_t(0));
271 [[nodiscard]] std::size_t size(std::size_t pos)
const
273 return data_ ? *(
reinterpret_cast<size_type const*
>(data_.get()) + pos) : 0;
276 [[nodiscard]] std::array<size_type, N> sizes()
const
279 return std::array<size_type, N>{};
282 size_type
const* it =
reinterpret_cast<size_type const*
>(data_.get());
284 std::array<size_type, N> s;
285 std::copy(it, it + N, s.data());
307 [[nodiscard]] std::size_t offset(std::size_t pos)
const
309 size_type
const* it =
reinterpret_cast<size_type const*
>(data_.get());
310 return data_ ? SIZES_OFFSET + T_NUM * std::accumulate(it, it + pos, std::size_t(0))
318 void resize(std::size_t count)
323 }
else if (size() == count) {
327 T* p_cur = data_.release();
328 T* p_new = allocate(p_cur, count);
332 throw std::bad_alloc();
337 auto it =
reinterpret_cast<SIZE_T*
>(data_.get());
338 *it =
static_cast<SIZE_T
>(count);
339 std::fill(it + 1, it + N, SIZE_T(0));
342 void resize(std::size_t pos, std::size_t count)
344 auto cur_sizes = sizes();
346 std::accumulate(std::cbegin(cur_sizes), std::cend(cur_sizes), std::size_t(0));
347 auto cur_count = cur_sizes[pos];
349 if (cur_count == count) {
351 }
else if (0 == count && cur_size == cur_count) {
356 if (count < cur_count && N - 1 != pos) {
357#if __cplusplus >= 202002L
358 std::copy(std::to_address(begin(pos + 1)), std::to_address(end()),
359 std::to_address(begin(pos) + count));
361 std::copy(begin(pos + 1), end(), begin(pos) + count);
365 bool was_empty = empty();
367 T* p_cur = data_.release();
368 T* p_new = allocate(p_cur, cur_size + count - cur_count);
372 throw std::bad_alloc();
378 auto it =
reinterpret_cast<SIZE_T*
>(data_.get());
379 std::fill(it, it + N, SIZE_T(0));
381 if (count > cur_count && N - 1 != pos) {
382#if __cplusplus >= 202002L
383 std::copy_backward(std::to_address(begin(pos + 1)), std::to_address(end()),
384 std::to_address(end() + (count - cur_count)));
386 std::copy_backward(begin(pos + 1), end(), end() + (count - cur_count));
391 reinterpret_cast<SIZE_T&
>(data_[SIZES_SIZE * pos]) =
static_cast<SIZE_T
>(count);
398 [[nodiscard]] std::size_t memoryUsage()
400 return empty() ? 0 : N *
sizeof(SIZE_T) + size() * T_NUM *
sizeof(T);
403 [[nodiscard]] std::size_t memoryUsage(std::size_t pos)
405 return empty(pos) ? 0 : size(pos) * T_NUM *
sizeof(T);
412 std::size_t serializedSize()
const {
return sizeof(std::uint32_t) + memoryUsage(); }
417 in.read(&s,
sizeof(s));
420 in.read(data_.get(), memoryUsage());
427 in.read(&s,
sizeof(s));
430 in.read(data(pos), memoryUsage(pos));
436 std::uint32_t s = size();
437 out.write(&s,
sizeof(s));
439 out.write(data_.get(), memoryUsage());
445 std::uint32_t s = size(pos);
446 out.write(&s,
sizeof(s));
448 out.write(data(pos), memoryUsage(pos));
457 T* allocate(T* p, std::size_t s)
459 return static_cast<T*
>(realloc(p, N *
sizeof(SIZE_T) + s * T_NUM *
sizeof(T)));
464 void operator()(
void* x) { free(x); }
467 std::unique_ptr<T[], free_delete> data_;