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