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