BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
prevector.h
Go to the documentation of this file.
1 // Copyright (c) 2015-2018 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 <assert.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <cstddef>
14 #include <iterator>
15 #include <type_traits>
16 
17 #include <compat.h>
18 
19 #pragma pack(push, 1)
20 
38 template<unsigned int N, typename T, typename Size = uint32_t, typename Diff = int32_t>
39 class prevector {
40 public:
41  typedef Size size_type;
42  typedef Diff difference_type;
43  typedef T value_type;
45  typedef const value_type& const_reference;
46  typedef value_type* pointer;
47  typedef const value_type* const_pointer;
48 
49  class iterator {
50  T* ptr;
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(T* ptr_) : ptr(ptr_) {}
58  T& operator*() const { return *ptr; }
59  T* operator->() const { return ptr; }
60  T& operator[](size_type pos) { return ptr[pos]; }
61  const T& operator[](size_type pos) const { return ptr[pos]; }
62  iterator& operator++() { ptr++; return *this; }
63  iterator& operator--() { ptr--; return *this; }
64  iterator operator++(int) { iterator copy(*this); ++(*this); return copy; }
65  iterator operator--(int) { iterator copy(*this); --(*this); return copy; }
66  difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); }
67  iterator operator+(size_type n) { return iterator(ptr + n); }
68  iterator& operator+=(size_type n) { ptr += n; return *this; }
69  iterator operator-(size_type n) { return iterator(ptr - n); }
70  iterator& operator-=(size_type n) { ptr -= n; return *this; }
71  bool operator==(iterator x) const { return ptr == x.ptr; }
72  bool operator!=(iterator x) const { return ptr != x.ptr; }
73  bool operator>=(iterator x) const { return ptr >= x.ptr; }
74  bool operator<=(iterator x) const { return ptr <= x.ptr; }
75  bool operator>(iterator x) const { return ptr > x.ptr; }
76  bool operator<(iterator x) const { return ptr < x.ptr; }
77  };
78 
80  T* ptr;
81  public:
82  typedef Diff difference_type;
83  typedef T value_type;
84  typedef T* pointer;
85  typedef T& reference;
86  typedef std::bidirectional_iterator_tag iterator_category;
87  reverse_iterator(T* ptr_) : ptr(ptr_) {}
88  T& operator*() { return *ptr; }
89  const T& operator*() const { return *ptr; }
90  T* operator->() { return ptr; }
91  const T* operator->() const { return ptr; }
92  reverse_iterator& operator--() { ptr++; return *this; }
93  reverse_iterator& operator++() { ptr--; return *this; }
94  reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; }
95  reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; }
96  bool operator==(reverse_iterator x) const { return ptr == x.ptr; }
97  bool operator!=(reverse_iterator x) const { return ptr != x.ptr; }
98  };
99 
101  const T* ptr;
102  public:
103  typedef Diff difference_type;
104  typedef const T value_type;
105  typedef const T* pointer;
106  typedef const T& reference;
107  typedef std::random_access_iterator_tag iterator_category;
108  const_iterator(const T* ptr_) : ptr(ptr_) {}
109  const_iterator(iterator x) : ptr(&(*x)) {}
110  const T& operator*() const { return *ptr; }
111  const T* operator->() const { return ptr; }
112  const T& operator[](size_type pos) const { return ptr[pos]; }
113  const_iterator& operator++() { ptr++; return *this; }
114  const_iterator& operator--() { ptr--; return *this; }
115  const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; }
116  const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; }
117  difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); }
119  const_iterator& operator+=(size_type n) { ptr += n; return *this; }
121  const_iterator& operator-=(size_type n) { ptr -= n; return *this; }
122  bool operator==(const_iterator x) const { return ptr == x.ptr; }
123  bool operator!=(const_iterator x) const { return ptr != x.ptr; }
124  bool operator>=(const_iterator x) const { return ptr >= x.ptr; }
125  bool operator<=(const_iterator x) const { return ptr <= x.ptr; }
126  bool operator>(const_iterator x) const { return ptr > x.ptr; }
127  bool operator<(const_iterator x) const { return ptr < x.ptr; }
128  };
129 
131  const T* ptr;
132  public:
133  typedef Diff difference_type;
134  typedef const T value_type;
135  typedef const T* pointer;
136  typedef const T& reference;
137  typedef std::bidirectional_iterator_tag iterator_category;
138  const_reverse_iterator(const T* ptr_) : ptr(ptr_) {}
140  const T& operator*() const { return *ptr; }
141  const T* operator->() const { return ptr; }
142  const_reverse_iterator& operator--() { ptr++; return *this; }
143  const_reverse_iterator& operator++() { ptr--; return *this; }
144  const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; }
145  const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; }
146  bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; }
147  bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; }
148  };
149 
150 private:
153  char direct[sizeof(T) * N];
154  struct {
156  char* indirect;
157  };
158  } _union;
159 
160  T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
161  const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
162  T* indirect_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.indirect) + pos; }
163  const T* indirect_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.indirect) + pos; }
164  bool is_direct() const { return _size <= N; }
165 
166  void change_capacity(size_type new_capacity) {
167  if (new_capacity <= N) {
168  if (!is_direct()) {
169  T* indirect = indirect_ptr(0);
170  T* src = indirect;
171  T* dst = direct_ptr(0);
172  memcpy(dst, src, size() * sizeof(T));
173  free(indirect);
174  _size -= N + 1;
175  }
176  } else {
177  if (!is_direct()) {
178  /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
179  success. These should instead use an allocator or new/delete so that handlers
180  are called as necessary, but performance would be slightly degraded by doing so. */
181  _union.indirect = static_cast<char*>(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity));
182  assert(_union.indirect);
183  _union.capacity = new_capacity;
184  } else {
185  char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
186  assert(new_indirect);
187  T* src = direct_ptr(0);
188  T* dst = reinterpret_cast<T*>(new_indirect);
189  memcpy(dst, src, size() * sizeof(T));
190  _union.indirect = new_indirect;
191  _union.capacity = new_capacity;
192  _size += N + 1;
193  }
194  }
195  }
196 
197  T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
198  const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
199 
200  void fill(T* dst, ptrdiff_t count) {
201  if (IS_TRIVIALLY_CONSTRUCTIBLE<T>::value) {
202  // The most common use of prevector is where T=unsigned char. For
203  // trivially constructible types, we can use memset() to avoid
204  // looping.
205  ::memset(dst, 0, count * sizeof(T));
206  } else {
207  for (auto i = 0; i < count; ++i) {
208  new(static_cast<void*>(dst + i)) T();
209  }
210  }
211  }
212 
213  void fill(T* dst, ptrdiff_t count, const T& value) {
214  for (auto i = 0; i < count; ++i) {
215  new(static_cast<void*>(dst + i)) T(value);
216  }
217  }
218 
219  template<typename InputIterator>
220  void fill(T* dst, InputIterator first, InputIterator last) {
221  while (first != last) {
222  new(static_cast<void*>(dst)) T(*first);
223  ++dst;
224  ++first;
225  }
226  }
227 
228 public:
229  void assign(size_type n, const T& val) {
230  clear();
231  if (capacity() < n) {
232  change_capacity(n);
233  }
234  _size += n;
235  fill(item_ptr(0), n, val);
236  }
237 
238  template<typename InputIterator>
239  void assign(InputIterator first, InputIterator last) {
240  size_type n = last - first;
241  clear();
242  if (capacity() < n) {
243  change_capacity(n);
244  }
245  _size += n;
246  fill(item_ptr(0), first, last);
247  }
248 
249  prevector() : _size(0), _union{{}} {}
250 
251  explicit prevector(size_type n) : prevector() {
252  resize(n);
253  }
254 
255  explicit prevector(size_type n, const T& val) : prevector() {
256  change_capacity(n);
257  _size += n;
258  fill(item_ptr(0), n, val);
259  }
260 
261  template<typename InputIterator>
262  prevector(InputIterator first, InputIterator last) : prevector() {
263  size_type n = last - first;
264  change_capacity(n);
265  _size += n;
266  fill(item_ptr(0), first, last);
267  }
268 
270  size_type n = other.size();
271  change_capacity(n);
272  _size += n;
273  fill(item_ptr(0), other.begin(), other.end());
274  }
275 
277  swap(other);
278  }
279 
281  if (&other == this) {
282  return *this;
283  }
284  assign(other.begin(), other.end());
285  return *this;
286  }
287 
289  swap(other);
290  return *this;
291  }
292 
293  size_type size() const {
294  return is_direct() ? _size : _size - N - 1;
295  }
296 
297  bool empty() const {
298  return size() == 0;
299  }
300 
301  iterator begin() { return iterator(item_ptr(0)); }
302  const_iterator begin() const { return const_iterator(item_ptr(0)); }
303  iterator end() { return iterator(item_ptr(size())); }
305 
310 
311  size_t capacity() const {
312  if (is_direct()) {
313  return N;
314  } else {
315  return _union.capacity;
316  }
317  }
318 
320  return *item_ptr(pos);
321  }
322 
323  const T& operator[](size_type pos) const {
324  return *item_ptr(pos);
325  }
326 
327  void resize(size_type new_size) {
328  size_type cur_size = size();
329  if (cur_size == new_size) {
330  return;
331  }
332  if (cur_size > new_size) {
333  erase(item_ptr(new_size), end());
334  return;
335  }
336  if (new_size > capacity()) {
337  change_capacity(new_size);
338  }
339  ptrdiff_t increase = new_size - cur_size;
340  fill(item_ptr(cur_size), increase);
341  _size += increase;
342  }
343 
344  void reserve(size_type new_capacity) {
345  if (new_capacity > capacity()) {
346  change_capacity(new_capacity);
347  }
348  }
349 
350  void shrink_to_fit() {
352  }
353 
354  void clear() {
355  resize(0);
356  }
357 
358  iterator insert(iterator pos, const T& value) {
359  size_type p = pos - begin();
360  size_type new_size = size() + 1;
361  if (capacity() < new_size) {
362  change_capacity(new_size + (new_size >> 1));
363  }
364  T* ptr = item_ptr(p);
365  memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
366  _size++;
367  new(static_cast<void*>(ptr)) T(value);
368  return iterator(ptr);
369  }
370 
371  void insert(iterator pos, size_type count, const T& value) {
372  size_type p = pos - begin();
373  size_type new_size = size() + count;
374  if (capacity() < new_size) {
375  change_capacity(new_size + (new_size >> 1));
376  }
377  T* ptr = item_ptr(p);
378  memmove(ptr + count, ptr, (size() - p) * sizeof(T));
379  _size += count;
380  fill(item_ptr(p), count, value);
381  }
382 
383  template<typename InputIterator>
384  void insert(iterator pos, InputIterator first, InputIterator last) {
385  size_type p = pos - begin();
386  difference_type count = last - first;
387  size_type new_size = size() + count;
388  if (capacity() < new_size) {
389  change_capacity(new_size + (new_size >> 1));
390  }
391  T* ptr = item_ptr(p);
392  memmove(ptr + count, ptr, (size() - p) * sizeof(T));
393  _size += count;
394  fill(ptr, first, last);
395  }
396 
398  return erase(pos, pos + 1);
399  }
400 
402  // Erase is not allowed to the change the object's capacity. That means
403  // that when starting with an indirectly allocated prevector with
404  // size and capacity > N, the result may be a still indirectly allocated
405  // prevector with size <= N and capacity > N. A shrink_to_fit() call is
406  // necessary to switch to the (more efficient) directly allocated
407  // representation (with capacity N and size <= N).
408  iterator p = first;
409  char* endp = (char*)&(*end());
410  if (!std::is_trivially_destructible<T>::value) {
411  while (p != last) {
412  (*p).~T();
413  _size--;
414  ++p;
415  }
416  } else {
417  _size -= last - p;
418  }
419  memmove(&(*first), &(*last), endp - ((char*)(&(*last))));
420  return first;
421  }
422 
423  void push_back(const T& value) {
424  size_type new_size = size() + 1;
425  if (capacity() < new_size) {
426  change_capacity(new_size + (new_size >> 1));
427  }
428  new(item_ptr(size())) T(value);
429  _size++;
430  }
431 
432  void pop_back() {
433  erase(end() - 1, end());
434  }
435 
436  T& front() {
437  return *item_ptr(0);
438  }
439 
440  const T& front() const {
441  return *item_ptr(0);
442  }
443 
444  T& back() {
445  return *item_ptr(size() - 1);
446  }
447 
448  const T& back() const {
449  return *item_ptr(size() - 1);
450  }
451 
453  std::swap(_union, other._union);
454  std::swap(_size, other._size);
455  }
456 
458  if (!std::is_trivially_destructible<T>::value) {
459  clear();
460  }
461  if (!is_direct()) {
462  free(_union.indirect);
463  _union.indirect = nullptr;
464  }
465  }
466 
467  bool operator==(const prevector<N, T, Size, Diff>& other) const {
468  if (other.size() != size()) {
469  return false;
470  }
471  const_iterator b1 = begin();
472  const_iterator b2 = other.begin();
473  const_iterator e1 = end();
474  while (b1 != e1) {
475  if ((*b1) != (*b2)) {
476  return false;
477  }
478  ++b1;
479  ++b2;
480  }
481  return true;
482  }
483 
484  bool operator!=(const prevector<N, T, Size, Diff>& other) const {
485  return !(*this == other);
486  }
487 
488  bool operator<(const prevector<N, T, Size, Diff>& other) const {
489  if (size() < other.size()) {
490  return true;
491  }
492  if (size() > other.size()) {
493  return false;
494  }
495  const_iterator b1 = begin();
496  const_iterator b2 = other.begin();
497  const_iterator e1 = end();
498  while (b1 != e1) {
499  if ((*b1) < (*b2)) {
500  return true;
501  }
502  if ((*b2) < (*b1)) {
503  return false;
504  }
505  ++b1;
506  ++b2;
507  }
508  return false;
509  }
510 
511  size_t allocated_memory() const {
512  if (is_direct()) {
513  return 0;
514  } else {
515  return ((size_t)(sizeof(T))) * _union.capacity;
516  }
517  }
518 
520  return item_ptr(0);
521  }
522 
523  const value_type* data() const {
524  return item_ptr(0);
525  }
526 };
527 #pragma pack(pop)
528 
529 #endif // BITCOIN_PREVECTOR_H
bool operator!=(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:484
T * direct_ptr(difference_type pos)
Definition: prevector.h:160
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:86
prevector & operator=(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:280
const value_type & const_reference
Definition: prevector.h:45
const_iterator operator--(int)
Definition: prevector.h:116
void resize(size_type new_size)
Definition: prevector.h:327
const T * operator->() const
Definition: prevector.h:91
const T & operator[](size_type pos) const
Definition: prevector.h:61
const value_type * const_pointer
Definition: prevector.h:47
void assign(size_type n, const T &val)
Definition: prevector.h:229
T * indirect_ptr(difference_type pos)
Definition: prevector.h:162
iterator operator+(size_type n)
Definition: prevector.h:67
bool operator<=(const_iterator x) const
Definition: prevector.h:125
iterator operator-(size_type n)
Definition: prevector.h:69
T & back()
Definition: prevector.h:444
prevector(prevector< N, T, Size, Diff > &&other)
Definition: prevector.h:276
void assign(InputIterator first, InputIterator last)
Definition: prevector.h:239
void shrink_to_fit()
Definition: prevector.h:350
void pop_back()
Definition: prevector.h:432
T * operator->() const
Definition: prevector.h:59
reverse_iterator operator++(int)
Definition: prevector.h:94
iterator insert(iterator pos, const T &value)
Definition: prevector.h:358
void clear()
Definition: prevector.h:354
Size size_type
Definition: prevector.h:41
reverse_iterator operator--(int)
Definition: prevector.h:95
const T & operator[](size_type pos) const
Definition: prevector.h:112
void fill(T *dst, ptrdiff_t count, const T &value)
Definition: prevector.h:213
bool operator!=(iterator x) const
Definition: prevector.h:72
const_iterator & operator-=(size_type n)
Definition: prevector.h:121
const_reverse_iterator & operator--()
Definition: prevector.h:142
const_iterator & operator++()
Definition: prevector.h:113
iterator operator++(int)
Definition: prevector.h:64
void insert(iterator pos, InputIterator first, InputIterator last)
Definition: prevector.h:384
const_reverse_iterator operator--(int)
Definition: prevector.h:145
void fill(T *dst, InputIterator first, InputIterator last)
Definition: prevector.h:220
const T & back() const
Definition: prevector.h:448
const T * operator->() const
Definition: prevector.h:141
iterator operator--(int)
Definition: prevector.h:65
const value_type * data() const
Definition: prevector.h:523
const T * direct_ptr(difference_type pos) const
Definition: prevector.h:161
size_t allocated_memory() const
Definition: prevector.h:511
bool operator==(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:467
size_t capacity() const
Definition: prevector.h:311
const_reverse_iterator & operator++()
Definition: prevector.h:143
bool is_direct() const
Definition: prevector.h:164
~prevector()
Definition: prevector.h:457
iterator(T *ptr_)
Definition: prevector.h:57
T & operator[](size_type pos)
Definition: prevector.h:60
bool operator==(const_reverse_iterator x) const
Definition: prevector.h:146
bool operator>=(iterator x) const
Definition: prevector.h:73
value_type * data()
Definition: prevector.h:519
prevector(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:269
const_reverse_iterator operator++(int)
Definition: prevector.h:144
bool operator>=(const_iterator x) const
Definition: prevector.h:124
T value_type
Definition: prevector.h:43
const T * item_ptr(difference_type pos) const
Definition: prevector.h:198
iterator end()
Definition: prevector.h:303
Diff difference_type
Definition: prevector.h:42
void push_back(const T &value)
Definition: prevector.h:423
T & front()
Definition: prevector.h:436
prevector & operator=(prevector< N, T, Size, Diff > &&other)
Definition: prevector.h:288
value_type * pointer
Definition: prevector.h:46
const T & operator*() const
Definition: prevector.h:110
const_reverse_iterator rend() const
Definition: prevector.h:309
const_reverse_iterator rbegin() const
Definition: prevector.h:307
T & operator[](size_type pos)
Definition: prevector.h:319
void swap(prevector< N, T, Size, Diff > &other)
Definition: prevector.h:452
bool operator<=(iterator x) const
Definition: prevector.h:74
void insert(iterator pos, size_type count, const T &value)
Definition: prevector.h:371
const_iterator operator+(size_type n)
Definition: prevector.h:118
prevector(size_type n)
Definition: prevector.h:251
reverse_iterator rend()
Definition: prevector.h:308
const_reverse_iterator(reverse_iterator x)
Definition: prevector.h:139
bool operator>(const_iterator x) const
Definition: prevector.h:126
bool operator==(iterator x) const
Definition: prevector.h:71
reverse_iterator rbegin()
Definition: prevector.h:306
void fill(T *dst, ptrdiff_t count)
Definition: prevector.h:200
char direct[sizeof(T) *N]
Definition: prevector.h:153
iterator & operator+=(size_type n)
Definition: prevector.h:68
iterator erase(iterator pos)
Definition: prevector.h:397
bool operator<(iterator x) const
Definition: prevector.h:76
const_reverse_iterator(const T *ptr_)
Definition: prevector.h:138
const T & operator[](size_type pos) const
Definition: prevector.h:323
const_iterator(iterator x)
Definition: prevector.h:109
reverse_iterator & operator++()
Definition: prevector.h:93
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:39
T & operator*() const
Definition: prevector.h:58
bool operator!=(const_reverse_iterator x) const
Definition: prevector.h:147
const_iterator & operator--()
Definition: prevector.h:114
bool operator==(reverse_iterator x) const
Definition: prevector.h:96
const_iterator operator-(size_type n)
Definition: prevector.h:120
void reserve(size_type new_capacity)
Definition: prevector.h:344
const T * operator->() const
Definition: prevector.h:111
void change_capacity(size_type new_capacity)
Definition: prevector.h:166
const T & front() const
Definition: prevector.h:440
prevector(InputIterator first, InputIterator last)
Definition: prevector.h:262
T * item_ptr(difference_type pos)
Definition: prevector.h:197
void * memcpy(void *a, const void *b, size_t c)
bool empty() const
Definition: prevector.h:297
bool operator>(iterator x) const
Definition: prevector.h:75
reverse_iterator & operator--()
Definition: prevector.h:92
std::random_access_iterator_tag iterator_category
Definition: prevector.h:56
union prevector::direct_or_indirect _union
const T & operator*() const
Definition: prevector.h:89
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:137
const_iterator operator++(int)
Definition: prevector.h:115
iterator begin()
Definition: prevector.h:301
std::random_access_iterator_tag iterator_category
Definition: prevector.h:107
size_type size() const
Definition: prevector.h:293
iterator erase(iterator first, iterator last)
Definition: prevector.h:401
bool operator!=(const_iterator x) const
Definition: prevector.h:123
iterator & operator++()
Definition: prevector.h:62
size_type _size
Definition: prevector.h:151
difference_type friend operator-(iterator a, iterator b)
Definition: prevector.h:66
const T * indirect_ptr(difference_type pos) const
Definition: prevector.h:163
bool operator<(const_iterator x) const
Definition: prevector.h:127
prevector(size_type n, const T &val)
Definition: prevector.h:255
const_iterator end() const
Definition: prevector.h:304
iterator & operator-=(size_type n)
Definition: prevector.h:70
void * memmove(void *a, const void *b, size_t c)
const_iterator begin() const
Definition: prevector.h:302
iterator & operator--()
Definition: prevector.h:63
bool operator==(const_iterator x) const
Definition: prevector.h:122
bool operator!=(reverse_iterator x) const
Definition: prevector.h:97
const_iterator & operator+=(size_type n)
Definition: prevector.h:119
const_iterator(const T *ptr_)
Definition: prevector.h:108
value_type & reference
Definition: prevector.h:44
difference_type friend operator-(const_iterator a, const_iterator b)
Definition: prevector.h:117