Bitcoin ABC 0.30.5
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 typedef Size size_type;
41 typedef Diff difference_type;
42 typedef T value_type;
46 typedef const value_type *const_pointer;
47
48 class iterator {
49 T *ptr;
50
51 public:
52 typedef Diff difference_type;
53 typedef T value_type;
54 typedef T *pointer;
55 typedef T &reference;
56 typedef std::random_access_iterator_tag iterator_category;
57 iterator() : ptr(nullptr) {}
58 iterator(T *ptr_) : ptr(ptr_) {}
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:
106 typedef Diff difference_type;
107 typedef T value_type;
108 typedef T *pointer;
109 typedef T &reference;
110 typedef std::bidirectional_iterator_tag iterator_category;
111 reverse_iterator() : ptr(nullptr) {}
112 reverse_iterator(T *ptr_) : ptr(ptr_) {}
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:
143 typedef Diff difference_type;
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;
148 const_iterator() : ptr(nullptr) {}
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 }
176 return const_iterator(ptr + n);
177 }
179 ptr += n;
180 return *this;
181 }
183 return const_iterator(ptr - n);
184 }
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:
201 typedef Diff difference_type;
202 typedef const T value_type;
203 typedef const T *pointer;
204 typedef const T &reference;
205 typedef std::bidirectional_iterator_tag iterator_category;
207 const_reverse_iterator(const T *ptr_) : ptr(ptr_) {}
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
269 void change_capacity(size_type new_capacity) {
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));
290 _union.indirect_contents.capacity = new_capacity;
291 } else {
292 char *new_indirect = static_cast<char *>(
293 malloc(((size_t)sizeof(T)) * new_capacity));
294 assert(new_indirect);
295 T *src = direct_ptr(0);
296 T *dst = reinterpret_cast<T *>(new_indirect);
297 memcpy(dst, src, size() * sizeof(T));
298 _union.indirect_contents.indirect = new_indirect;
299 _union.indirect_contents.capacity = new_capacity;
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>
336 void assign(InputIterator first, InputIterator last) {
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>
357 prevector(InputIterator first, InputIterator last) {
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 : _union(std::move(other._union)), _size(other._size) {
373 other._size = 0;
374 }
375
377 if (&other == this) {
378 return *this;
379 }
380 assign(other.begin(), other.end());
381 return *this;
382 }
383
385 if (!is_direct()) {
387 }
388 _union = std::move(other._union);
389 _size = other._size;
390 other._size = 0;
391 return *this;
392 }
393
394 size_type size() const { return is_direct() ? _size : _size - N - 1; }
395
396 bool empty() const { return size() == 0; }
397
398 iterator begin() { return iterator(item_ptr(0)); }
402
405 return const_reverse_iterator(item_ptr(size() - 1));
406 }
410 }
411
412 size_t capacity() const {
413 if (is_direct()) {
414 return N;
415 } else {
417 }
418 }
419
420 T &operator[](size_type pos) { return *item_ptr(pos); }
421
422 const T &operator[](size_type pos) const { return *item_ptr(pos); }
423
424 void resize(size_type new_size) {
425 size_type cur_size = size();
426 if (cur_size == new_size) {
427 return;
428 }
429 if (cur_size > new_size) {
430 erase(item_ptr(new_size), end());
431 return;
432 }
433 if (new_size > capacity()) {
434 change_capacity(new_size);
435 }
436 ptrdiff_t increase = new_size - cur_size;
437 fill(item_ptr(cur_size), increase);
438 _size += increase;
439 }
440
441 void reserve(size_type new_capacity) {
442 if (new_capacity > capacity()) {
443 change_capacity(new_capacity);
444 }
445 }
446
448
449 void clear() { resize(0); }
450
451 iterator insert(iterator pos, const T &value) {
452 size_type p = pos - begin();
453 size_type new_size = size() + 1;
454 if (capacity() < new_size) {
455 change_capacity(new_size + (new_size >> 1));
456 }
457 T *ptr = item_ptr(p);
458 memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
459 _size++;
460 new (static_cast<void *>(ptr)) T(value);
461 return iterator(ptr);
462 }
463
464 void insert(iterator pos, size_type count, const T &value) {
465 size_type p = pos - begin();
466 size_type new_size = size() + count;
467 if (capacity() < new_size) {
468 change_capacity(new_size + (new_size >> 1));
469 }
470 T *ptr = item_ptr(p);
471 memmove(ptr + count, ptr, (size() - p) * sizeof(T));
472 _size += count;
473 fill(item_ptr(p), count, value);
474 }
475
476 template <typename InputIterator>
477 void insert(iterator pos, InputIterator first, InputIterator last) {
478 size_type p = pos - begin();
479 difference_type count = last - first;
480 size_type new_size = size() + count;
481 if (capacity() < new_size) {
482 change_capacity(new_size + (new_size >> 1));
483 }
484 T *ptr = item_ptr(p);
485 memmove(ptr + count, ptr, (size() - p) * sizeof(T));
486 _size += count;
487 fill(ptr, first, last);
488 }
489
490 inline void resize_uninitialized(size_type new_size) {
491 // resize_uninitialized changes the size of the prevector but does not
492 // initialize it. If size < new_size, the added elements must be
493 // initialized explicitly.
494 if (capacity() < new_size) {
495 change_capacity(new_size);
496 _size += new_size - size();
497 return;
498 }
499 if (new_size < size()) {
500 erase(item_ptr(new_size), end());
501 } else {
502 _size += new_size - size();
503 }
504 }
505
506 iterator erase(iterator pos) { return erase(pos, pos + 1); }
507
509 // Erase is not allowed to the change the object's capacity. That means
510 // that when starting with an indirectly allocated prevector with
511 // size and capacity > N, the result may be a still indirectly allocated
512 // prevector with size <= N and capacity > N. A shrink_to_fit() call is
513 // necessary to switch to the (more efficient) directly allocated
514 // representation (with capacity N and size <= N).
515 iterator p = first;
516 char *endp = (char *)&(*end());
517 if (!std::is_trivially_destructible<T>::value) {
518 while (p != last) {
519 (*p).~T();
520 _size--;
521 ++p;
522 }
523 } else {
524 _size -= last - p;
525 }
526 memmove(&(*first), &(*last), endp - ((char *)(&(*last))));
527 return first;
528 }
529
530 template <typename... Args> void emplace_back(Args &&...args) {
531 size_type new_size = size() + 1;
532 if (capacity() < new_size) {
533 change_capacity(new_size + (new_size >> 1));
534 }
535 new (item_ptr(size())) T(std::forward<Args>(args)...);
536 _size++;
537 }
538
539 void push_back(const T &value) { emplace_back(value); }
540
541 void pop_back() { erase(end() - 1, end()); }
542
543 T &front() { return *item_ptr(0); }
544
545 const T &front() const { return *item_ptr(0); }
546
547 T &back() { return *item_ptr(size() - 1); }
548
549 const T &back() const { return *item_ptr(size() - 1); }
550
551 void swap(prevector<N, T, Size, Diff> &other) noexcept {
552 std::swap(_union, other._union);
553 std::swap(_size, other._size);
554 }
555
557 if (!std::is_trivially_destructible<T>::value) {
558 clear();
559 }
560 if (!is_direct()) {
563 }
564 }
565
566 bool operator==(const prevector<N, T, Size, Diff> &other) const {
567 if (other.size() != size()) {
568 return false;
569 }
570 const_iterator b1 = begin();
571 const_iterator b2 = other.begin();
572 const_iterator e1 = end();
573 while (b1 != e1) {
574 if ((*b1) != (*b2)) {
575 return false;
576 }
577 ++b1;
578 ++b2;
579 }
580 return true;
581 }
582
583 bool operator!=(const prevector<N, T, Size, Diff> &other) const {
584 return !(*this == other);
585 }
586
587 bool operator<(const prevector<N, T, Size, Diff> &other) const {
588 if (size() < other.size()) {
589 return true;
590 }
591 if (size() > other.size()) {
592 return false;
593 }
594 const_iterator b1 = begin();
595 const_iterator b2 = other.begin();
596 const_iterator e1 = end();
597 while (b1 != e1) {
598 if ((*b1) < (*b2)) {
599 return true;
600 }
601 if ((*b2) < (*b1)) {
602 return false;
603 }
604 ++b1;
605 ++b2;
606 }
607 return false;
608 }
609
610 size_t allocated_memory() const {
611 if (is_direct()) {
612 return 0;
613 } else {
614 return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity;
615 }
616 }
617
618 value_type *data() { return item_ptr(0); }
619
620 const value_type *data() const { return item_ptr(0); }
621};
622
623#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_iterator(iterator x)
Definition: prevector.h:150
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
const T * operator->() const
Definition: prevector.h:210
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
iterator(T *ptr_)
Definition: prevector.h:58
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:396
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:541
iterator erase(iterator first, iterator last)
Definition: prevector.h:508
prevector(InputIterator first, InputIterator last)
Definition: prevector.h:357
void swap(prevector< N, T, Size, Diff > &other) noexcept
Definition: prevector.h:551
prevector & operator=(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:384
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:447
void clear()
Definition: prevector.h:449
value_type & reference
Definition: prevector.h:43
~prevector()
Definition: prevector.h:556
void emplace_back(Args &&...args)
Definition: prevector.h:530
size_type size() const
Definition: prevector.h:394
reverse_iterator rend()
Definition: prevector.h:407
T & front()
Definition: prevector.h:543
bool operator==(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:566
iterator erase(iterator pos)
Definition: prevector.h:506
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:412
T * direct_ptr(difference_type pos)
Definition: prevector.h:254
const_iterator end() const
Definition: prevector.h:401
const T & front() const
Definition: prevector.h:545
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:547
void insert(iterator pos, InputIterator first, InputIterator last)
Definition: prevector.h:477
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:587
value_type * data()
Definition: prevector.h:618
iterator begin()
Definition: prevector.h:398
T value_type
Definition: prevector.h:42
iterator end()
Definition: prevector.h:400
const value_type * data() const
Definition: prevector.h:620
bool operator!=(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:583
const T & back() const
Definition: prevector.h:549
void reserve(size_type new_capacity)
Definition: prevector.h:441
prevector(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:364
const T & operator[](size_type pos) const
Definition: prevector.h:422
const T * direct_ptr(difference_type pos) const
Definition: prevector.h:257
void resize_uninitialized(size_type new_size)
Definition: prevector.h:490
const_reverse_iterator rbegin() const
Definition: prevector.h:404
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:376
void resize(size_type new_size)
Definition: prevector.h:424
size_t allocated_memory() const
Definition: prevector.h:610
iterator insert(iterator pos, const T &value)
Definition: prevector.h:451
value_type * pointer
Definition: prevector.h:45
reverse_iterator rbegin()
Definition: prevector.h:403
const_reverse_iterator rend() const
Definition: prevector.h:408
prevector(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:371
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:464
void push_back(const T &value)
Definition: prevector.h:539
const_iterator begin() const
Definition: prevector.h:399
T & operator[](size_type pos)
Definition: prevector.h:420
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())