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