Branch data Line data Source code
1 : : // Copyright (c) 2015-2022 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 <cstdlib>
10 : : #include <stdint.h>
11 : : #include <string.h>
12 : :
13 : : #include <algorithm>
14 : : #include <cstddef>
15 : : #include <type_traits>
16 : : #include <utility>
17 : :
18 : : /** Implements a drop-in replacement for std::vector<T> which stores up to N
19 : : * elements directly (without heap allocation). The types Size and Diff are
20 : : * used to store element counts, and can be any unsigned + signed type.
21 : : *
22 : : * Storage layout is either:
23 : : * - Direct allocation:
24 : : * - Size _size: the number of used elements (between 0 and N)
25 : : * - T direct[N]: an array of N elements of type T
26 : : * (only the first _size are initialized).
27 : : * - Indirect allocation:
28 : : * - Size _size: the number of used elements plus N + 1
29 : : * - Size capacity: the number of allocated elements
30 : : * - T* indirect: a pointer to an array of capacity elements of type T
31 : : * (only the first _size are initialized).
32 : : *
33 : : * The data type T must be movable by memmove/realloc(). Once we switch to C++,
34 : : * move constructors can be used instead.
35 : : */
36 : : template<unsigned int N, typename T, typename Size = uint32_t, typename Diff = int32_t>
37 : : class prevector {
38 : : static_assert(std::is_trivially_copyable_v<T>);
39 : :
40 : : public:
41 : : typedef Size size_type;
42 : : typedef Diff difference_type;
43 : : typedef T value_type;
44 : : typedef value_type& reference;
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 : 192626245 : iterator(T* ptr_) : ptr(ptr_) {}
58 : 223271831 : 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 : 24330348 : 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 : 79913962 : difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); }
67 : 79616 : iterator operator+(size_type n) { return iterator(ptr + n); }
68 : : iterator& operator+=(size_type n) { ptr += n; return *this; }
69 : 7497 : 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 : 18204987 : 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 : :
79 : : class reverse_iterator {
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 : :
100 : : class const_iterator {
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 : 1375155527 : const_iterator(const T* ptr_) : ptr(ptr_) {}
109 : 254023 : const_iterator(iterator x) : ptr(&(*x)) {}
110 :11443388491 : const T& operator*() const { return *ptr; }
111 : : const T* operator->() const { return ptr; }
112 : 1876779 : const T& operator[](size_type pos) const { return ptr[pos]; }
113 :10090259805 : const_iterator& operator++() { ptr++; return *this; }
114 : 0 : const_iterator& operator--() { ptr--; return *this; }
115 : 172407992 : const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; }
116 : : const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; }
117 : 453187351 : difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); }
118 : 30971915 : const_iterator operator+(size_type n) { return const_iterator(ptr + n); }
119 : 43695210 : const_iterator& operator+=(size_type n) { ptr += n; return *this; }
120 : 1472691 : const_iterator operator-(size_type n) { return const_iterator(ptr - n); }
121 : : const_iterator& operator-=(size_type n) { ptr -= n; return *this; }
122 : 26821 : bool operator==(const_iterator x) const { return ptr == x.ptr; }
123 : 8308488930 : bool operator!=(const_iterator x) const { return ptr != x.ptr; }
124 : 167797978 : 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 : 146566178 : bool operator<(const_iterator x) const { return ptr < x.ptr; }
128 : : };
129 : :
130 : : class const_reverse_iterator {
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 : 1132 : const_reverse_iterator(const T* ptr_) : ptr(ptr_) {}
139 : : const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {}
140 : 2888606 : const T& operator*() const { return *ptr; }
141 : : const T* operator->() const { return ptr; }
142 : : const_reverse_iterator& operator--() { ptr++; return *this; }
143 : 2888606 : 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 : 2889172 : bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; }
148 : : };
149 : :
150 : : private:
151 : : #pragma pack(push, 1)
152 : : union direct_or_indirect {
153 : : char direct[sizeof(T) * N];
154 : : struct {
155 : : char* indirect;
156 : : size_type capacity;
157 : : } indirect_contents;
158 : : };
159 : : #pragma pack(pop)
160 : 306643205 : alignas(char*) direct_or_indirect _union = {};
161 : 306643205 : size_type _size = 0;
162 : :
163 : : static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer");
164 : : static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer");
165 : :
166 : 317313082 : T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
167 : 1148853296 : const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
168 : 310535042 : T* indirect_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.indirect_contents.indirect) + pos; }
169 : 877711683 : const T* indirect_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.indirect_contents.indirect) + pos; }
170 : 6072993834 : bool is_direct() const { return _size <= N; }
171 : :
172 : 266690633 : void change_capacity(size_type new_capacity) {
173 [ + + + + : 266690633 : if (new_capacity <= N) {
# # ]
174 [ + + + - : 157881796 : if (!is_direct()) {
# # ]
175 : 76299 : T* indirect = indirect_ptr(0);
176 : 76299 : T* src = indirect;
177 : 76299 : T* dst = direct_ptr(0);
178 : 76299 : memcpy(dst, src, size() * sizeof(T));
179 : 76299 : free(indirect);
180 : 76299 : _size -= N + 1;
181 : 76299 : }
182 : 157881796 : } else {
183 [ + + + - : 108808837 : if (!is_direct()) {
# # ]
184 : : /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
185 : : success. These should instead use an allocator or new/delete so that handlers
186 : : are called as necessary, but performance would be slightly degraded by doing so. */
187 : 404798 : _union.indirect_contents.indirect = static_cast<char*>(realloc(_union.indirect_contents.indirect, ((size_t)sizeof(T)) * new_capacity));
188 [ + - # # : 404798 : assert(_union.indirect_contents.indirect);
# # ]
189 : 404798 : _union.indirect_contents.capacity = new_capacity;
190 : 404798 : } else {
191 : 108404039 : char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
192 [ + - + - : 108404039 : assert(new_indirect);
# # ]
193 : 108404039 : T* src = direct_ptr(0);
194 : 108404039 : T* dst = reinterpret_cast<T*>(new_indirect);
195 : 108404039 : memcpy(dst, src, size() * sizeof(T));
196 : 108404039 : _union.indirect_contents.indirect = new_indirect;
197 : 108404039 : _union.indirect_contents.capacity = new_capacity;
198 : 108404039 : _size += N + 1;
199 : : }
200 : : }
201 : 266690633 : }
202 : :
203 [ + + + + : 519291487 : T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
# # ]
204 [ + + + + ]: 2026564979 : const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
205 : :
206 : 38844941 : void fill(T* dst, ptrdiff_t count, const T& value = T{}) {
207 : 38844941 : std::fill_n(dst, count, value);
208 : 38844941 : }
209 : :
210 : : template<typename InputIterator>
211 : 262180008 : void fill(T* dst, InputIterator first, InputIterator last) {
212 [ + + + + : 9871845540 : while (first != last) {
+ + + + +
+ + + ]
213 : 9609665532 : new(static_cast<void*>(dst)) T(*first);
214 : 9609665532 : ++dst;
215 : 9609665532 : ++first;
216 : : }
217 : 262180008 : }
218 : :
219 : : public:
220 : 376286 : void assign(size_type n, const T& val) {
221 : 376286 : clear();
222 [ + + ]: 376286 : if (capacity() < n) {
223 : 5999 : change_capacity(n);
224 : 5999 : }
225 : 376286 : _size += n;
226 : 376286 : fill(item_ptr(0), n, val);
227 : 376286 : }
228 : :
229 : : template<typename InputIterator>
230 : 37025076 : void assign(InputIterator first, InputIterator last) {
231 : 37025076 : size_type n = last - first;
232 : 37025076 : clear();
233 [ + + + - : 37025076 : if (capacity() < n) {
- + # # ]
234 : 19109679 : change_capacity(n);
235 : 19109679 : }
236 : 37025076 : _size += n;
237 : 37025076 : fill(item_ptr(0), first, last);
238 : 37025076 : }
239 : :
240 : 198741178 : prevector() {}
241 : :
242 : : explicit prevector(size_type n) {
243 : : resize(n);
244 : : }
245 : :
246 : 29155546 : explicit prevector(size_type n, const T& val) {
247 : 29155546 : change_capacity(n);
248 : 29155546 : _size += n;
249 : 29155546 : fill(item_ptr(0), n, val);
250 : 29155546 : }
251 : :
252 : : template<typename InputIterator>
253 : 1519193 : prevector(InputIterator first, InputIterator last) {
254 : 1519193 : size_type n = last - first;
255 : 1519193 : change_capacity(n);
256 : 1519193 : _size += n;
257 : 1519193 : fill(item_ptr(0), first, last);
258 : 1519193 : }
259 : :
260 : 176597877 : prevector(const prevector<N, T, Size, Diff>& other) {
261 : 176597877 : size_type n = other.size();
262 : 176597877 : change_capacity(n);
263 : 176597877 : _size += n;
264 : 176597877 : fill(item_ptr(0), other.begin(), other.end());
265 : 176597877 : }
266 : :
267 : 53975358 : prevector(prevector<N, T, Size, Diff>&& other) noexcept
268 : 53975358 : : _union(std::move(other._union)), _size(other._size)
269 : : {
270 : 53975358 : other._size = 0;
271 : 53975358 : }
272 : :
273 : 33565712 : prevector& operator=(const prevector<N, T, Size, Diff>& other) {
274 [ - + ]: 33565712 : if (&other == this) {
275 : 0 : return *this;
276 : : }
277 : 33565712 : assign(other.begin(), other.end());
278 : 33565712 : return *this;
279 : 33565712 : }
280 : :
281 : 27127085 : prevector& operator=(prevector<N, T, Size, Diff>&& other) noexcept {
282 [ + + + + ]: 27127085 : if (!is_direct()) {
283 : 83653 : free(_union.indirect_contents.indirect);
284 : 83653 : }
285 : 27127085 : _union = std::move(other._union);
286 : 27127085 : _size = other._size;
287 : 27127085 : other._size = 0;
288 : 27127085 : return *this;
289 : : }
290 : :
291 : 2740260964 : size_type size() const {
292 [ + + + + : 2740260964 : return is_direct() ? _size : _size - N - 1;
# # ]
293 : : }
294 : :
295 : 319861210 : bool empty() const {
296 : 319861210 : return size() == 0;
297 : : }
298 : :
299 : 70402617 : iterator begin() { return iterator(item_ptr(0)); }
300 : 723200221 : const_iterator begin() const { return const_iterator(item_ptr(0)); }
301 : 89661273 : iterator end() { return iterator(item_ptr(size())); }
302 : 619510705 : const_iterator end() const { return const_iterator(item_ptr(size())); }
303 : :
304 : : reverse_iterator rbegin() { return reverse_iterator(item_ptr(size() - 1)); }
305 : 566 : const_reverse_iterator rbegin() const { return const_reverse_iterator(item_ptr(size() - 1)); }
306 : : reverse_iterator rend() { return reverse_iterator(item_ptr(-1)); }
307 : 566 : const_reverse_iterator rend() const { return const_reverse_iterator(item_ptr(-1)); }
308 : :
309 : 120242681 : size_t capacity() const {
310 [ + + + - ]: 120242681 : if (is_direct()) {
311 : 54969490 : return N;
312 : : } else {
313 : 65273191 : return _union.indirect_contents.capacity;
314 : : }
315 : 120242681 : }
316 : :
317 : 7006378 : T& operator[](size_type pos) {
318 : 7006378 : return *item_ptr(pos);
319 : : }
320 : :
321 : 342068173 : const T& operator[](size_type pos) const {
322 : 342068173 : return *item_ptr(pos);
323 : : }
324 : :
325 : 98078683 : void resize(size_type new_size) {
326 : 98078683 : size_type cur_size = size();
327 [ + + # # ]: 98078683 : if (cur_size == new_size) {
328 : 79091788 : return;
329 : : }
330 [ + + # # ]: 18986895 : if (cur_size > new_size) {
331 : 9685528 : erase(item_ptr(new_size), end());
332 : 9685528 : return;
333 : : }
334 [ + + # # ]: 9301367 : if (new_size > capacity()) {
335 : 4792231 : change_capacity(new_size);
336 : 4792231 : }
337 : 9301367 : ptrdiff_t increase = new_size - cur_size;
338 : 9301367 : fill(item_ptr(cur_size), increase);
339 : 9301367 : _size += increase;
340 : 98078683 : }
341 : :
342 : 8539 : void reserve(size_type new_capacity) {
343 [ + + ]: 8539 : if (new_capacity > capacity()) {
344 : 5514 : change_capacity(new_capacity);
345 : 5514 : }
346 : 8539 : }
347 : :
348 : 33500643 : void shrink_to_fit() {
349 : 33500643 : change_capacity(size());
350 : 33500643 : }
351 : :
352 : 80484360 : void clear() {
353 : 80484360 : resize(0);
354 : 80484360 : }
355 : :
356 : 22785138 : iterator insert(iterator pos, const T& value) {
357 : 22785138 : size_type p = pos - begin();
358 : 22785138 : size_type new_size = size() + 1;
359 [ + + ]: 22785138 : if (capacity() < new_size) {
360 : 42095 : change_capacity(new_size + (new_size >> 1));
361 : 42095 : }
362 : 22785138 : T* ptr = item_ptr(p);
363 : 22785138 : memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
364 : 22785138 : _size++;
365 : 22785138 : new(static_cast<void*>(ptr)) T(value);
366 : 22785138 : return iterator(ptr);
367 : : }
368 : :
369 : 11742 : void insert(iterator pos, size_type count, const T& value) {
370 : 11742 : size_type p = pos - begin();
371 : 11742 : size_type new_size = size() + count;
372 [ + + ]: 11742 : if (capacity() < new_size) {
373 : 1419 : change_capacity(new_size + (new_size >> 1));
374 : 1419 : }
375 : 11742 : T* ptr = item_ptr(p);
376 : 11742 : memmove(ptr + count, ptr, (size() - p) * sizeof(T));
377 : 11742 : _size += count;
378 : 11742 : fill(item_ptr(p), count, value);
379 : 11742 : }
380 : :
381 : : template<typename InputIterator>
382 : 47037862 : void insert(iterator pos, InputIterator first, InputIterator last) {
383 : 47037862 : size_type p = pos - begin();
384 : 47037862 : difference_type count = last - first;
385 : 47037862 : size_type new_size = size() + count;
386 [ + + + + : 47037862 : if (capacity() < new_size) {
+ + ]
387 : 627349 : change_capacity(new_size + (new_size >> 1));
388 : 627349 : }
389 : 47037862 : T* ptr = item_ptr(p);
390 : 47037862 : memmove(ptr + count, ptr, (size() - p) * sizeof(T));
391 : 47037862 : _size += count;
392 : 47037862 : fill(ptr, first, last);
393 : 47037862 : }
394 : :
395 : 3392965 : inline void resize_uninitialized(size_type new_size) {
396 : : // resize_uninitialized changes the size of the prevector but does not initialize it.
397 : : // If size < new_size, the added elements must be initialized explicitly.
398 [ + + ]: 3392965 : if (capacity() < new_size) {
399 : 1330413 : change_capacity(new_size);
400 : 1330413 : _size += new_size - size();
401 : 1330413 : return;
402 : : }
403 [ + + ]: 2062552 : if (new_size < size()) {
404 : 4576 : erase(item_ptr(new_size), end());
405 : 4576 : } else {
406 : 2057976 : _size += new_size - size();
407 : : }
408 : 3392965 : }
409 : :
410 : 6137 : iterator erase(iterator pos) {
411 : 6137 : return erase(pos, pos + 1);
412 : : }
413 : :
414 : 9714884 : iterator erase(iterator first, iterator last) {
415 : : // Erase is not allowed to the change the object's capacity. That means
416 : : // that when starting with an indirectly allocated prevector with
417 : : // size and capacity > N, the result may be a still indirectly allocated
418 : : // prevector with size <= N and capacity > N. A shrink_to_fit() call is
419 : : // necessary to switch to the (more efficient) directly allocated
420 : : // representation (with capacity N and size <= N).
421 : 9714884 : iterator p = first;
422 : 9714884 : char* endp = (char*)&(*end());
423 : 9714884 : _size -= last - p;
424 : 9714884 : memmove(&(*first), &(*last), endp - ((char*)(&(*last))));
425 : 9714884 : return first;
426 : : }
427 : :
428 : : template<typename... Args>
429 : 295167 : void emplace_back(Args&&... args) {
430 : 295167 : size_type new_size = size() + 1;
431 [ + + ]: 295167 : if (capacity() < new_size) {
432 : 2675 : change_capacity(new_size + (new_size >> 1));
433 : 2675 : }
434 : 295167 : new(item_ptr(size())) T(std::forward<Args>(args)...);
435 : 295167 : _size++;
436 : 295167 : }
437 : :
438 : 295167 : void push_back(const T& value) {
439 : 295167 : emplace_back(value);
440 : 295167 : }
441 : :
442 : 7497 : void pop_back() {
443 : 7497 : erase(end() - 1, end());
444 : 7497 : }
445 : :
446 : : T& front() {
447 : : return *item_ptr(0);
448 : : }
449 : :
450 : : const T& front() const {
451 : : return *item_ptr(0);
452 : : }
453 : :
454 : 5473 : T& back() {
455 : 5473 : return *item_ptr(size() - 1);
456 : : }
457 : :
458 : 1639070 : const T& back() const {
459 : 1639070 : return *item_ptr(size() - 1);
460 : : }
461 : :
462 : 10884 : void swap(prevector<N, T, Size, Diff>& other) noexcept
463 : : {
464 : 10884 : std::swap(_union, other._union);
465 : 10884 : std::swap(_size, other._size);
466 : 10884 : }
467 : :
468 : 360618476 : ~prevector() {
469 [ + + + + : 360618476 : if (!is_direct()) {
# # # # #
# ]
470 : 108244044 : free(_union.indirect_contents.indirect);
471 : 108244044 : _union.indirect_contents.indirect = nullptr;
472 : 108244044 : }
473 : 360618476 : }
474 : :
475 : 22150459 : bool operator==(const prevector<N, T, Size, Diff>& other) const {
476 [ + + ]: 22150459 : if (other.size() != size()) {
477 : 262 : return false;
478 : : }
479 : 22150197 : const_iterator b1 = begin();
480 : 22150197 : const_iterator b2 = other.begin();
481 : 22150197 : const_iterator e1 = end();
482 [ + + ]: 339754272 : while (b1 != e1) {
483 [ + + ]: 323791897 : if ((*b1) != (*b2)) {
484 : 6187822 : return false;
485 : : }
486 : 317604075 : ++b1;
487 : 317604075 : ++b2;
488 : : }
489 : 15962375 : return true;
490 : 22150459 : }
491 : :
492 : 7685 : bool operator!=(const prevector<N, T, Size, Diff>& other) const {
493 : 7685 : return !(*this == other);
494 : : }
495 : :
496 : 448532 : bool operator<(const prevector<N, T, Size, Diff>& other) const {
497 [ - + ]: 448532 : if (size() < other.size()) {
498 : 0 : return true;
499 : : }
500 [ - + ]: 448532 : if (size() > other.size()) {
501 : 0 : return false;
502 : : }
503 : 448532 : const_iterator b1 = begin();
504 : 448532 : const_iterator b2 = other.begin();
505 : 448532 : const_iterator e1 = end();
506 [ + + ]: 2339396 : while (b1 != e1) {
507 [ + + ]: 2267144 : if ((*b1) < (*b2)) {
508 : 289236 : return true;
509 : : }
510 [ + + ]: 1977908 : if ((*b2) < (*b1)) {
511 : 87044 : return false;
512 : : }
513 : 1890864 : ++b1;
514 : 1890864 : ++b2;
515 : : }
516 : 72252 : return false;
517 : 448532 : }
518 : :
519 : 12199424 : size_t allocated_memory() const {
520 [ + + ]: 12199424 : if (is_direct()) {
521 : 3819557 : return 0;
522 : : } else {
523 : 8379867 : return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity;
524 : : }
525 : 12199424 : }
526 : :
527 : 18408646 : value_type* data() {
528 : 18408646 : return item_ptr(0);
529 : : }
530 : :
531 : 340145684 : const value_type* data() const {
532 : 340145684 : return item_ptr(0);
533 : : }
534 : : };
535 : :
536 : : #endif // BITCOIN_PREVECTOR_H
|