Bitcoin ABC 0.32.4
P2P Digital Currency
prevector.h
Go to the documentation of this file.
1// Copyright (c) 2015-2016 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_PREVECTOR_H
6#define BITCOIN_PREVECTOR_H
7
8#include <algorithm>
9#include <cassert>
10#include <cstddef>
11#include <cstdint>
12#include <cstdlib>
13#include <cstring>
14#include <type_traits>
15#include <utility>
16
36template <unsigned int N, typename T, typename Size = uint32_t,
37 typename Diff = int32_t>
38class prevector {
39public:
40 static constexpr unsigned int STATIC_SIZE{N};
41
42 typedef Size size_type;
43 typedef Diff difference_type;
44 typedef T value_type;
48 typedef const value_type *const_pointer;
49
50 class iterator {
51 T *ptr;
52
53 public:
54 typedef Diff difference_type;
55 typedef T value_type;
56 typedef T *pointer;
57 typedef T &reference;
58 typedef std::random_access_iterator_tag iterator_category;
59 iterator() : ptr(nullptr) {}
60 iterator(T *ptr_) : ptr(ptr_) {}
61 T &operator*() const { return *ptr; }
62 T *operator->() const { return ptr; }
63 T &operator[](size_type pos) { return ptr[pos]; }
64 const T &operator[](size_type pos) const { return ptr[pos]; }
66 ptr++;
67 return *this;
68 }
70 ptr--;
71 return *this;
72 }
74 iterator copy(*this);
75 ++(*this);
76 return copy;
77 }
79 iterator copy(*this);
80 --(*this);
81 return copy;
82 }
84 return (&(*a) - &(*b));
85 }
88 ptr += n;
89 return *this;
90 }
93 ptr -= n;
94 return *this;
95 }
96 bool operator==(iterator x) const { return ptr == x.ptr; }
97 bool operator!=(iterator x) const { return ptr != x.ptr; }
98 bool operator>=(iterator x) const { return ptr >= x.ptr; }
99 bool operator<=(iterator x) const { return ptr <= x.ptr; }
100 bool operator>(iterator x) const { return ptr > x.ptr; }
101 bool operator<(iterator x) const { return ptr < x.ptr; }
102 };
103
105 T *ptr;
106
107 public:
108 typedef Diff difference_type;
109 typedef T value_type;
110 typedef T *pointer;
111 typedef T &reference;
112 typedef std::bidirectional_iterator_tag iterator_category;
113 reverse_iterator() : ptr(nullptr) {}
114 reverse_iterator(T *ptr_) : ptr(ptr_) {}
115 T &operator*() { return *ptr; }
116 const T &operator*() const { return *ptr; }
117 T *operator->() { return ptr; }
118 const T *operator->() const { return ptr; }
120 ptr++;
121 return *this;
122 }
124 ptr--;
125 return *this;
126 }
128 reverse_iterator copy(*this);
129 ++(*this);
130 return copy;
131 }
133 reverse_iterator copy(*this);
134 --(*this);
135 return copy;
136 }
137 bool operator==(reverse_iterator x) const { return ptr == x.ptr; }
138 bool operator!=(reverse_iterator x) const { return ptr != x.ptr; }
139 };
140
142 const T *ptr;
143
144 public:
145 typedef Diff difference_type;
146 typedef const T value_type;
147 typedef const T *pointer;
148 typedef const T &reference;
149 typedef std::random_access_iterator_tag iterator_category;
150 const_iterator() : ptr(nullptr) {}
151 const_iterator(const T *ptr_) : ptr(ptr_) {}
153 const T &operator*() const { return *ptr; }
154 const T *operator->() const { return ptr; }
155 const T &operator[](size_type pos) const { return ptr[pos]; }
157 ptr++;
158 return *this;
159 }
161 ptr--;
162 return *this;
163 }
165 const_iterator copy(*this);
166 ++(*this);
167 return copy;
168 }
170 const_iterator copy(*this);
171 --(*this);
172 return copy;
173 }
175 return (&(*a) - &(*b));
176 }
178 return const_iterator(ptr + n);
179 }
181 ptr += n;
182 return *this;
183 }
185 return const_iterator(ptr - n);
186 }
188 ptr -= n;
189 return *this;
190 }
191 bool operator==(const_iterator x) const { return ptr == x.ptr; }
192 bool operator!=(const_iterator x) const { return ptr != x.ptr; }
193 bool operator>=(const_iterator x) const { return ptr >= x.ptr; }
194 bool operator<=(const_iterator x) const { return ptr <= x.ptr; }
195 bool operator>(const_iterator x) const { return ptr > x.ptr; }
196 bool operator<(const_iterator x) const { return ptr < x.ptr; }
197 };
198
200 const T *ptr;
201
202 public:
203 typedef Diff difference_type;
204 typedef const T value_type;
205 typedef const T *pointer;
206 typedef const T &reference;
207 typedef std::bidirectional_iterator_tag iterator_category;
209 const_reverse_iterator(const T *ptr_) : ptr(ptr_) {}
211 const T &operator*() const { return *ptr; }
212 const T *operator->() const { return ptr; }
214 ptr++;
215 return *this;
216 }
218 ptr--;
219 return *this;
220 }
222 const_reverse_iterator copy(*this);
223 ++(*this);
224 return copy;
225 }
227 const_reverse_iterator copy(*this);
228 --(*this);
229 return copy;
230 }
231 bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; }
232 bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; }
233 };
234
235private:
236#pragma pack(push, 1)
238 char direct[sizeof(T) * N];
239 struct {
240 char *indirect;
243 };
244#pragma pack(pop)
245 alignas(char *) direct_or_indirect _union = {};
247
248 static_assert(alignof(char *) % alignof(size_type) == 0 &&
249 sizeof(char *) % alignof(size_type) == 0,
250 "size_type cannot have more restrictive alignment "
251 "requirement than pointer");
252 static_assert(alignof(char *) % alignof(T) == 0,
253 "value_type T cannot have more restrictive alignment "
254 "requirement than pointer");
255
257 return reinterpret_cast<T *>(_union.direct) + pos;
258 }
259 const T *direct_ptr(difference_type pos) const {
260 return reinterpret_cast<const T *>(_union.direct) + pos;
261 }
263 return reinterpret_cast<T *>(_union.indirect_contents.indirect) + pos;
264 }
265 const T *indirect_ptr(difference_type pos) const {
266 return reinterpret_cast<const T *>(_union.indirect_contents.indirect) +
267 pos;
268 }
269 bool is_direct() const { return _size <= N; }
270
271 void change_capacity(size_type new_capacity) {
272 if (new_capacity <= N) {
273 if (!is_direct()) {
274 T *indirect = indirect_ptr(0);
275 T *src = indirect;
276 T *dst = direct_ptr(0);
277 memcpy(dst, src, size() * sizeof(T));
278 free(indirect);
279 _size -= N + 1;
280 }
281 } else {
282 if (!is_direct()) {
283 // FIXME: Because malloc/realloc here won't call new_handler if
284 // allocation fails, assert success. These should instead use an
285 // allocator or new/delete so that handlers are called as
286 // necessary, but performance would be slightly degraded by
287 // doing so.
288 _union.indirect_contents.indirect = static_cast<char *>(
290 ((size_t)sizeof(T)) * new_capacity));
292 _union.indirect_contents.capacity = new_capacity;
293 } else {
294 char *new_indirect = static_cast<char *>(
295 malloc(((size_t)sizeof(T)) * new_capacity));
296 assert(new_indirect);
297 T *src = direct_ptr(0);
298 T *dst = reinterpret_cast<T *>(new_indirect);
299 memcpy(dst, src, size() * sizeof(T));
300 _union.indirect_contents.indirect = new_indirect;
301 _union.indirect_contents.capacity = new_capacity;
302 _size += N + 1;
303 }
304 }
305 }
306
308 return is_direct() ? direct_ptr(pos) : indirect_ptr(pos);
309 }
310 const T *item_ptr(difference_type pos) const {
311 return is_direct() ? direct_ptr(pos) : indirect_ptr(pos);
312 }
313
314 void fill(T *dst, ptrdiff_t count, const T &value = T{}) {
315 std::fill_n(dst, count, value);
316 }
317
318 template <typename InputIterator>
319 void fill(T *dst, InputIterator first, InputIterator last) {
320 while (first != last) {
321 new (static_cast<void *>(dst)) T(*first);
322 ++dst;
323 ++first;
324 }
325 }
326
327public:
328 void assign(size_type n, const T &val) {
329 clear();
330 if (capacity() < n) {
332 }
333 _size += n;
334 fill(item_ptr(0), n, val);
335 }
336
337 template <typename InputIterator>
338 void assign(InputIterator first, InputIterator last) {
339 size_type n = last - first;
340 clear();
341 if (capacity() < n) {
343 }
344 _size += n;
345 fill(item_ptr(0), first, last);
346 }
347
349
350 explicit prevector(size_type n) { resize(n); }
351
352 explicit prevector(size_type n, const T &val) {
354 _size += n;
355 fill(item_ptr(0), n, val);
356 }
357
358 template <typename InputIterator>
359 prevector(InputIterator first, InputIterator last) {
360 size_type n = last - first;
362 _size += n;
363 fill(item_ptr(0), first, last);
364 }
365
367 size_type n = other.size();
369 _size += n;
370 fill(item_ptr(0), other.begin(), other.end());
371 }
372
374 : _union(std::move(other._union)), _size(other._size) {
375 other._size = 0;
376 }
377
379 if (&other == this) {
380 return *this;
381 }
382 assign(other.begin(), other.end());
383 return *this;
384 }
385
387 if (!is_direct()) {
389 }
390 _union = std::move(other._union);
391 _size = other._size;
392 other._size = 0;
393 return *this;
394 }
395
396 size_type size() const { return is_direct() ? _size : _size - N - 1; }
397
398 bool empty() const { return size() == 0; }
399
400 iterator begin() { return iterator(item_ptr(0)); }
404
407 return const_reverse_iterator(item_ptr(size() - 1));
408 }
412 }
413
414 size_t capacity() const {
415 if (is_direct()) {
416 return N;
417 } else {
419 }
420 }
421
422 T &operator[](size_type pos) { return *item_ptr(pos); }
423
424 const T &operator[](size_type pos) const { return *item_ptr(pos); }
425
426 void resize(size_type new_size) {
427 size_type cur_size = size();
428 if (cur_size == new_size) {
429 return;
430 }
431 if (cur_size > new_size) {
432 erase(item_ptr(new_size), end());
433 return;
434 }
435 if (new_size > capacity()) {
436 change_capacity(new_size);
437 }
438 ptrdiff_t increase = new_size - cur_size;
439 fill(item_ptr(cur_size), increase);
440 _size += increase;
441 }
442
443 void reserve(size_type new_capacity) {
444 if (new_capacity > capacity()) {
445 change_capacity(new_capacity);
446 }
447 }
448
450
451 void clear() { resize(0); }
452
453 iterator insert(iterator pos, const T &value) {
454 size_type p = pos - begin();
455 size_type new_size = size() + 1;
456 if (capacity() < new_size) {
457 change_capacity(new_size + (new_size >> 1));
458 }
459 T *ptr = item_ptr(p);
460 memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
461 _size++;
462 new (static_cast<void *>(ptr)) T(value);
463 return iterator(ptr);
464 }
465
466 void insert(iterator pos, size_type count, const T &value) {
467 size_type p = pos - begin();
468 size_type new_size = size() + count;
469 if (capacity() < new_size) {
470 change_capacity(new_size + (new_size >> 1));
471 }
472 T *ptr = item_ptr(p);
473 memmove(ptr + count, ptr, (size() - p) * sizeof(T));
474 _size += count;
475 fill(item_ptr(p), count, value);
476 }
477
478 template <typename InputIterator>
479 void insert(iterator pos, InputIterator first, InputIterator last) {
480 size_type p = pos - begin();
481 difference_type count = last - first;
482 size_type new_size = size() + count;
483 if (capacity() < new_size) {
484 change_capacity(new_size + (new_size >> 1));
485 }
486 T *ptr = item_ptr(p);
487 memmove(ptr + count, ptr, (size() - p) * sizeof(T));
488 _size += count;
489 fill(ptr, first, last);
490 }
491
492 inline void resize_uninitialized(size_type new_size) {
493 // resize_uninitialized changes the size of the prevector but does not
494 // initialize it. If size < new_size, the added elements must be
495 // initialized explicitly.
496 if (capacity() < new_size) {
497 change_capacity(new_size);
498 _size += new_size - size();
499 return;
500 }
501 if (new_size < size()) {
502 erase(item_ptr(new_size), end());
503 } else {
504 _size += new_size - size();
505 }
506 }
507
508 iterator erase(iterator pos) { return erase(pos, pos + 1); }
509
511 // Erase is not allowed to the change the object's capacity. That means
512 // that when starting with an indirectly allocated prevector with
513 // size and capacity > N, the result may be a still indirectly allocated
514 // prevector with size <= N and capacity > N. A shrink_to_fit() call is
515 // necessary to switch to the (more efficient) directly allocated
516 // representation (with capacity N and size <= N).
517 iterator p = first;
518 char *endp = (char *)&(*end());
519 if (!std::is_trivially_destructible<T>::value) {
520 while (p != last) {
521 (*p).~T();
522 _size--;
523 ++p;
524 }
525 } else {
526 _size -= last - p;
527 }
528 memmove(&(*first), &(*last), endp - ((char *)(&(*last))));
529 return first;
530 }
531
532 template <typename... Args> void emplace_back(Args &&...args) {
533 size_type new_size = size() + 1;
534 if (capacity() < new_size) {
535 change_capacity(new_size + (new_size >> 1));
536 }
537 new (item_ptr(size())) T(std::forward<Args>(args)...);
538 _size++;
539 }
540
541 void push_back(const T &value) { emplace_back(value); }
542
543 void pop_back() { erase(end() - 1, end()); }
544
545 T &front() { return *item_ptr(0); }
546
547 const T &front() const { return *item_ptr(0); }
548
549 T &back() { return *item_ptr(size() - 1); }
550
551 const T &back() const { return *item_ptr(size() - 1); }
552
553 void swap(prevector<N, T, Size, Diff> &other) noexcept {
554 std::swap(_union, other._union);
555 std::swap(_size, other._size);
556 }
557
559 if (!std::is_trivially_destructible<T>::value) {
560 clear();
561 }
562 if (!is_direct()) {
565 }
566 }
567
568 bool operator==(const prevector<N, T, Size, Diff> &other) const {
569 if (other.size() != size()) {
570 return false;
571 }
572 const_iterator b1 = begin();
573 const_iterator b2 = other.begin();
574 const_iterator e1 = end();
575 while (b1 != e1) {
576 if ((*b1) != (*b2)) {
577 return false;
578 }
579 ++b1;
580 ++b2;
581 }
582 return true;
583 }
584
585 bool operator!=(const prevector<N, T, Size, Diff> &other) const {
586 return !(*this == other);
587 }
588
589 bool operator<(const prevector<N, T, Size, Diff> &other) const {
590 if (size() < other.size()) {
591 return true;
592 }
593 if (size() > other.size()) {
594 return false;
595 }
596 const_iterator b1 = begin();
597 const_iterator b2 = other.begin();
598 const_iterator e1 = end();
599 while (b1 != e1) {
600 if ((*b1) < (*b2)) {
601 return true;
602 }
603 if ((*b2) < (*b1)) {
604 return false;
605 }
606 ++b1;
607 ++b2;
608 }
609 return false;
610 }
611
612 size_t allocated_memory() const {
613 if (is_direct()) {
614 return 0;
615 } else {
616 return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity;
617 }
618 }
619
620 value_type *data() { return item_ptr(0); }
621
622 const value_type *data() const { return item_ptr(0); }
623};
624
625#endif // BITCOIN_PREVECTOR_H
bool operator==(const_iterator x) const
Definition: prevector.h:191
const_iterator & operator++()
Definition: prevector.h:156
const_iterator & operator+=(size_type n)
Definition: prevector.h:180
bool operator<(const_iterator x) const
Definition: prevector.h:196
const_iterator & operator-=(size_type n)
Definition: prevector.h:187
std::random_access_iterator_tag iterator_category
Definition: prevector.h:149
const_iterator operator--(int)
Definition: prevector.h:169
bool operator<=(const_iterator x) const
Definition: prevector.h:194
const_iterator operator++(int)
Definition: prevector.h:164
const_iterator(const T *ptr_)
Definition: prevector.h:151
const T * operator->() const
Definition: prevector.h:154
difference_type friend operator-(const_iterator a, const_iterator b)
Definition: prevector.h:174
bool operator!=(const_iterator x) const
Definition: prevector.h:192
const_iterator operator+(size_type n)
Definition: prevector.h:177
bool operator>=(const_iterator x) const
Definition: prevector.h:193
const_iterator & operator--()
Definition: prevector.h:160
const T & operator*() const
Definition: prevector.h:153
const_iterator operator-(size_type n)
Definition: prevector.h:184
const T & operator[](size_type pos) const
Definition: prevector.h:155
bool operator>(const_iterator x) const
Definition: prevector.h:195
const_iterator(iterator x)
Definition: prevector.h:152
const_reverse_iterator(const T *ptr_)
Definition: prevector.h:209
const_reverse_iterator & operator--()
Definition: prevector.h:213
const_reverse_iterator operator--(int)
Definition: prevector.h:226
const_reverse_iterator operator++(int)
Definition: prevector.h:221
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:207
const_reverse_iterator(reverse_iterator x)
Definition: prevector.h:210
const T * operator->() const
Definition: prevector.h:212
bool operator!=(const_reverse_iterator x) const
Definition: prevector.h:232
const_reverse_iterator & operator++()
Definition: prevector.h:217
bool operator==(const_reverse_iterator x) const
Definition: prevector.h:231
bool operator<(iterator x) const
Definition: prevector.h:101
bool operator==(iterator x) const
Definition: prevector.h:96
difference_type friend operator-(iterator a, iterator b)
Definition: prevector.h:83
bool operator!=(iterator x) const
Definition: prevector.h:97
iterator & operator++()
Definition: prevector.h:65
iterator operator-(size_type n)
Definition: prevector.h:91
iterator operator--(int)
Definition: prevector.h:78
bool operator<=(iterator x) const
Definition: prevector.h:99
bool operator>=(iterator x) const
Definition: prevector.h:98
T & operator*() const
Definition: prevector.h:61
T & operator[](size_type pos)
Definition: prevector.h:63
iterator & operator+=(size_type n)
Definition: prevector.h:87
T * operator->() const
Definition: prevector.h:62
iterator & operator-=(size_type n)
Definition: prevector.h:92
iterator operator++(int)
Definition: prevector.h:73
bool operator>(iterator x) const
Definition: prevector.h:100
const T & operator[](size_type pos) const
Definition: prevector.h:64
std::random_access_iterator_tag iterator_category
Definition: prevector.h:58
iterator & operator--()
Definition: prevector.h:69
iterator operator+(size_type n)
Definition: prevector.h:86
iterator(T *ptr_)
Definition: prevector.h:60
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:112
reverse_iterator operator++(int)
Definition: prevector.h:127
reverse_iterator & operator--()
Definition: prevector.h:119
const T & operator*() const
Definition: prevector.h:116
bool operator!=(reverse_iterator x) const
Definition: prevector.h:138
const T * operator->() const
Definition: prevector.h:118
bool operator==(reverse_iterator x) const
Definition: prevector.h:137
reverse_iterator operator--(int)
Definition: prevector.h:132
reverse_iterator & operator++()
Definition: prevector.h:123
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:38
bool empty() const
Definition: prevector.h:398
prevector(size_type n)
Definition: prevector.h:350
void change_capacity(size_type new_capacity)
Definition: prevector.h:271
void fill(T *dst, ptrdiff_t count, const T &value=T{})
Definition: prevector.h:314
void pop_back()
Definition: prevector.h:543
iterator erase(iterator first, iterator last)
Definition: prevector.h:510
prevector(InputIterator first, InputIterator last)
Definition: prevector.h:359
void swap(prevector< N, T, Size, Diff > &other) noexcept
Definition: prevector.h:553
prevector & operator=(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:386
Diff difference_type
Definition: prevector.h:43
const value_type & const_reference
Definition: prevector.h:46
size_type _size
Definition: prevector.h:246
void shrink_to_fit()
Definition: prevector.h:449
void clear()
Definition: prevector.h:451
value_type & reference
Definition: prevector.h:45
~prevector()
Definition: prevector.h:558
void emplace_back(Args &&...args)
Definition: prevector.h:532
size_type size() const
Definition: prevector.h:396
reverse_iterator rend()
Definition: prevector.h:409
T & front()
Definition: prevector.h:545
bool operator==(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:568
iterator erase(iterator pos)
Definition: prevector.h:508
prevector(size_type n, const T &val)
Definition: prevector.h:352
void fill(T *dst, InputIterator first, InputIterator last)
Definition: prevector.h:319
Size size_type
Definition: prevector.h:42
const T * indirect_ptr(difference_type pos) const
Definition: prevector.h:265
size_t capacity() const
Definition: prevector.h:414
T * direct_ptr(difference_type pos)
Definition: prevector.h:256
const_iterator end() const
Definition: prevector.h:403
const T & front() const
Definition: prevector.h:547
direct_or_indirect _union
Definition: prevector.h:245
void assign(InputIterator first, InputIterator last)
Definition: prevector.h:338
bool is_direct() const
Definition: prevector.h:269
T & back()
Definition: prevector.h:549
void insert(iterator pos, InputIterator first, InputIterator last)
Definition: prevector.h:479
const T * item_ptr(difference_type pos) const
Definition: prevector.h:310
bool operator<(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:589
value_type * data()
Definition: prevector.h:620
iterator begin()
Definition: prevector.h:400
T value_type
Definition: prevector.h:44
iterator end()
Definition: prevector.h:402
const value_type * data() const
Definition: prevector.h:622
static constexpr unsigned int STATIC_SIZE
Definition: prevector.h:40
bool operator!=(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:585
const T & back() const
Definition: prevector.h:551
void reserve(size_type new_capacity)
Definition: prevector.h:443
prevector(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:366
const T & operator[](size_type pos) const
Definition: prevector.h:424
const T * direct_ptr(difference_type pos) const
Definition: prevector.h:259
void resize_uninitialized(size_type new_size)
Definition: prevector.h:492
const_reverse_iterator rbegin() const
Definition: prevector.h:406
T * item_ptr(difference_type pos)
Definition: prevector.h:307
T * indirect_ptr(difference_type pos)
Definition: prevector.h:262
prevector & operator=(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:378
void resize(size_type new_size)
Definition: prevector.h:426
size_t allocated_memory() const
Definition: prevector.h:612
iterator insert(iterator pos, const T &value)
Definition: prevector.h:453
value_type * pointer
Definition: prevector.h:47
reverse_iterator rbegin()
Definition: prevector.h:405
const_reverse_iterator rend() const
Definition: prevector.h:410
prevector(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:373
const value_type * const_pointer
Definition: prevector.h:48
void assign(size_type n, const T &val)
Definition: prevector.h:328
void insert(iterator pos, size_type count, const T &value)
Definition: prevector.h:466
void push_back(const T &value)
Definition: prevector.h:541
const_iterator begin() const
Definition: prevector.h:401
T & operator[](size_type pos)
Definition: prevector.h:422
static int count
Definition: tests.c:31
struct prevector::direct_or_indirect::@2 indirect_contents
char direct[sizeof(T) *N]
Definition: prevector.h:238
assert(!tx.IsCoinBase())