WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
SmallVector.h
Go to the documentation of this file.
1//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the SmallVector class.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef WPIUTIL_WPI_SMALLVECTOR_H
15#define WPIUTIL_WPI_SMALLVECTOR_H
16
17// This file uses std::memcpy() to copy std::pair<unsigned int, unsigned int>.
18// That type is POD, but the standard doesn't guarantee that. GCC doesn't treat
19// the type as POD so it throws a warning. We want to consider this a warning
20// instead of an error.
21#if __GNUC__ >= 8
22#pragma GCC diagnostic warning "-Wclass-memaccess"
23#endif
24
25#include "wpi/Compiler.h"
26#include "wpi/type_traits.h"
27#include <algorithm>
28#include <cassert>
29#include <cstddef>
30#include <cstdint>
31#include <cstdlib>
32#include <cstring>
33#include <functional>
34#include <initializer_list>
35#include <iterator>
36#include <limits>
37#include <memory>
38#include <new>
39#include <span>
40#include <type_traits>
41#include <utility>
42
43namespace wpi {
44
45template <typename IteratorT> class iterator_range;
46
47template <class Iterator>
48using EnableIfConvertibleToInputIterator = std::enable_if_t<std::is_convertible<
49 typename std::iterator_traits<Iterator>::iterator_category,
50 std::input_iterator_tag>::value>;
51
52/// This is all the stuff common to all SmallVectors.
53///
54/// The template parameter specifies the type which should be used to hold the
55/// Size and Capacity of the SmallVector, so it can be adjusted.
56/// Using 32 bit size is desirable to shrink the size of the SmallVector.
57/// Using 64 bit size is desirable for cases like SmallVector<char>, where a
58/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
59/// buffering bitcode output - which can exceed 4GB.
61protected:
62 void *BeginX;
63 unsigned Size = 0, Capacity;
64
65 /// The maximum value of the unsigned used.
66 static constexpr size_t SizeTypeMax() {
67 return (std::numeric_limits<unsigned>::max)();
68 }
69
70 SmallVectorBase() = delete;
71 SmallVectorBase(void *FirstEl, size_t TotalCapacity)
72 : BeginX(FirstEl), Capacity(static_cast<unsigned>(TotalCapacity)) {}
73
74 /// This is a helper for \a grow() that's out of line to reduce code
75 /// duplication. This function will report a fatal error if it can't grow at
76 /// least to \p MinSize.
77 void *mallocForGrow(void *FirstEl, size_t MinSize, size_t TSize,
78 size_t &NewCapacity);
79
80 /// This is an implementation of the grow() method which only works
81 /// on POD-like data types and is out of line to reduce code duplication.
82 /// This function will report a fatal error if it cannot increase capacity.
83 void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
84
85 /// If vector was first created with capacity 0, getFirstEl() points to the
86 /// memory right after, an area unallocated. If a subsequent allocation,
87 /// that grows the vector, happens to return the same pointer as getFirstEl(),
88 /// get a new allocation, otherwise isSmall() will falsely return that no
89 /// allocation was done (true) and the memory will not be freed in the
90 /// destructor. If a VSize is given (vector size), also copy that many
91 /// elements to the new allocation - used if realloca fails to increase
92 /// space, and happens to allocate precisely at BeginX.
93 /// This is unlikely to be called often, but resolves a memory leak when the
94 /// situation does occur.
95 void *replaceAllocation(void *NewElts, size_t TSize, size_t NewCapacity,
96 size_t VSize = 0);
97
98public:
99 size_t size() const { return Size; }
100 size_t capacity() const { return Capacity; }
101
102 [[nodiscard]] bool empty() const { return !Size; }
103
104protected:
105 /// Set the array size to \p N, which the current array must have enough
106 /// capacity for.
107 ///
108 /// This does not construct or destroy any elements in the vector.
109 void set_size(size_t N) {
110 assert(N <= capacity()); // implies no overflow in assignment
111 Size = static_cast<unsigned>(N);
112 }
113
114 /// Set the array data pointer to \p Begin and capacity to \p N.
115 ///
116 /// This does not construct or destroy any elements in the vector.
117 // This does not clean up any existing allocation.
118 void set_allocation_range(void *Begin, size_t N) {
119 assert(N <= SizeTypeMax());
120 BeginX = Begin;
121 Capacity = static_cast<unsigned>(N);
122 }
123};
124
125/// Figure out the offset of the first element.
126template <class T, typename = void> struct SmallVectorAlignmentAndSize {
127 alignas(SmallVectorBase) char Base[sizeof(
129 alignas(T) char FirstEl[sizeof(T)];
130};
131
132/// This is the part of SmallVectorTemplateBase which does not depend on whether
133/// the type T is a POD. The extra dummy template argument is used by std::span
134/// to avoid unnecessarily requiring T to be complete.
135template <typename T, typename = void>
137 : public SmallVectorBase {
138 using Base = SmallVectorBase;
139
140protected:
141 /// Find the address of the first element. For this pointer math to be valid
142 /// with small-size of 0 for T with lots of alignment, it's important that
143 /// SmallVectorStorage is properly-aligned even for small-size of 0.
144 void *getFirstEl() const {
145 return const_cast<void *>(reinterpret_cast<const void *>(
146 reinterpret_cast<const char *>(this) +
147 offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
148 }
149 // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
150
152
153 void grow_pod(size_t MinSize, size_t TSize) {
154 Base::grow_pod(getFirstEl(), MinSize, TSize);
155 }
156
157 /// Return true if this is a smallvector which has not had dynamic
158 /// memory allocated for it.
159 bool isSmall() const { return this->BeginX == getFirstEl(); }
160
161 /// Put this vector in a state of being small.
163 this->BeginX = getFirstEl();
164 this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
165 }
166
167 /// Return true if V is an internal reference to the given range.
168 bool isReferenceToRange(const void *V, const void *First, const void *Last) const {
169 // Use std::less to avoid UB.
170 std::less<> LessThan;
171 return !LessThan(V, First) && LessThan(V, Last);
172 }
173
174 /// Return true if V is an internal reference to this vector.
175 bool isReferenceToStorage(const void *V) const {
176 return isReferenceToRange(V, this->begin(), this->end());
177 }
178
179 /// Return true if First and Last form a valid (possibly empty) range in this
180 /// vector's storage.
181 bool isRangeInStorage(const void *First, const void *Last) const {
182 // Use std::less to avoid UB.
183 std::less<> LessThan;
184 return !LessThan(First, this->begin()) && !LessThan(Last, First) &&
185 !LessThan(this->end(), Last);
186 }
187
188 /// Return true unless Elt will be invalidated by resizing the vector to
189 /// NewSize.
190 bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
191 // Past the end.
193 return true;
194
195 // Return false if Elt will be destroyed by shrinking.
196 if (NewSize <= this->size())
197 return Elt < this->begin() + NewSize;
198
199 // Return false if we need to grow.
200 return NewSize <= this->capacity();
201 }
202
203 /// Check whether Elt will be invalidated by resizing the vector to NewSize.
204 void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
205 assert(isSafeToReferenceAfterResize(Elt, NewSize) &&
206 "Attempting to reference an element of the vector in an operation "
207 "that invalidates it");
208 }
209
210 /// Check whether Elt will be invalidated by increasing the size of the
211 /// vector by N.
212 void assertSafeToAdd(const void *Elt, size_t N = 1) {
213 this->assertSafeToReferenceAfterResize(Elt, this->size() + N);
214 }
215
216 /// Check whether any part of the range will be invalidated by clearing.
217 void assertSafeToReferenceAfterClear(const T *From, const T *To) {
218 if (From == To)
219 return;
221 this->assertSafeToReferenceAfterResize(To - 1, 0);
222 }
223 template <
224 class ItTy,
225 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
226 bool> = false>
228
229 /// Check whether any part of the range will be invalidated by growing.
230 void assertSafeToAddRange(const T *From, const T *To) {
231 if (From == To)
232 return;
233 this->assertSafeToAdd(From, To - From);
234 this->assertSafeToAdd(To - 1, To - From);
235 }
236 template <
237 class ItTy,
238 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
239 bool> = false>
240 void assertSafeToAddRange(ItTy, ItTy) {}
241
242 /// Reserve enough space to add one element, and return the updated element
243 /// pointer in case it was a reference to the storage.
244 template <class U>
245 static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt,
246 size_t N) {
247 size_t NewSize = This->size() + N;
248 if (LLVM_LIKELY(NewSize <= This->capacity()))
249 return &Elt;
250
251 bool ReferencesStorage = false;
252 int64_t Index = -1;
253 if (!U::TakesParamByValue) {
254 if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))) {
255 ReferencesStorage = true;
256 Index = &Elt - This->begin();
257 }
258 }
259 This->grow(NewSize);
260 return ReferencesStorage ? This->begin() + Index : &Elt;
261 }
262
263public:
264 using size_type = size_t;
265 using difference_type = ptrdiff_t;
266 using value_type = T;
267 using iterator = T *;
268 using const_iterator = const T *;
269
270 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
271 using reverse_iterator = std::reverse_iterator<iterator>;
272
273 using reference = T &;
274 using const_reference = const T &;
275 using pointer = T *;
276 using const_pointer = const T *;
277
281
282 // forward iterator creation methods.
283 iterator begin() { return (iterator)this->BeginX; }
284 const_iterator begin() const { return (const_iterator)this->BeginX; }
285 iterator end() { return begin() + size(); }
286 const_iterator end() const { return begin() + size(); }
287
288 // reverse iterator creation methods.
293
294 size_type size_in_bytes() const { return size() * sizeof(T); }
296 return (std::min)(this->SizeTypeMax(), size_type(-1) / sizeof(T));
297 }
298
299 size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
300
301 /// Return a pointer to the vector's buffer, even if empty().
302 pointer data() { return pointer(begin()); }
303 /// Return a pointer to the vector's buffer, even if empty().
304 const_pointer data() const { return const_pointer(begin()); }
305
307 assert(idx < size());
308 return begin()[idx];
309 }
311 assert(idx < size());
312 return begin()[idx];
313 }
314
316 assert(!empty());
317 return begin()[0];
318 }
320 assert(!empty());
321 return begin()[0];
322 }
323
325 assert(!empty());
326 return end()[-1];
327 }
329 assert(!empty());
330 return end()[-1];
331 }
332};
333
334/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
335/// method implementations that are designed to work with non-trivial T's.
336///
337/// We approximate is_trivially_copyable with trivial move/copy construction and
338/// trivial destruction. While the standard doesn't specify that you're allowed
339/// copy these types with memcpy, there is no way for the type to observe this.
340/// This catches the important case of std::pair<POD, POD>, which is not
341/// trivially assignable.
342template <typename T, bool = (std::is_trivially_copy_constructible<T>::value) &&
343 (std::is_trivially_move_constructible<T>::value) &&
344 std::is_trivially_destructible<T>::value>
346 friend class SmallVectorTemplateCommon<T>;
347
348protected:
349 static constexpr bool TakesParamByValue = false;
350 using ValueParamT = const T &;
351
353
354 static void destroy_range(T *S, T *E) {
355 while (S != E) {
356 --E;
357 E->~T();
358 }
359 }
360
361 /// Move the range [I, E) into the uninitialized memory starting with "Dest",
362 /// constructing elements as needed.
363 template<typename It1, typename It2>
364 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
365 std::uninitialized_move(I, E, Dest);
366 }
367
368 /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
369 /// constructing elements as needed.
370 template<typename It1, typename It2>
371 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
372 std::uninitialized_copy(I, E, Dest);
373 }
374
375 /// Grow the allocated memory (without initializing new elements), doubling
376 /// the size of the allocated memory. Guarantees space for at least one more
377 /// element, or MinSize more elements if specified.
378 void grow(size_t MinSize = 0);
379
380 /// Create a new allocation big enough for \p MinSize and pass back its size
381 /// in \p NewCapacity. This is the first section of \a grow().
382 T *mallocForGrow(size_t MinSize, size_t &NewCapacity);
383
384 /// Move existing elements over to the new allocation \p NewElts, the middle
385 /// section of \a grow().
386 void moveElementsForGrow(T *NewElts);
387
388 /// Transfer ownership of the allocation, finishing up \a grow().
389 void takeAllocationForGrow(T *NewElts, size_t NewCapacity);
390
391 /// Reserve enough space to add one element, and return the updated element
392 /// pointer in case it was a reference to the storage.
393 const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
394 return this->reserveForParamAndGetAddressImpl(this, Elt, N);
395 }
396
397 /// Reserve enough space to add one element, and return the updated element
398 /// pointer in case it was a reference to the storage.
399 T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
400 return const_cast<T *>(
401 this->reserveForParamAndGetAddressImpl(this, Elt, N));
402 }
403
404 static T &&forward_value_param(T &&V) { return std::move(V); }
405 static const T &forward_value_param(const T &V) { return V; }
406
407 void growAndAssign(size_t NumElts, const T &Elt) {
408 // Grow manually in case Elt is an internal reference.
409 size_t NewCapacity;
410 T *NewElts = mallocForGrow(NumElts, NewCapacity);
411 std::uninitialized_fill_n(NewElts, NumElts, Elt);
412 this->destroy_range(this->begin(), this->end());
413 takeAllocationForGrow(NewElts, NewCapacity);
414 this->set_size(NumElts);
415 }
416
417 template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
418 // Grow manually in case one of Args is an internal reference.
419 size_t NewCapacity;
420 T *NewElts = mallocForGrow(0, NewCapacity);
421 ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...);
422 moveElementsForGrow(NewElts);
423 takeAllocationForGrow(NewElts, NewCapacity);
424 this->set_size(this->size() + 1);
425 return this->back();
426 }
427
428public:
429 void push_back(const T &Elt) {
430 const T *EltPtr = reserveForParamAndGetAddress(Elt);
431 ::new ((void *)this->end()) T(*EltPtr);
432 this->set_size(this->size() + 1);
433 }
434
435 void push_back(T &&Elt) {
436 T *EltPtr = reserveForParamAndGetAddress(Elt);
437 ::new ((void *)this->end()) T(::std::move(*EltPtr));
438 this->set_size(this->size() + 1);
439 }
440
441 void pop_back() {
442 this->set_size(this->size() - 1);
443 this->end()->~T();
444 }
445};
446
447// Define this out-of-line to dissuade the C++ compiler from inlining it.
448template <typename T, bool TriviallyCopyable>
450 size_t NewCapacity;
451 T *NewElts = mallocForGrow(MinSize, NewCapacity);
452 moveElementsForGrow(NewElts);
453 takeAllocationForGrow(NewElts, NewCapacity);
454}
455
456template <typename T, bool TriviallyCopyable>
458 size_t MinSize, size_t &NewCapacity) {
459 return static_cast<T *>(
461 this->getFirstEl(), MinSize, sizeof(T), NewCapacity));
462}
463
464// Define this out-of-line to dissuade the C++ compiler from inlining it.
465template <typename T, bool TriviallyCopyable>
467 T *NewElts) {
468 // Move the elements over.
469 this->uninitialized_move(this->begin(), this->end(), NewElts);
470
471 // Destroy the original elements.
472 destroy_range(this->begin(), this->end());
473}
474
475// Define this out-of-line to dissuade the C++ compiler from inlining it.
476template <typename T, bool TriviallyCopyable>
478 T *NewElts, size_t NewCapacity) {
479 // If this wasn't grown from the inline copy, deallocate the old space.
480 if (!this->isSmall())
481 free(this->begin());
482
483 this->set_allocation_range(NewElts, NewCapacity);
484}
485
486/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
487/// method implementations that are designed to work with trivially copyable
488/// T's. This allows using memcpy in place of copy/move construction and
489/// skipping destruction.
490template <typename T>
492 friend class SmallVectorTemplateCommon<T>;
493
494protected:
495 /// True if it's cheap enough to take parameters by value. Doing so avoids
496 /// overhead related to mitigations for reference invalidation.
497 static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *);
498
499 /// Either const T& or T, depending on whether it's cheap enough to take
500 /// parameters by value.
501 using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
502
504
505 // No need to do a destroy loop for POD's.
506 static void destroy_range(T *, T *) {}
507
508 /// Move the range [I, E) onto the uninitialized memory
509 /// starting with "Dest", constructing elements into it as needed.
510 template<typename It1, typename It2>
511 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
512 // Just do a copy.
513 uninitialized_copy(I, E, Dest);
514 }
515
516 /// Copy the range [I, E) onto the uninitialized memory
517 /// starting with "Dest", constructing elements into it as needed.
518 template<typename It1, typename It2>
519 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
520 // Arbitrary iterator types; just use the basic implementation.
521 std::uninitialized_copy(I, E, Dest);
522 }
523
524 /// Copy the range [I, E) onto the uninitialized memory
525 /// starting with "Dest", constructing elements into it as needed.
526 template <typename T1, typename T2>
528 T1 *I, T1 *E, T2 *Dest,
529 std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>::value> * =
530 nullptr) {
531 // Use memcpy for PODs iterated by pointers (which includes SmallVector
532 // iterators): std::uninitialized_copy optimizes to memmove, but we can
533 // use memcpy here. Note that I and E are iterators and thus might be
534 // invalid for memcpy if they are equal.
535 if (I != E)
536 memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
537 }
538
539 /// Double the size of the allocated memory, guaranteeing space for at
540 /// least one more element or MinSize if specified.
541 void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
542
543 /// Reserve enough space to add one element, and return the updated element
544 /// pointer in case it was a reference to the storage.
545 const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
546 return this->reserveForParamAndGetAddressImpl(this, Elt, N);
547 }
548
549 /// Reserve enough space to add one element, and return the updated element
550 /// pointer in case it was a reference to the storage.
551 T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
552 return const_cast<T *>(
553 this->reserveForParamAndGetAddressImpl(this, Elt, N));
554 }
555
556 /// Copy \p V or return a reference, depending on \a ValueParamT.
558
559 void growAndAssign(size_t NumElts, T Elt) {
560 // Elt has been copied in case it's an internal reference, side-stepping
561 // reference invalidation problems without losing the realloc optimization.
562 this->set_size(0);
563 this->grow(NumElts);
564 std::uninitialized_fill_n(this->begin(), NumElts, Elt);
565 this->set_size(NumElts);
566 }
567
568 template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
569 // Use push_back with a copy in case Args has an internal reference,
570 // side-stepping reference invalidation problems without losing the realloc
571 // optimization.
572 push_back(T(std::forward<ArgTypes>(Args)...));
573 return this->back();
574 }
575
576public:
578 const T *EltPtr = reserveForParamAndGetAddress(Elt);
579 memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T));
580 this->set_size(this->size() + 1);
581 }
582
583 void pop_back() { this->set_size(this->size() - 1); }
584};
585
586/// This class consists of common code factored out of the SmallVector class to
587/// reduce code duplication based on the SmallVector 'N' template parameter.
588template <typename T>
589class SmallVectorImpl : public SmallVectorTemplateBase<T> {
590 using SuperClass = SmallVectorTemplateBase<T>;
591
592public:
597
598protected:
601
602 // Default ctor - Initialize to empty.
603 explicit SmallVectorImpl(unsigned N)
604 : SmallVectorTemplateBase<T>(N) {}
605
607 this->destroy_range(this->begin(), this->end());
608 if (!this->isSmall())
609 free(this->begin());
610 this->BeginX = RHS.BeginX;
611 this->Size = RHS.Size;
612 this->Capacity = RHS.Capacity;
613 RHS.resetToSmall();
614 }
615
617 // Subclass has already destructed this vector's elements.
618 // If this wasn't grown from the inline copy, deallocate the old space.
619 if (!this->isSmall())
620 free(this->begin());
621 }
622
623public:
625
626 void clear() {
627 this->destroy_range(this->begin(), this->end());
628 this->Size = 0;
629 }
630
631private:
632 // Make set_size() private to avoid misuse in subclasses.
634
635 template <bool ForOverwrite> void resizeImpl(size_type N) {
636 if (N == this->size())
637 return;
638
639 if (N < this->size()) {
640 this->truncate(N);
641 return;
642 }
643
644 this->reserve(N);
645 for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
646 if (ForOverwrite)
647 new (&*I) T;
648 else
649 new (&*I) T();
650 this->set_size(N);
651 }
652
653public:
654 void resize(size_type N) { resizeImpl<false>(N); }
655
656 /// Like resize, but \ref T is POD, the new values won't be initialized.
657 void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
658
659 /// Like resize, but requires that \p N is less than \a size().
661 assert(this->size() >= N && "Cannot increase size with truncate");
662 this->destroy_range(this->begin() + N, this->end());
663 this->set_size(N);
664 }
665
667 if (N == this->size())
668 return;
669
670 if (N < this->size()) {
671 this->truncate(N);
672 return;
673 }
674
675 // N > this->size(). Defer to append.
676 this->append(N - this->size(), NV);
677 }
678
680 if (this->capacity() < N)
681 this->grow(N);
682 }
683
684 void pop_back_n(size_type NumItems) {
685 assert(this->size() >= NumItems);
686 truncate(this->size() - NumItems);
687 }
688
689 [[nodiscard]] T pop_back_val() {
690 T Result = ::std::move(this->back());
691 this->pop_back();
692 return Result;
693 }
694
696
697 /// Add the specified range to the end of the SmallVector.
698 template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
699 void append(ItTy in_start, ItTy in_end) {
700 this->assertSafeToAddRange(in_start, in_end);
701 size_type NumInputs = std::distance(in_start, in_end);
702 this->reserve(this->size() + NumInputs);
703 this->uninitialized_copy(in_start, in_end, this->end());
704 this->set_size(this->size() + NumInputs);
705 }
706
707 /// Append \p NumInputs copies of \p Elt to the end.
708 void append(size_type NumInputs, ValueParamT Elt) {
709 const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs);
710 std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr);
711 this->set_size(this->size() + NumInputs);
712 }
713
714 void append(std::initializer_list<T> IL) {
715 append(IL.begin(), IL.end());
716 }
717
718 void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); }
719
720 void assign(size_type NumElts, ValueParamT Elt) {
721 // Note that Elt could be an internal reference.
722 if (NumElts > this->capacity()) {
723 this->growAndAssign(NumElts, Elt);
724 return;
725 }
726
727 // Assign over existing elements.
728 std::fill_n(this->begin(), (std::min)(NumElts, this->size()), Elt);
729 if (NumElts > this->size())
730 std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
731 else if (NumElts < this->size())
732 this->destroy_range(this->begin() + NumElts, this->end());
733 this->set_size(NumElts);
734 }
735
736 // FIXME: Consider assigning over existing elements, rather than clearing &
737 // re-initializing them - for all assign(...) variants.
738
739 template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
740 void assign(ItTy in_start, ItTy in_end) {
741 this->assertSafeToReferenceAfterClear(in_start, in_end);
742 clear();
743 append(in_start, in_end);
744 }
745
746 void assign(std::initializer_list<T> IL) {
747 clear();
748 append(IL);
749 }
750
751 void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); }
752
754 // Just cast away constness because this is a non-const member function.
755 iterator I = const_cast<iterator>(CI);
756
757 assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.");
758
759 iterator N = I;
760 // Shift all elts down one.
761 std::move(I+1, this->end(), I);
762 // Drop the last elt.
763 this->pop_back();
764 return(N);
765 }
766
768 // Just cast away constness because this is a non-const member function.
769 iterator S = const_cast<iterator>(CS);
770 iterator E = const_cast<iterator>(CE);
771
772 assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.");
773
774 iterator N = S;
775 // Shift all elts down.
776 iterator I = std::move(E, this->end(), S);
777 // Drop the last elts.
778 this->destroy_range(I, this->end());
779 this->set_size(I - this->begin());
780 return(N);
781 }
782
783private:
784 template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) {
785 // Callers ensure that ArgType is derived from T.
786 static_assert(
787 std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
788 T>::value,
789 "ArgType must be derived from T!");
790
791 if (I == this->end()) { // Important special case for empty vector.
792 this->push_back(::std::forward<ArgType>(Elt));
793 return this->end()-1;
794 }
795
796 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
797
798 // Grow if necessary.
799 size_t Index = I - this->begin();
800 std::remove_reference_t<ArgType> *EltPtr =
802 I = this->begin() + Index;
803
804 ::new ((void*) this->end()) T(::std::move(this->back()));
805 // Push everything else over.
806 std::move_backward(I, this->end()-1, this->end());
807 this->set_size(this->size() + 1);
808
809 // If we just moved the element we're inserting, be sure to update
810 // the reference (never happens if TakesParamByValue).
811 static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value,
812 "ArgType must be 'T' when taking by value!");
813 if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
814 ++EltPtr;
815
816 *I = ::std::forward<ArgType>(*EltPtr);
817 return I;
818 }
819
820public:
822 return insert_one_impl(I, this->forward_value_param(std::move(Elt)));
823 }
824
825 iterator insert(iterator I, const T &Elt) {
826 return insert_one_impl(I, this->forward_value_param(Elt));
827 }
828
830 // Convert iterator to elt# to avoid invalidating iterator when we reserve()
831 size_t InsertElt = I - this->begin();
832
833 if (I == this->end()) { // Important special case for empty vector.
834 append(NumToInsert, Elt);
835 return this->begin()+InsertElt;
836 }
837
838 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
839
840 // Ensure there is enough space, and get the (maybe updated) address of
841 // Elt.
842 const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert);
843
844 // Uninvalidate the iterator.
845 I = this->begin()+InsertElt;
846
847 // If there are more elements between the insertion point and the end of the
848 // range than there are being inserted, we can use a simple approach to
849 // insertion. Since we already reserved space, we know that this won't
850 // reallocate the vector.
851 if (size_t(this->end()-I) >= NumToInsert) {
852 T *OldEnd = this->end();
853 append(std::move_iterator<iterator>(this->end() - NumToInsert),
854 std::move_iterator<iterator>(this->end()));
855
856 // Copy the existing elements that get replaced.
857 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
858
859 // If we just moved the element we're inserting, be sure to update
860 // the reference (never happens if TakesParamByValue).
861 if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
862 EltPtr += NumToInsert;
863
864 std::fill_n(I, NumToInsert, *EltPtr);
865 return I;
866 }
867
868 // Otherwise, we're inserting more elements than exist already, and we're
869 // not inserting at the end.
870
871 // Move over the elements that we're about to overwrite.
872 T *OldEnd = this->end();
873 this->set_size(this->size() + NumToInsert);
874 size_t NumOverwritten = OldEnd-I;
875 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
876
877 // If we just moved the element we're inserting, be sure to update
878 // the reference (never happens if TakesParamByValue).
879 if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
880 EltPtr += NumToInsert;
881
882 // Replace the overwritten part.
883 std::fill_n(I, NumOverwritten, *EltPtr);
884
885 // Insert the non-overwritten middle part.
886 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
887 return I;
888 }
889
890 template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
891 iterator insert(iterator I, ItTy From, ItTy To) {
892 // Convert iterator to elt# to avoid invalidating iterator when we reserve()
893 size_t InsertElt = I - this->begin();
894
895 if (I == this->end()) { // Important special case for empty vector.
896 append(From, To);
897 return this->begin()+InsertElt;
898 }
899
900 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
901
902 // Check that the reserve that follows doesn't invalidate the iterators.
903 this->assertSafeToAddRange(From, To);
904
905 size_t NumToInsert = std::distance(From, To);
906
907 // Ensure there is enough space.
908 reserve(this->size() + NumToInsert);
909
910 // Uninvalidate the iterator.
911 I = this->begin()+InsertElt;
912
913 // If there are more elements between the insertion point and the end of the
914 // range than there are being inserted, we can use a simple approach to
915 // insertion. Since we already reserved space, we know that this won't
916 // reallocate the vector.
917 if (size_t(this->end()-I) >= NumToInsert) {
918 T *OldEnd = this->end();
919 append(std::move_iterator<iterator>(this->end() - NumToInsert),
920 std::move_iterator<iterator>(this->end()));
921
922 // Copy the existing elements that get replaced.
923 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
924
925 std::copy(From, To, I);
926 return I;
927 }
928
929 // Otherwise, we're inserting more elements than exist already, and we're
930 // not inserting at the end.
931
932 // Move over the elements that we're about to overwrite.
933 T *OldEnd = this->end();
934 this->set_size(this->size() + NumToInsert);
935 size_t NumOverwritten = OldEnd-I;
936 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
937
938 // Replace the overwritten part.
939 for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
940 *J = *From;
941 ++J; ++From;
942 }
943
944 // Insert the non-overwritten middle part.
945 this->uninitialized_copy(From, To, OldEnd);
946 return I;
947 }
948
949 void insert(iterator I, std::initializer_list<T> IL) {
950 insert(I, IL.begin(), IL.end());
951 }
952
953 template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
954 if (LLVM_UNLIKELY(this->size() >= this->capacity()))
955 return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
956
957 ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
958 this->set_size(this->size() + 1);
959 return this->back();
960 }
961
963
965
966 bool operator==(const SmallVectorImpl &RHS) const {
967 if (this->size() != RHS.size()) return false;
968 return std::equal(this->begin(), this->end(), RHS.begin());
969 }
970 bool operator!=(const SmallVectorImpl &RHS) const {
971 return !(*this == RHS);
972 }
973
974 bool operator<(const SmallVectorImpl &RHS) const {
975 return std::lexicographical_compare(this->begin(), this->end(),
976 RHS.begin(), RHS.end());
977 }
978 bool operator>(const SmallVectorImpl &RHS) const { return RHS < *this; }
979 bool operator<=(const SmallVectorImpl &RHS) const { return !(*this > RHS); }
980 bool operator>=(const SmallVectorImpl &RHS) const { return !(*this < RHS); }
981};
982
983template <typename T>
985 if (this == &RHS) return;
986
987 // We can only avoid copying elements if neither vector is small.
988 if (!this->isSmall() && !RHS.isSmall()) {
989 std::swap(this->BeginX, RHS.BeginX);
990 std::swap(this->Size, RHS.Size);
991 std::swap(this->Capacity, RHS.Capacity);
992 return;
993 }
994 this->reserve(RHS.size());
995 RHS.reserve(this->size());
996
997 // Swap the shared elements.
998 size_t NumShared = this->size();
999 if (NumShared > RHS.size()) NumShared = RHS.size();
1000 for (size_type i = 0; i != NumShared; ++i)
1001 std::swap((*this)[i], RHS[i]);
1002
1003 // Copy over the extra elts.
1004 if (this->size() > RHS.size()) {
1005 size_t EltDiff = this->size() - RHS.size();
1006 this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
1007 RHS.set_size(RHS.size() + EltDiff);
1008 this->destroy_range(this->begin()+NumShared, this->end());
1009 this->set_size(NumShared);
1010 } else if (RHS.size() > this->size()) {
1011 size_t EltDiff = RHS.size() - this->size();
1012 this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
1013 this->set_size(this->size() + EltDiff);
1014 this->destroy_range(RHS.begin()+NumShared, RHS.end());
1015 RHS.set_size(NumShared);
1016 }
1017}
1018
1019template <typename T>
1021 operator=(const SmallVectorImpl<T> &RHS) {
1022 // Avoid self-assignment.
1023 if (this == &RHS) return *this;
1024
1025 // If we already have sufficient space, assign the common elements, then
1026 // destroy any excess.
1027 size_t RHSSize = RHS.size();
1028 size_t CurSize = this->size();
1029 if (CurSize >= RHSSize) {
1030 // Assign common elements.
1031 iterator NewEnd;
1032 if (RHSSize)
1033 NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
1034 else
1035 NewEnd = this->begin();
1036
1037 // Destroy excess elements.
1038 this->destroy_range(NewEnd, this->end());
1039
1040 // Trim.
1041 this->set_size(RHSSize);
1042 return *this;
1043 }
1044
1045 // If we have to grow to have enough elements, destroy the current elements.
1046 // This allows us to avoid copying them during the grow.
1047 // FIXME: don't do this if they're efficiently moveable.
1048 if (this->capacity() < RHSSize) {
1049 // Destroy current elements.
1050 this->clear();
1051 CurSize = 0;
1052 this->grow(RHSSize);
1053 } else if (CurSize) {
1054 // Otherwise, use assignment for the already-constructed elements.
1055 std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
1056 }
1057
1058 // Copy construct the new elements in place.
1059 this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
1060 this->begin()+CurSize);
1061
1062 // Set end.
1063 this->set_size(RHSSize);
1064 return *this;
1065}
1066
1067template <typename T>
1069 // Avoid self-assignment.
1070 if (this == &RHS) return *this;
1071
1072 // If the RHS isn't small, clear this vector and then steal its buffer.
1073 if (!RHS.isSmall()) {
1074 this->assignRemote(std::move(RHS));
1075 return *this;
1076 }
1077
1078 // If we already have sufficient space, assign the common elements, then
1079 // destroy any excess.
1080 size_t RHSSize = RHS.size();
1081 size_t CurSize = this->size();
1082 if (CurSize >= RHSSize) {
1083 // Assign common elements.
1084 iterator NewEnd = this->begin();
1085 if (RHSSize)
1086 NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
1087
1088 // Destroy excess elements and trim the bounds.
1089 this->destroy_range(NewEnd, this->end());
1090 this->set_size(RHSSize);
1091
1092 // Clear the RHS.
1093 RHS.clear();
1094
1095 return *this;
1096 }
1097
1098 // If we have to grow to have enough elements, destroy the current elements.
1099 // This allows us to avoid copying them during the grow.
1100 // FIXME: this may not actually make any sense if we can efficiently move
1101 // elements.
1102 if (this->capacity() < RHSSize) {
1103 // Destroy current elements.
1104 this->clear();
1105 CurSize = 0;
1106 this->grow(RHSSize);
1107 } else if (CurSize) {
1108 // Otherwise, use assignment for the already-constructed elements.
1109 std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
1110 }
1111
1112 // Move-construct the new elements in place.
1113 this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
1114 this->begin()+CurSize);
1115
1116 // Set end.
1117 this->set_size(RHSSize);
1118
1119 RHS.clear();
1120 return *this;
1121}
1122
1123/// Storage for the SmallVector elements. This is specialized for the N=0 case
1124/// to avoid allocating unnecessary storage.
1125template <typename T, unsigned N>
1127 alignas(T) char InlineElts[N * sizeof(T)];
1128};
1129
1130/// We need the storage to be properly aligned even for small-size of 0 so that
1131/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
1132/// well-defined.
1133template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {};
1134
1135/// Forward declaration of SmallVector so that
1136/// calculateSmallVectorDefaultInlinedElements can reference
1137/// `sizeof(SmallVector<T, 0>)`.
1138template <typename T, unsigned N> class LLVM_GSL_OWNER SmallVector;
1139
1140/// Helper class for calculating the default number of inline elements for
1141/// `SmallVector<T>`.
1142///
1143/// This should be migrated to a constexpr function when our minimum
1144/// compiler support is enough for multi-statement constexpr functions.
1146 // Parameter controlling the default number of inlined elements
1147 // for `SmallVector<T>`.
1148 //
1149 // The default number of inlined elements ensures that
1150 // 1. There is at least one inlined element.
1151 // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
1152 // it contradicts 1.
1153 static constexpr size_t kPreferredSmallVectorSizeof = 64;
1154
1155 // static_assert that sizeof(T) is not "too big".
1156 //
1157 // Because our policy guarantees at least one inlined element, it is possible
1158 // for an arbitrarily large inlined element to allocate an arbitrarily large
1159 // amount of inline storage. We generally consider it an antipattern for a
1160 // SmallVector to allocate an excessive amount of inline storage, so we want
1161 // to call attention to these cases and make sure that users are making an
1162 // intentional decision if they request a lot of inline storage.
1163 //
1164 // We want this assertion to trigger in pathological cases, but otherwise
1165 // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
1166 // larger than kPreferredSmallVectorSizeof (otherwise,
1167 // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
1168 // pattern seems useful in practice).
1169 //
1170 // One wrinkle is that this assertion is in theory non-portable, since
1171 // sizeof(T) is in general platform-dependent. However, we don't expect this
1172 // to be much of an issue, because most LLVM development happens on 64-bit
1173 // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
1174 // 32-bit hosts, dodging the issue. The reverse situation, where development
1175 // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
1176 // 64-bit host, is expected to be very rare.
1177 static_assert(
1178 sizeof(T) <= 256,
1179 "You are trying to use a default number of inlined elements for "
1180 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1181 "explicit number of inlined elements with `SmallVector<T, N>` to make "
1182 "sure you really want that much inline storage.");
1183
1184 // Discount the size of the header itself when calculating the maximum inline
1185 // bytes.
1186 static constexpr size_t PreferredInlineBytes =
1187 kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>);
1188 static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T);
1189 static constexpr size_t value =
1190 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1191};
1192
1193/// This is a 'vector' (really, a variable-sized array), optimized
1194/// for the case when the array is small. It contains some number of elements
1195/// in-place, which allows it to avoid heap allocation when the actual number of
1196/// elements is below that threshold. This allows normal "small" cases to be
1197/// fast without losing generality for large inputs.
1198///
1199/// \note
1200/// In the absence of a well-motivated choice for the number of inlined
1201/// elements \p N, it is recommended to use \c SmallVector<T> (that is,
1202/// omitting the \p N). This will choose a default number of inlined elements
1203/// reasonable for allocation on the stack (for example, trying to keep \c
1204/// sizeof(SmallVector<T>) around 64 bytes).
1205///
1206/// \warning This does not attempt to be exception safe.
1207///
1208/// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
1209template <typename T,
1212 SmallVectorStorage<T, N> {
1213public:
1215
1217 // Destroy the constructed elements in the vector.
1218 this->destroy_range(this->begin(), this->end());
1219 }
1220
1221 explicit SmallVector(size_t Size)
1222 : SmallVectorImpl<T>(N) {
1223 this->resize(Size);
1224 }
1225
1226 SmallVector(size_t Size, const T &Value)
1227 : SmallVectorImpl<T>(N) {
1228 this->assign(Size, Value);
1229 }
1230
1231 template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
1232 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
1233 this->append(S, E);
1234 }
1235
1236 template <typename RangeTy>
1238 : SmallVectorImpl<T>(N) {
1239 this->append(R.begin(), R.end());
1240 }
1241
1242 SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
1243 this->append(IL);
1244 }
1245
1246 template <typename U,
1247 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
1248 explicit SmallVector(std::span<const U> A) : SmallVectorImpl<T>(N) {
1249 this->append(A.begin(), A.end());
1250 }
1251
1253 if (!RHS.empty())
1255 }
1256
1259 return *this;
1260 }
1261
1263 if (!RHS.empty())
1264 SmallVectorImpl<T>::operator=(::std::move(RHS));
1265 }
1266
1268 if (!RHS.empty())
1269 SmallVectorImpl<T>::operator=(::std::move(RHS));
1270 }
1271
1273 if (N) {
1274 SmallVectorImpl<T>::operator=(::std::move(RHS));
1275 return *this;
1276 }
1277 // SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
1278 // case.
1279 if (this == &RHS)
1280 return *this;
1281 if (RHS.empty()) {
1282 this->destroy_range(this->begin(), this->end());
1283 this->Size = 0;
1284 } else {
1285 this->assignRemote(std::move(RHS));
1286 }
1287 return *this;
1288 }
1289
1291 SmallVectorImpl<T>::operator=(::std::move(RHS));
1292 return *this;
1293 }
1294
1295 SmallVector &operator=(std::initializer_list<T> IL) {
1296 this->assign(IL);
1297 return *this;
1298 }
1299};
1300
1301template <typename T, unsigned N>
1302inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
1303 return X.capacity_in_bytes();
1304}
1305
1306template <typename RangeType>
1308 std::remove_const_t<std::remove_reference_t<decltype(*std::begin(
1309 std::declval<RangeType &>()))>>;
1310
1311/// Given a range of type R, iterate the entire range and return a
1312/// SmallVector with elements of the vector. This is useful, for example,
1313/// when you want to iterate a range and then sort the results.
1314template <unsigned Size, typename R>
1316 return {std::begin(Range), std::end(Range)};
1317}
1318template <typename R>
1320 return {std::begin(Range), std::end(Range)};
1321}
1322
1323template <typename Out, unsigned Size, typename R>
1325 return {std::begin(Range), std::end(Range)};
1326}
1327
1328template <typename Out, typename R> SmallVector<Out> to_vector_of(R &&Range) {
1329 return {std::begin(Range), std::end(Range)};
1330}
1331
1332template <typename T, typename Pred>
1334 SmallVectorImpl<T>& c, Pred pred) {
1335 const auto original_size = c.size();
1336 c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());
1337 return original_size - c.size();
1338}
1339
1340} // end namespace wpi
1341
1342namespace std {
1343
1344 /// Implement std::swap in terms of SmallVector swap.
1345 template<typename T>
1346 inline void
1348 LHS.swap(RHS);
1349 }
1350
1351 /// Implement std::swap in terms of SmallVector swap.
1352 template<typename T, unsigned N>
1353 inline void
1355 LHS.swap(RHS);
1356 }
1357
1358} // end namespace std
1359
1360#endif // WPIUTIL_WPI_SMALLVECTOR_H
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:253
#define LLVM_GSL_OWNER
LLVM_GSL_OWNER - Apply this to owning classes like SmallVector to enable lifetime warnings.
Definition Compiler.h:349
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:252
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or and nanopb were all modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this submitted means any form of or written communication sent to the Licensor or its including but not limited to communication on electronic mailing source code control and issue tracking systems that are managed or on behalf the Licensor for the purpose of discussing and improving the but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work Grant of Copyright License Subject to the terms and conditions of this each Contributor hereby grants to You a non no royalty free
Definition ThirdPartyNotices.txt:164
This is all the stuff common to all SmallVectors.
Definition SmallVector.h:60
void * mallocForGrow(void *FirstEl, size_t MinSize, size_t TSize, size_t &NewCapacity)
This is a helper for grow() that's out of line to reduce code duplication.
void * BeginX
Definition SmallVector.h:62
size_t size() const
Definition SmallVector.h:99
void * replaceAllocation(void *NewElts, size_t TSize, size_t NewCapacity, size_t VSize=0)
If vector was first created with capacity 0, getFirstEl() points to the memory right after,...
unsigned Capacity
Definition SmallVector.h:63
unsigned Size
Definition SmallVector.h:63
size_t capacity() const
Definition SmallVector.h:100
static constexpr size_t SizeTypeMax()
The maximum value of the unsigned used.
Definition SmallVector.h:66
void grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
This is an implementation of the grow() method which only works on POD-like data types and is out of ...
SmallVectorBase(void *FirstEl, size_t TotalCapacity)
Definition SmallVector.h:71
bool empty() const
Definition SmallVector.h:102
void set_allocation_range(void *Begin, size_t N)
Set the array data pointer to Begin and capacity to N.
Definition SmallVector.h:118
void set_size(size_t N)
Set the array size to N, which the current array must have enough capacity for.
Definition SmallVector.h:109
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition SmallVector.h:1212
SmallVector(ItTy S, ItTy E)
Definition SmallVector.h:1232
SmallVector(std::span< const U > A)
Definition SmallVector.h:1248
SmallVector(size_t Size, const T &Value)
Definition SmallVector.h:1226
SmallVector(const iterator_range< RangeTy > &R)
Definition SmallVector.h:1237
~SmallVector()
Definition SmallVector.h:1216
SmallVector(std::initializer_list< T > IL)
Definition SmallVector.h:1242
SmallVector(SmallVectorImpl< T > &&RHS)
Definition SmallVector.h:1267
SmallVector & operator=(SmallVectorImpl< T > &&RHS)
Definition SmallVector.h:1290
SmallVector()
Definition SmallVector.h:1214
SmallVector(size_t Size)
Definition SmallVector.h:1221
SmallVector(const SmallVector &RHS)
Definition SmallVector.h:1252
SmallVector & operator=(SmallVector &&RHS)
Definition SmallVector.h:1272
SmallVector & operator=(const SmallVector &RHS)
Definition SmallVector.h:1257
SmallVector(SmallVector &&RHS)
Definition SmallVector.h:1262
SmallVector & operator=(std::initializer_list< T > IL)
Definition SmallVector.h:1295
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition sha1.h:30
bool operator!=(const SmallVectorImpl &RHS) const
Definition SmallVector.h:970
SmallVectorImpl & operator=(SmallVectorImpl &&RHS)
Definition SmallVector.h:1068
iterator erase(const_iterator CI)
Definition SmallVector.h:753
~SmallVectorImpl()
Definition SmallVector.h:616
reference emplace_back(ArgTypes &&... Args)
Definition SmallVector.h:953
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
Definition SmallVector.h:657
void assign(std::initializer_list< T > IL)
Definition SmallVector.h:746
void append(std::initializer_list< T > IL)
Definition SmallVector.h:714
iterator insert(iterator I, ItTy From, ItTy To)
Definition SmallVector.h:891
bool operator==(const SmallVectorImpl &RHS) const
Definition SmallVector.h:966
T pop_back_val()
Definition SmallVector.h:689
SmallVectorImpl(unsigned N)
Definition SmallVector.h:603
SmallVectorImpl & operator=(const SmallVectorImpl &RHS)
Definition SmallVector.h:1021
bool operator>(const SmallVectorImpl &RHS) const
Definition SmallVector.h:978
void clear()
Definition SmallVector.h:626
void assignRemote(SmallVectorImpl &&RHS)
Definition SmallVector.h:606
bool operator<=(const SmallVectorImpl &RHS) const
Definition SmallVector.h:979
typename SuperClass::size_type size_type
Definition SmallVector.h:596
void swap(SmallVectorImpl &RHS)
Definition SmallVector.h:984
iterator insert(iterator I, T &&Elt)
Definition SmallVector.h:821
void reserve(size_type N)
Definition SmallVector.h:679
void assign(const SmallVectorImpl &RHS)
Definition SmallVector.h:751
void truncate(size_type N)
Like resize, but requires that N is less than size().
Definition SmallVector.h:660
typename SuperClass::iterator iterator
Definition SmallVector.h:593
bool operator<(const SmallVectorImpl &RHS) const
Definition SmallVector.h:974
void assign(size_type NumElts, ValueParamT Elt)
Definition SmallVector.h:720
typename SuperClass::ValueParamT ValueParamT
Definition SmallVector.h:600
typename SuperClass::const_iterator const_iterator
Definition SmallVector.h:594
iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt)
Definition SmallVector.h:829
typename SuperClass::reference reference
Definition SmallVector.h:595
void append(const SmallVectorImpl &RHS)
Definition SmallVector.h:718
SmallVectorImpl(const SmallVectorImpl &)=delete
void resize(size_type N, ValueParamT NV)
Definition SmallVector.h:666
void pop_back_n(size_type NumItems)
Definition SmallVector.h:684
void assign(ItTy in_start, ItTy in_end)
Definition SmallVector.h:740
void insert(iterator I, std::initializer_list< T > IL)
Definition SmallVector.h:949
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition SmallVector.h:699
void append(size_type NumInputs, ValueParamT Elt)
Append NumInputs copies of Elt to the end.
Definition SmallVector.h:708
bool operator>=(const SmallVectorImpl &RHS) const
Definition SmallVector.h:980
void resize(size_type N)
Definition SmallVector.h:654
iterator insert(iterator I, const T &Elt)
Definition SmallVector.h:825
iterator erase(const_iterator CS, const_iterator CE)
Definition SmallVector.h:767
void growAndAssign(size_t NumElts, T Elt)
Definition SmallVector.h:559
std::conditional_t< TakesParamByValue, T, const T & > ValueParamT
Either const T& or T, depending on whether it's cheap enough to take parameters by value.
Definition SmallVector.h:501
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
Definition SmallVector.h:545
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, std::enable_if_t< std::is_same< std::remove_const_t< T1 >, T2 >::value > *=nullptr)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
Definition SmallVector.h:527
static ValueParamT forward_value_param(ValueParamT V)
Copy V or return a reference, depending on ValueParamT.
Definition SmallVector.h:557
static void destroy_range(T *, T *)
Definition SmallVector.h:506
SmallVectorTemplateBase(size_t Size)
Definition SmallVector.h:503
T & growAndEmplaceBack(ArgTypes &&... Args)
Definition SmallVector.h:568
void grow(size_t MinSize=0)
Double the size of the allocated memory, guaranteeing space for at least one more element or MinSize ...
Definition SmallVector.h:541
void push_back(ValueParamT Elt)
Definition SmallVector.h:577
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
Definition SmallVector.h:519
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
Definition SmallVector.h:551
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
Definition SmallVector.h:511
void pop_back()
Definition SmallVector.h:583
SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method implementations that...
Definition SmallVector.h:345
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) into the uninitialized memory starting with "Dest", constructing elements as ne...
Definition SmallVector.h:364
void moveElementsForGrow(T *NewElts)
Move existing elements over to the new allocation NewElts, the middle section of grow().
Definition SmallVector.h:466
SmallVectorTemplateBase(size_t Size)
Definition SmallVector.h:352
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements as ne...
Definition SmallVector.h:371
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
Definition SmallVector.h:399
const T & ValueParamT
Definition SmallVector.h:350
void pop_back()
Definition SmallVector.h:441
static const T & forward_value_param(const T &V)
Definition SmallVector.h:405
static void destroy_range(T *S, T *E)
Definition SmallVector.h:354
void takeAllocationForGrow(T *NewElts, size_t NewCapacity)
Transfer ownership of the allocation, finishing up grow().
Definition SmallVector.h:477
static T && forward_value_param(T &&V)
Definition SmallVector.h:404
static constexpr bool TakesParamByValue
Definition SmallVector.h:349
T * mallocForGrow(size_t MinSize, size_t &NewCapacity)
Create a new allocation big enough for MinSize and pass back its size in NewCapacity.
Definition SmallVector.h:457
void push_back(T &&Elt)
Definition SmallVector.h:435
void grow(size_t MinSize=0)
Grow the allocated memory (without initializing new elements), doubling the size of the allocated mem...
Definition SmallVector.h:449
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
Definition SmallVector.h:393
T & growAndEmplaceBack(ArgTypes &&... Args)
Definition SmallVector.h:417
void push_back(const T &Elt)
Definition SmallVector.h:429
void growAndAssign(size_t NumElts, const T &Elt)
Definition SmallVector.h:407
This is the part of SmallVectorTemplateBase which does not depend on whether the type T is a POD.
Definition SmallVector.h:137
ptrdiff_t difference_type
Definition SmallVector.h:265
const T * const_pointer
Definition SmallVector.h:276
void assertSafeToReferenceAfterClear(const T *From, const T *To)
Check whether any part of the range will be invalidated by clearing.
Definition SmallVector.h:217
reverse_iterator rbegin()
Definition SmallVector.h:289
const_iterator begin() const
Definition SmallVector.h:284
reference front()
Definition SmallVector.h:315
size_t size() const
Definition SmallVector.h:99
size_type size_in_bytes() const
Definition SmallVector.h:294
void resetToSmall()
Put this vector in a state of being small.
Definition SmallVector.h:162
void * getFirstEl() const
Find the address of the first element.
Definition SmallVector.h:144
const_reverse_iterator rbegin() const
Definition SmallVector.h:290
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition SmallVector.h:270
const_reference operator[](size_type idx) const
Definition SmallVector.h:310
bool isReferenceToStorage(const void *V) const
Return true if V is an internal reference to this vector.
Definition SmallVector.h:175
const_pointer data() const
Return a pointer to the vector's buffer, even if empty().
Definition SmallVector.h:304
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition SmallVector.h:302
size_t capacity() const
Definition SmallVector.h:100
iterator begin()
Definition SmallVector.h:283
T * iterator
Definition SmallVector.h:267
const_reference back() const
Definition SmallVector.h:328
const T & const_reference
Definition SmallVector.h:274
size_t size_type
Definition SmallVector.h:264
reference operator[](size_type idx)
Definition SmallVector.h:306
size_t capacity_in_bytes() const
Definition SmallVector.h:299
const_reverse_iterator rend() const
Definition SmallVector.h:292
std::reverse_iterator< iterator > reverse_iterator
Definition SmallVector.h:271
const_iterator end() const
Definition SmallVector.h:286
bool isSmall() const
Return true if this is a smallvector which has not had dynamic memory allocated for it.
Definition SmallVector.h:159
T value_type
Definition SmallVector.h:266
iterator end()
Definition SmallVector.h:285
static const T * reserveForParamAndGetAddressImpl(U *This, const T &Elt, size_t N)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
Definition SmallVector.h:245
void assertSafeToAddRange(ItTy, ItTy)
Definition SmallVector.h:240
SmallVectorTemplateCommon(size_t Size)
Definition SmallVector.h:151
void assertSafeToAddRange(const T *From, const T *To)
Check whether any part of the range will be invalidated by growing.
Definition SmallVector.h:230
const_reference front() const
Definition SmallVector.h:319
T & reference
Definition SmallVector.h:273
const T * const_iterator
Definition SmallVector.h:268
T * pointer
Definition SmallVector.h:275
void assertSafeToAdd(const void *Elt, size_t N=1)
Check whether Elt will be invalidated by increasing the size of the vector by N.
Definition SmallVector.h:212
bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
Return true unless Elt will be invalidated by resizing the vector to NewSize.
Definition SmallVector.h:190
void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
Check whether Elt will be invalidated by resizing the vector to NewSize.
Definition SmallVector.h:204
bool empty() const
Definition SmallVector.h:102
bool isRangeInStorage(const void *First, const void *Last) const
Return true if First and Last form a valid (possibly empty) range in this vector's storage.
Definition SmallVector.h:181
reference back()
Definition SmallVector.h:324
bool isReferenceToRange(const void *V, const void *First, const void *Last) const
Return true if V is an internal reference to the given range.
Definition SmallVector.h:168
void assertSafeToReferenceAfterClear(ItTy, ItTy)
Definition SmallVector.h:227
size_type max_size() const
Definition SmallVector.h:295
void grow_pod(size_t MinSize, size_t TSize)
Definition SmallVector.h:153
reverse_iterator rend()
Definition SmallVector.h:291
A range adaptor for a pair of iterators.
Definition iterator_range.h:42
IteratorT end() const
Definition iterator_range.h:64
IteratorT begin() const
Definition iterator_range.h:63
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
WPI_BASIC_JSON_TPL_DECLARATION void swap(wpi::WPI_BASIC_JSON_TPL &j1, wpi::WPI_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< wpi::WPI_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< wpi::WPI_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.h:5258
Foonathan namespace.
Definition ntcore_cpp.h:26
iterator_range(Container &&) -> iterator_range< wpi::detail::IterOfRange< Container > >
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
Definition SmallVector.h:1315
std::remove_const_t< std::remove_reference_t< decltype(*std::begin( std::declval< RangeType & >()))> > ValueTypeFromRangeType
Definition SmallVector.h:1307
size_t capacity_in_bytes(const DenseMap< KeyT, ValueT, KeyInfoT > &X)
Definition DenseMap.h:1347
SmallVector< Out, Size > to_vector_of(R &&Range)
Definition SmallVector.h:1324
std::enable_if_t< std::is_convertible< typename std::iterator_traits< Iterator >::iterator_category, std::input_iterator_tag >::value > EnableIfConvertibleToInputIterator
Definition SmallVector.h:48
SmallVectorImpl< T >::size_type erase_if(SmallVectorImpl< T > &c, Pred pred)
Definition SmallVector.h:1333
Helper class for calculating the default number of inline elements for SmallVector<T>.
Definition SmallVector.h:1145
Figure out the offset of the first element.
Definition SmallVector.h:126
char FirstEl[sizeof(T)]
Definition SmallVector.h:129
Storage for the SmallVector elements.
Definition SmallVector.h:1126
#define S(label, offset, message)
Definition Errors.h:113