5 #ifndef BITCOIN_PREVECTOR_H
6 #define BITCOIN_PREVECTOR_H
15 #include <type_traits>
36 template<
unsigned int N,
typename T,
typename Size = u
int32_t,
typename Diff =
int32_t>
59 const T&
operator[](size_type pos)
const {
return ptr[pos]; }
110 const T&
operator[](size_type pos)
const {
return ptr[pos]; }
149 #pragma pack(push, 1)
158 alignas(
char*) direct_or_indirect
_union = {};
161 static_assert(
alignof(
char*) %
alignof(size_type) == 0 &&
sizeof(
char*) %
alignof(size_type) == 0,
"size_type cannot have more restrictive alignment requirement than pointer");
162 static_assert(
alignof(
char*) %
alignof(T) == 0,
"value_type T cannot have more restrictive alignment requirement than pointer");
164 T* direct_ptr(difference_type pos) {
return reinterpret_cast<T*
>(
_union.
direct) + pos; }
165 const T* direct_ptr(difference_type pos)
const {
return reinterpret_cast<const T*
>(
_union.
direct) + pos; }
168 bool is_direct()
const {
return _size <= N; }
170 void change_capacity(size_type new_capacity) {
171 if (new_capacity <= N) {
173 T* indirect = indirect_ptr(0);
175 T* dst = direct_ptr(0);
176 memcpy(dst, src, size() *
sizeof(T));
189 char* new_indirect =
static_cast<char*
>(malloc(((
size_t)
sizeof(T)) * new_capacity));
190 assert(new_indirect);
191 T* src = direct_ptr(0);
192 T* dst =
reinterpret_cast<T*
>(new_indirect);
193 memcpy(dst, src, size() *
sizeof(T));
201 T* item_ptr(difference_type pos) {
return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
202 const T* item_ptr(difference_type pos)
const {
return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
204 void fill(T* dst, ptrdiff_t
count,
const T& value = T{}) {
205 std::fill_n(dst, count, value);
208 template<
typename InputIterator>
209 void fill(T* dst, InputIterator first, InputIterator last) {
210 while (first != last) {
211 new(
static_cast<void*
>(dst)) T(*first);
218 void assign(size_type n,
const T& val) {
220 if (capacity() < n) {
224 fill(item_ptr(0), n, val);
227 template<
typename InputIterator>
228 void assign(InputIterator first, InputIterator last) {
229 size_type n = last - first;
231 if (capacity() < n) {
235 fill(item_ptr(0), first, last);
244 explicit prevector(size_type n,
const T& val) {
247 fill(item_ptr(0), n, val);
250 template<
typename InputIterator>
251 prevector(InputIterator first, InputIterator last) {
252 size_type n = last - first;
255 fill(item_ptr(0), first, last);
259 size_type n = other.size();
262 fill(item_ptr(0), other.begin(), other.end());
270 if (&other ==
this) {
273 assign(other.begin(), other.end());
282 size_type size()
const {
283 return is_direct() ? _size : _size - N - 1;
290 iterator begin() {
return iterator(item_ptr(0)); }
291 const_iterator begin()
const {
return const_iterator(item_ptr(0)); }
292 iterator end() {
return iterator(item_ptr(size())); }
293 const_iterator end()
const {
return const_iterator(item_ptr(size())); }
295 reverse_iterator rbegin() {
return reverse_iterator(item_ptr(size() - 1)); }
296 const_reverse_iterator rbegin()
const {
return const_reverse_iterator(item_ptr(size() - 1)); }
297 reverse_iterator rend() {
return reverse_iterator(item_ptr(-1)); }
298 const_reverse_iterator rend()
const {
return const_reverse_iterator(item_ptr(-1)); }
300 size_t capacity()
const {
308 T& operator[](size_type pos) {
309 return *item_ptr(pos);
312 const T& operator[](size_type pos)
const {
313 return *item_ptr(pos);
316 void resize(size_type new_size) {
317 size_type cur_size = size();
318 if (cur_size == new_size) {
321 if (cur_size > new_size) {
322 erase(item_ptr(new_size), end());
325 if (new_size > capacity()) {
326 change_capacity(new_size);
328 ptrdiff_t increase = new_size - cur_size;
329 fill(item_ptr(cur_size), increase);
333 void reserve(size_type new_capacity) {
334 if (new_capacity > capacity()) {
335 change_capacity(new_capacity);
339 void shrink_to_fit() {
340 change_capacity(size());
347 iterator
insert(iterator pos,
const T& value) {
348 size_type p = pos - begin();
349 size_type new_size = size() + 1;
350 if (capacity() < new_size) {
351 change_capacity(new_size + (new_size >> 1));
353 T* ptr = item_ptr(p);
354 memmove(ptr + 1, ptr, (size() - p) *
sizeof(T));
356 new(
static_cast<void*
>(ptr)) T(value);
357 return iterator(ptr);
360 void insert(iterator pos, size_type count,
const T& value) {
361 size_type p = pos - begin();
362 size_type new_size = size() +
count;
363 if (capacity() < new_size) {
364 change_capacity(new_size + (new_size >> 1));
366 T* ptr = item_ptr(p);
367 memmove(ptr + count, ptr, (size() - p) *
sizeof(T));
369 fill(item_ptr(p), count, value);
372 template<
typename InputIterator>
373 void insert(iterator pos, InputIterator first, InputIterator last) {
374 size_type p = pos - begin();
375 difference_type count = last - first;
376 size_type new_size = size() +
count;
377 if (capacity() < new_size) {
378 change_capacity(new_size + (new_size >> 1));
380 T* ptr = item_ptr(p);
381 memmove(ptr + count, ptr, (size() - p) *
sizeof(T));
383 fill(ptr, first, last);
386 inline void resize_uninitialized(size_type new_size) {
389 if (capacity() < new_size) {
390 change_capacity(new_size);
391 _size += new_size - size();
394 if (new_size < size()) {
395 erase(item_ptr(new_size), end());
397 _size += new_size - size();
401 iterator erase(iterator pos) {
402 return erase(pos, pos + 1);
405 iterator erase(iterator first, iterator last) {
413 char* endp = (
char*)&(*end());
414 if (!std::is_trivially_destructible<T>::value) {
423 memmove(&(*first), &(*last), endp - ((
char*)(&(*last))));
427 template<
typename... Args>
428 void emplace_back(Args&&... args) {
429 size_type new_size = size() + 1;
430 if (capacity() < new_size) {
431 change_capacity(new_size + (new_size >> 1));
433 new(item_ptr(size())) T(std::forward<Args>(args)...);
437 void push_back(
const T& value) {
442 erase(end() - 1, end());
449 const T& front()
const {
454 return *item_ptr(size() - 1);
457 const T& back()
const {
458 return *item_ptr(size() - 1);
463 std::swap(_size, other.
_size);
467 if (!std::is_trivially_destructible<T>::value) {
477 if (other.size() != size()) {
480 const_iterator b1 = begin();
481 const_iterator b2 = other.begin();
482 const_iterator e1 = end();
484 if ((*b1) != (*b2)) {
494 return !(*
this == other);
497 bool operator<(const prevector<N, T, Size, Diff>& other)
const {
498 if (size() < other.size()) {
501 if (size() > other.size()) {
504 const_iterator b1 = begin();
505 const_iterator b2 = other.begin();
506 const_iterator e1 = end();
520 size_t allocated_memory()
const {
532 const value_type* data()
const {
537 #endif // BITCOIN_PREVECTOR_H
struct prevector::direct_or_indirect::@2 indirect_contents
std::bidirectional_iterator_tag iterator_category
const value_type & const_reference
const_iterator operator--(int)
const value_type * const_pointer
bool operator>=(iterator x) const
iterator operator+(size_type n)
iterator operator-(size_type n)
bool operator==(reverse_iterator x) const
reverse_iterator operator++(int)
bool operator==(const CNetAddr &a, const CNetAddr &b)
bool operator<(iterator x) const
reverse_iterator operator--(int)
const_iterator & operator-=(size_type n)
const_reverse_iterator & operator--()
const_iterator & operator++()
const T * operator->() const
const_reverse_iterator operator--(int)
reverse_iterator(T *ptr_)
bool operator!=(const_reverse_iterator x) const
bool operator<=(iterator x) const
bool operator!=(const_iterator x) const
void insert(Tdst &dst, const Tsrc &src)
Simplification of std insertion.
const T & operator[](size_type pos) const
const_reverse_iterator & operator++()
T & operator[](size_type pos)
const T * operator->() const
disconnectpool queuedTx clear()
direct_or_indirect _union
const_reverse_iterator operator++(int)
bool operator!=(reverse_iterator x) const
const_iterator operator+(size_type n)
const_reverse_iterator(reverse_iterator x)
iterator & operator+=(size_type n)
const_reverse_iterator(const T *ptr_)
const_iterator(iterator x)
reverse_iterator & operator++()
const T * operator->() const
Implements a drop-in replacement for std::vector which stores up to N elements directly (without h...
const_iterator & operator--()
const_iterator operator-(size_type n)
bool operator!=(iterator x) const
bool operator<=(const_iterator x) const
const T & operator*() const
bool operator==(const_reverse_iterator x) const
const T & operator*() const
void * memcpy(void *a, const void *b, size_t c)
bool operator<(const_iterator x) const
reverse_iterator & operator--()
bool operator==(iterator x) const
std::random_access_iterator_tag iterator_category
std::bidirectional_iterator_tag iterator_category
const_iterator operator++(int)
std::random_access_iterator_tag iterator_category
bool operator>(const_iterator x) const
bool operator==(const_iterator x) const
bool operator>(iterator x) const
difference_type friend operator-(iterator a, iterator b)
iterator & operator-=(size_type n)
void * memmove(void *a, const void *b, size_t c)
bool operator>=(const_iterator x) const
const_iterator & operator+=(size_type n)
const_iterator(const T *ptr_)
const T & operator[](size_type pos) const
const T & operator*() const
difference_type friend operator-(const_iterator a, const_iterator b)