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