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