SmallVector.h
Go to the documentation of this file.
1 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the SmallVector class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_VECSMALL_ADT_SMALLVECTOR_H
15 #define LLVM_VECSMALL_ADT_SMALLVECTOR_H
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cstddef>
20 #include <cstdlib>
21 #include <cstring>
22 #include <initializer_list>
23 #include <iterator>
24 #include <memory>
25 
26 // LLVM Macros
27 #define LLVM_VECSMALL_NODISCARD
28 #define LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE inline
29 #define LLVM_VECSMALL_UNLIKELY(x) (x)
30 
31 // LLVM External Functions
32 namespace llvm_vecsmall {
33  namespace detail {
36  inline uint64_t NextPowerOf2(uint64_t A) {
37  A |= (A >> 1);
38  A |= (A >> 2);
39  A |= (A >> 4);
40  A |= (A >> 8);
41  A |= (A >> 16);
42  A |= (A >> 32);
43  return A + 1;
44  }
45  }
46 }
47 
48 
49 namespace llvm_vecsmall {
50 
51 // std::is_pod has been deprecated in C++20.
52 template <typename T>
53 struct IsPod : std::integral_constant<bool, std::is_standard_layout<T>::value &&
54  std::is_trivial<T>::value> {};
55 
58 protected:
59  void *BeginX, *EndX, *CapacityX;
60 
61 protected:
62  SmallVectorBase(void *FirstEl, size_t Size)
63  : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
64 
67  void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize);
68 
69 public:
71  size_t size_in_bytes() const {
72  return size_t((char*)EndX - (char*)BeginX);
73  }
74 
76  size_t capacity_in_bytes() const {
77  return size_t((char*)CapacityX - (char*)BeginX);
78  }
79 
80  LLVM_VECSMALL_NODISCARD bool empty() const { return BeginX == EndX; }
81 };
82 
83 template <typename T, unsigned N> struct SmallVectorStorage;
84 
88 template <typename T, typename = void>
90 private:
91  template <typename, unsigned> friend struct SmallVectorStorage;
92 
93  // Allocate raw space for N elements of type T. If T has a ctor or dtor, we
94  // don't want it to be automatically run, so we need to represent the space as
95  // something else. Use an array of char of sufficient alignment.
99  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
100 
101 protected:
102  SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {}
103 
104  void grow_pod(size_t MinSizeInBytes, size_t TSize) {
105  SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
106  }
107 
110  bool isSmall() const {
111  return BeginX == static_cast<const void*>(&FirstEl);
112  }
113 
115  void resetToSmall() {
116  BeginX = EndX = CapacityX = &FirstEl;
117  }
118 
119  void setEnd(T *P) { this->EndX = P; }
120 public:
121  typedef size_t size_type;
122  typedef ptrdiff_t difference_type;
123  typedef T value_type;
124  typedef T *iterator;
125  typedef const T *const_iterator;
126 
127  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
128  typedef std::reverse_iterator<iterator> reverse_iterator;
129 
130  typedef T &reference;
131  typedef const T &const_reference;
132  typedef T *pointer;
133  typedef const T *const_pointer;
134 
135  // forward iterator creation methods.
137  iterator begin() { return (iterator)this->BeginX; }
139  const_iterator begin() const { return (const_iterator)this->BeginX; }
141  iterator end() { return (iterator)this->EndX; }
143  const_iterator end() const { return (const_iterator)this->EndX; }
144 protected:
145  iterator capacity_ptr() { return (iterator)this->CapacityX; }
146  const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
147 public:
148 
149  // reverse iterator creation methods.
150  reverse_iterator rbegin() { return reverse_iterator(end()); }
151  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
152  reverse_iterator rend() { return reverse_iterator(begin()); }
153  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
154 
156  size_type size() const { return end()-begin(); }
157  size_type max_size() const { return size_type(-1) / sizeof(T); }
158 
160  size_t capacity() const { return capacity_ptr() - begin(); }
161 
163  pointer data() { return pointer(begin()); }
165  const_pointer data() const { return const_pointer(begin()); }
166 
168  reference operator[](size_type idx) {
169  assert(idx < size());
170  return begin()[idx];
171  }
173  const_reference operator[](size_type idx) const {
174  assert(idx < size());
175  return begin()[idx];
176  }
177 
178  reference front() {
179  assert(!empty());
180  return begin()[0];
181  }
182  const_reference front() const {
183  assert(!empty());
184  return begin()[0];
185  }
186 
187  reference back() {
188  assert(!empty());
189  return end()[-1];
190  }
191  const_reference back() const {
192  assert(!empty());
193  return end()[-1];
194  }
195 };
196 
199 template <typename T, bool isPodLike>
201 protected:
203 
204  static void destroy_range(T *S, T *E) {
205  while (S != E) {
206  --E;
207  E->~T();
208  }
209  }
210 
213  template<typename It1, typename It2>
214  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
215  std::uninitialized_copy(std::make_move_iterator(I),
216  std::make_move_iterator(E), Dest);
217  }
218 
221  template<typename It1, typename It2>
222  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
223  std::uninitialized_copy(I, E, Dest);
224  }
225 
229  void grow(size_t MinSize = 0);
230 
231 public:
232  void push_back(const T &Elt) {
233  if (LLVM_VECSMALL_UNLIKELY(this->EndX >= this->CapacityX))
234  this->grow();
235  ::new ((void*) this->end()) T(Elt);
236  this->setEnd(this->end()+1);
237  }
238 
239  void push_back(T &&Elt) {
240  if (LLVM_VECSMALL_UNLIKELY(this->EndX >= this->CapacityX))
241  this->grow();
242  ::new ((void*) this->end()) T(::std::move(Elt));
243  this->setEnd(this->end()+1);
244  }
245 
246  void pop_back() {
247  this->setEnd(this->end()-1);
248  this->end()->~T();
249  }
250 };
251 
252 // Define this out-of-line to dissuade the C++ compiler from inlining it.
253 template <typename T, bool isPodLike>
255  size_t CurCapacity = this->capacity();
256  size_t CurSize = this->size();
257  // Always grow, even from zero.
258  size_t NewCapacity = size_t(llvm_vecsmall::detail::NextPowerOf2(CurCapacity+2));
259  if (NewCapacity < MinSize)
260  NewCapacity = MinSize;
261  T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
262 
263  // Move the elements over.
264  this->uninitialized_move(this->begin(), this->end(), NewElts);
265 
266  // Destroy the original elements.
267  destroy_range(this->begin(), this->end());
268 
269  // If this wasn't grown from the inline copy, deallocate the old space.
270  if (!this->isSmall())
271  free(this->begin());
272 
273  this->setEnd(NewElts+CurSize);
274  this->BeginX = NewElts;
275  this->CapacityX = this->begin()+NewCapacity;
276 }
277 
278 
281 template <typename T>
283 protected:
285 
286  // No need to do a destroy loop for POD's.
287  static void destroy_range(T *, T *) {}
288 
291  template<typename It1, typename It2>
292  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
293  // Just do a copy.
294  uninitialized_copy(I, E, Dest);
295  }
296 
299  template<typename It1, typename It2>
300  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
301  // Arbitrary iterator types; just use the basic implementation.
302  std::uninitialized_copy(I, E, Dest);
303  }
304 
307  template <typename T1, typename T2>
308  static void uninitialized_copy(
309  T1 *I, T1 *E, T2 *Dest,
310  typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
311  T2>::value>::type * = nullptr) {
312  // Use memcpy for PODs iterated by pointers (which includes SmallVector
313  // iterators): std::uninitialized_copy optimizes to memmove, but we can
314  // use memcpy here. Note that I and E are iterators and thus might be
315  // invalid for memcpy if they are equal.
316  if (I != E)
317  memcpy(Dest, I, (E - I) * sizeof(T));
318  }
319 
322  void grow(size_t MinSize = 0) {
323  this->grow_pod(MinSize*sizeof(T), sizeof(T));
324  }
325 public:
326  void push_back(const T &Elt) {
327  if (LLVM_VECSMALL_UNLIKELY(this->EndX >= this->CapacityX))
328  this->grow();
329  memcpy(this->end(), &Elt, sizeof(T));
330  this->setEnd(this->end()+1);
331  }
332 
333  void pop_back() {
334  this->setEnd(this->end()-1);
335  }
336 };
337 
338 
341 template <typename T>
342 class SmallVectorImpl : public SmallVectorTemplateBase<T, IsPod<T>::value> {
344 
345  SmallVectorImpl(const SmallVectorImpl&) = delete;
346 
347 public:
348  typedef typename SuperClass::iterator iterator;
349  typedef typename SuperClass::const_iterator const_iterator;
350  typedef typename SuperClass::size_type size_type;
351 
352 protected:
353  // Default ctor - Initialize to empty.
354  explicit SmallVectorImpl(unsigned N)
355  : SmallVectorTemplateBase<T, IsPod<T>::value>(N*sizeof(T)) {
356  }
357 
358 public:
360  // Destroy the constructed elements in the vector.
361  this->destroy_range(this->begin(), this->end());
362 
363  // If this wasn't grown from the inline copy, deallocate the old space.
364  if (!this->isSmall())
365  free(this->begin());
366  }
367 
368 
369  void clear() {
370  this->destroy_range(this->begin(), this->end());
371  this->EndX = this->BeginX;
372  }
373 
374  void resize(size_type N) {
375  if (N < this->size()) {
376  this->destroy_range(this->begin()+N, this->end());
377  this->setEnd(this->begin()+N);
378  } else if (N > this->size()) {
379  if (this->capacity() < N)
380  this->grow(N);
381  for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
382  new (&*I) T();
383  this->setEnd(this->begin()+N);
384  }
385  }
386 
387  void resize(size_type N, const T &NV) {
388  if (N < this->size()) {
389  this->destroy_range(this->begin()+N, this->end());
390  this->setEnd(this->begin()+N);
391  } else if (N > this->size()) {
392  if (this->capacity() < N)
393  this->grow(N);
394  std::uninitialized_fill(this->end(), this->begin()+N, NV);
395  this->setEnd(this->begin()+N);
396  }
397  }
398 
399  void reserve(size_type N) {
400  if (this->capacity() < N)
401  this->grow(N);
402  }
403 
405  T Result = ::std::move(this->back());
406  this->pop_back();
407  return Result;
408  }
409 
410  void swap(SmallVectorImpl &RHS);
411 
413  template<typename in_iter>
414  void append(in_iter in_start, in_iter in_end) {
415  size_type NumInputs = std::distance(in_start, in_end);
416  // Grow allocated space if needed.
417  if (NumInputs > size_type(this->capacity_ptr()-this->end()))
418  this->grow(this->size()+NumInputs);
419 
420  // Copy the new elements over.
421  this->uninitialized_copy(in_start, in_end, this->end());
422  this->setEnd(this->end() + NumInputs);
423  }
424 
426  void append(size_type NumInputs, const T &Elt) {
427  // Grow allocated space if needed.
428  if (NumInputs > size_type(this->capacity_ptr()-this->end()))
429  this->grow(this->size()+NumInputs);
430 
431  // Copy the new elements over.
432  std::uninitialized_fill_n(this->end(), NumInputs, Elt);
433  this->setEnd(this->end() + NumInputs);
434  }
435 
436  void append(std::initializer_list<T> IL) {
437  append(IL.begin(), IL.end());
438  }
439 
440  void assign(size_type NumElts, const T &Elt) {
441  clear();
442  if (this->capacity() < NumElts)
443  this->grow(NumElts);
444  this->setEnd(this->begin()+NumElts);
445  std::uninitialized_fill(this->begin(), this->end(), Elt);
446  }
447 
448  void assign(std::initializer_list<T> IL) {
449  clear();
450  append(IL);
451  }
452 
453  iterator erase(const_iterator CI) {
454  // Just cast away constness because this is a non-const member function.
455  iterator I = const_cast<iterator>(CI);
456 
457  assert(I >= this->begin() && "Iterator to erase is out of bounds.");
458  assert(I < this->end() && "Erasing at past-the-end iterator.");
459 
460  iterator N = I;
461  // Shift all elts down one.
462  std::move(I+1, this->end(), I);
463  // Drop the last elt.
464  this->pop_back();
465  return(N);
466  }
467 
468  iterator erase(const_iterator CS, const_iterator CE) {
469  // Just cast away constness because this is a non-const member function.
470  iterator S = const_cast<iterator>(CS);
471  iterator E = const_cast<iterator>(CE);
472 
473  assert(S >= this->begin() && "Range to erase is out of bounds.");
474  assert(S <= E && "Trying to erase invalid range.");
475  assert(E <= this->end() && "Trying to erase past the end.");
476 
477  iterator N = S;
478  // Shift all elts down.
479  iterator I = std::move(E, this->end(), S);
480  // Drop the last elts.
481  this->destroy_range(I, this->end());
482  this->setEnd(I);
483  return(N);
484  }
485 
486  iterator insert(iterator I, T &&Elt) {
487  if (I == this->end()) { // Important special case for empty vector.
488  this->push_back(::std::move(Elt));
489  return this->end()-1;
490  }
491 
492  assert(I >= this->begin() && "Insertion iterator is out of bounds.");
493  assert(I <= this->end() && "Inserting past the end of the vector.");
494 
495  if (this->EndX >= this->CapacityX) {
496  size_t EltNo = I-this->begin();
497  this->grow();
498  I = this->begin()+EltNo;
499  }
500 
501  ::new ((void*) this->end()) T(::std::move(this->back()));
502  // Push everything else over.
503  std::move_backward(I, this->end()-1, this->end());
504  this->setEnd(this->end()+1);
505 
506  // If we just moved the element we're inserting, be sure to update
507  // the reference.
508  T *EltPtr = &Elt;
509  if (I <= EltPtr && EltPtr < this->EndX)
510  ++EltPtr;
511 
512  *I = ::std::move(*EltPtr);
513  return I;
514  }
515 
516  iterator insert(iterator I, const T &Elt) {
517  if (I == this->end()) { // Important special case for empty vector.
518  this->push_back(Elt);
519  return this->end()-1;
520  }
521 
522  assert(I >= this->begin() && "Insertion iterator is out of bounds.");
523  assert(I <= this->end() && "Inserting past the end of the vector.");
524 
525  if (this->EndX >= this->CapacityX) {
526  size_t EltNo = I-this->begin();
527  this->grow();
528  I = this->begin()+EltNo;
529  }
530  ::new ((void*) this->end()) T(std::move(this->back()));
531  // Push everything else over.
532  std::move_backward(I, this->end()-1, this->end());
533  this->setEnd(this->end()+1);
534 
535  // If we just moved the element we're inserting, be sure to update
536  // the reference.
537  const T *EltPtr = &Elt;
538  if (I <= EltPtr && EltPtr < this->EndX)
539  ++EltPtr;
540 
541  *I = *EltPtr;
542  return I;
543  }
544 
545  iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
546  // Convert iterator to elt# to avoid invalidating iterator when we reserve()
547  size_t InsertElt = I - this->begin();
548 
549  if (I == this->end()) { // Important special case for empty vector.
550  append(NumToInsert, Elt);
551  return this->begin()+InsertElt;
552  }
553 
554  assert(I >= this->begin() && "Insertion iterator is out of bounds.");
555  assert(I <= this->end() && "Inserting past the end of the vector.");
556 
557  // Ensure there is enough space.
558  reserve(this->size() + NumToInsert);
559 
560  // Uninvalidate the iterator.
561  I = this->begin()+InsertElt;
562 
563  // If there are more elements between the insertion point and the end of the
564  // range than there are being inserted, we can use a simple approach to
565  // insertion. Since we already reserved space, we know that this won't
566  // reallocate the vector.
567  if (size_t(this->end()-I) >= NumToInsert) {
568  T *OldEnd = this->end();
569  append(std::move_iterator<iterator>(this->end() - NumToInsert),
570  std::move_iterator<iterator>(this->end()));
571 
572  // Copy the existing elements that get replaced.
573  std::move_backward(I, OldEnd-NumToInsert, OldEnd);
574 
575  std::fill_n(I, NumToInsert, Elt);
576  return I;
577  }
578 
579  // Otherwise, we're inserting more elements than exist already, and we're
580  // not inserting at the end.
581 
582  // Move over the elements that we're about to overwrite.
583  T *OldEnd = this->end();
584  this->setEnd(this->end() + NumToInsert);
585  size_t NumOverwritten = OldEnd-I;
586  this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
587 
588  // Replace the overwritten part.
589  std::fill_n(I, NumOverwritten, Elt);
590 
591  // Insert the non-overwritten middle part.
592  std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
593  return I;
594  }
595 
596  template<typename ItTy>
597  iterator insert(iterator I, ItTy From, ItTy To) {
598  // Convert iterator to elt# to avoid invalidating iterator when we reserve()
599  size_t InsertElt = I - this->begin();
600 
601  if (I == this->end()) { // Important special case for empty vector.
602  append(From, To);
603  return this->begin()+InsertElt;
604  }
605 
606  assert(I >= this->begin() && "Insertion iterator is out of bounds.");
607  assert(I <= this->end() && "Inserting past the end of the vector.");
608 
609  size_t NumToInsert = std::distance(From, To);
610 
611  // Ensure there is enough space.
612  reserve(this->size() + NumToInsert);
613 
614  // Uninvalidate the iterator.
615  I = this->begin()+InsertElt;
616 
617  // If there are more elements between the insertion point and the end of the
618  // range than there are being inserted, we can use a simple approach to
619  // insertion. Since we already reserved space, we know that this won't
620  // reallocate the vector.
621  if (size_t(this->end()-I) >= NumToInsert) {
622  T *OldEnd = this->end();
623  append(std::move_iterator<iterator>(this->end() - NumToInsert),
624  std::move_iterator<iterator>(this->end()));
625 
626  // Copy the existing elements that get replaced.
627  std::move_backward(I, OldEnd-NumToInsert, OldEnd);
628 
629  std::copy(From, To, I);
630  return I;
631  }
632 
633  // Otherwise, we're inserting more elements than exist already, and we're
634  // not inserting at the end.
635 
636  // Move over the elements that we're about to overwrite.
637  T *OldEnd = this->end();
638  this->setEnd(this->end() + NumToInsert);
639  size_t NumOverwritten = OldEnd-I;
640  this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
641 
642  // Replace the overwritten part.
643  for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
644  *J = *From;
645  ++J; ++From;
646  }
647 
648  // Insert the non-overwritten middle part.
649  this->uninitialized_copy(From, To, OldEnd);
650  return I;
651  }
652 
653  void insert(iterator I, std::initializer_list<T> IL) {
654  insert(I, IL.begin(), IL.end());
655  }
656 
657  template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
658  if (LLVM_VECSMALL_UNLIKELY(this->EndX >= this->CapacityX))
659  this->grow();
660  ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
661  this->setEnd(this->end() + 1);
662  }
663 
664  SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
665 
666  SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
667 
668  bool operator==(const SmallVectorImpl &RHS) const {
669  if (this->size() != RHS.size()) return false;
670  return std::equal(this->begin(), this->end(), RHS.begin());
671  }
672  bool operator!=(const SmallVectorImpl &RHS) const {
673  return !(*this == RHS);
674  }
675 
676  bool operator<(const SmallVectorImpl &RHS) const {
677  return std::lexicographical_compare(this->begin(), this->end(),
678  RHS.begin(), RHS.end());
679  }
680 
690  void set_size(size_type N) {
691  assert(N <= this->capacity());
692  this->setEnd(this->begin() + N);
693  }
694 };
695 
696 
697 template <typename T>
699  if (this == &RHS) return;
700 
701  // We can only avoid copying elements if neither vector is small.
702  if (!this->isSmall() && !RHS.isSmall()) {
703  std::swap(this->BeginX, RHS.BeginX);
704  std::swap(this->EndX, RHS.EndX);
705  std::swap(this->CapacityX, RHS.CapacityX);
706  return;
707  }
708  if (RHS.size() > this->capacity())
709  this->grow(RHS.size());
710  if (this->size() > RHS.capacity())
711  RHS.grow(this->size());
712 
713  // Swap the shared elements.
714  size_t NumShared = this->size();
715  if (NumShared > RHS.size()) NumShared = RHS.size();
716  for (size_type i = 0; i != NumShared; ++i)
717  std::swap((*this)[i], RHS[i]);
718 
719  // Copy over the extra elts.
720  if (this->size() > RHS.size()) {
721  size_t EltDiff = this->size() - RHS.size();
722  this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
723  RHS.setEnd(RHS.end()+EltDiff);
724  this->destroy_range(this->begin()+NumShared, this->end());
725  this->setEnd(this->begin()+NumShared);
726  } else if (RHS.size() > this->size()) {
727  size_t EltDiff = RHS.size() - this->size();
728  this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
729  this->setEnd(this->end() + EltDiff);
730  this->destroy_range(RHS.begin()+NumShared, RHS.end());
731  RHS.setEnd(RHS.begin()+NumShared);
732  }
733 }
734 
735 template <typename T>
738  // Avoid self-assignment.
739  if (this == &RHS) return *this;
740 
741  // If we already have sufficient space, assign the common elements, then
742  // destroy any excess.
743  size_t RHSSize = RHS.size();
744  size_t CurSize = this->size();
745  if (CurSize >= RHSSize) {
746  // Assign common elements.
747  iterator NewEnd;
748  if (RHSSize)
749  NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
750  else
751  NewEnd = this->begin();
752 
753  // Destroy excess elements.
754  this->destroy_range(NewEnd, this->end());
755 
756  // Trim.
757  this->setEnd(NewEnd);
758  return *this;
759  }
760 
761  // If we have to grow to have enough elements, destroy the current elements.
762  // This allows us to avoid copying them during the grow.
763  // FIXME: don't do this if they're efficiently moveable.
764  if (this->capacity() < RHSSize) {
765  // Destroy current elements.
766  this->destroy_range(this->begin(), this->end());
767  this->setEnd(this->begin());
768  CurSize = 0;
769  this->grow(RHSSize);
770  } else if (CurSize) {
771  // Otherwise, use assignment for the already-constructed elements.
772  std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
773  }
774 
775  // Copy construct the new elements in place.
776  this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
777  this->begin()+CurSize);
778 
779  // Set end.
780  this->setEnd(this->begin()+RHSSize);
781  return *this;
782 }
783 
784 template <typename T>
786  // Avoid self-assignment.
787  if (this == &RHS) return *this;
788 
789  // If the RHS isn't small, clear this vector and then steal its buffer.
790  if (!RHS.isSmall()) {
791  this->destroy_range(this->begin(), this->end());
792  if (!this->isSmall()) free(this->begin());
793  this->BeginX = RHS.BeginX;
794  this->EndX = RHS.EndX;
795  this->CapacityX = RHS.CapacityX;
796  RHS.resetToSmall();
797  return *this;
798  }
799 
800  // If we already have sufficient space, assign the common elements, then
801  // destroy any excess.
802  size_t RHSSize = RHS.size();
803  size_t CurSize = this->size();
804  if (CurSize >= RHSSize) {
805  // Assign common elements.
806  iterator NewEnd = this->begin();
807  if (RHSSize)
808  NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
809 
810  // Destroy excess elements and trim the bounds.
811  this->destroy_range(NewEnd, this->end());
812  this->setEnd(NewEnd);
813 
814  // Clear the RHS.
815  RHS.clear();
816 
817  return *this;
818  }
819 
820  // If we have to grow to have enough elements, destroy the current elements.
821  // This allows us to avoid copying them during the grow.
822  // FIXME: this may not actually make any sense if we can efficiently move
823  // elements.
824  if (this->capacity() < RHSSize) {
825  // Destroy current elements.
826  this->destroy_range(this->begin(), this->end());
827  this->setEnd(this->begin());
828  CurSize = 0;
829  this->grow(RHSSize);
830  } else if (CurSize) {
831  // Otherwise, use assignment for the already-constructed elements.
832  std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
833  }
834 
835  // Move-construct the new elements in place.
836  this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
837  this->begin()+CurSize);
838 
839  // Set end.
840  this->setEnd(this->begin()+RHSSize);
841 
842  RHS.clear();
843  return *this;
844 }
845 
850 template <typename T, unsigned N>
851 struct SmallVectorStorage {
852  typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
853 };
854 template <typename T> struct SmallVectorStorage<T, 1> {};
855 template <typename T> struct SmallVectorStorage<T, 0> {};
856 
865 template <typename T, unsigned N>
866 class SmallVector : public SmallVectorImpl<T> {
869 public:
871  }
872 
873  explicit SmallVector(size_t Size, const T &Value = T())
874  : SmallVectorImpl<T>(N) {
875  this->assign(Size, Value);
876  }
877 
878  template<typename ItTy>
879  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
880  this->append(S, E);
881  }
882 
883 /*
884  template <typename RangeTy>
885  explicit SmallVector(const llvm_vecsmall::iterator_range<RangeTy> &R)
886  : SmallVectorImpl<T>(N) {
887  this->append(R.begin(), R.end());
888  }
889 */
890 
891  SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
892  this->assign(IL);
893  }
894 
896  if (!RHS.empty())
898  }
899 
900  const SmallVector &operator=(const SmallVector &RHS) {
902  return *this;
903  }
904 
906  if (!RHS.empty())
908  }
909 
912  return *this;
913  }
914 
916  if (!RHS.empty())
918  }
919 
922  return *this;
923  }
924 
925  const SmallVector &operator=(std::initializer_list<T> IL) {
926  this->assign(IL);
927  return *this;
928  }
929 };
930 
931 template<typename T, unsigned N>
932 static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
933  return X.capacity_in_bytes();
934 }
935 
936 } // End llvm_vecsmall namespace
937 
938 namespace std {
940  template<typename T>
941  inline void
943  LHS.swap(RHS);
944  }
945 
947  template<typename T, unsigned N>
948  inline void
950  LHS.swap(RHS);
951  }
952 }
953 
954 namespace llvm_vecsmall {
957 inline
958 void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSizeInBytes,
959  size_t TSize) {
960  size_t CurSizeBytes = size_in_bytes();
961  size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow.
962  if (NewCapacityInBytes < MinSizeInBytes)
963  NewCapacityInBytes = MinSizeInBytes;
964 
965  void *NewElts;
966  if (BeginX == FirstEl) {
967  NewElts = malloc(NewCapacityInBytes);
968 
969  // Copy the elements over. No need to run dtors on PODs.
970  memcpy(NewElts, this->BeginX, CurSizeBytes);
971  } else {
972  // If this wasn't grown from the inline copy, grow the allocated space.
973  NewElts = realloc(this->BeginX, NewCapacityInBytes);
974  }
975  assert(NewElts && "Out of memory");
976 
977  this->EndX = (char*)NewElts+CurSizeBytes;
978  this->BeginX = NewElts;
979  this->CapacityX = (char*)this->BeginX + NewCapacityInBytes;
980 }
981 }
982 
983 #endif
void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize)
Definition: SmallVector.h:958
SmallVectorTemplateBase< T, IsPod< T >::value > SuperClass
Definition: SmallVector.h:343
const SmallVector & operator=(const SmallVector &RHS)
Definition: SmallVector.h:900
void resize(size_type N, const T &NV)
Definition: SmallVector.h:387
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:163
LLVM_VECSMALL_NODISCARD bool empty() const
Definition: SmallVector.h:80
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:414
void set_size(size_type N)
Definition: SmallVector.h:690
SuperClass::size_type size_type
Definition: SmallVector.h:350
const SmallVector & operator=(std::initializer_list< T > IL)
Definition: SmallVector.h:925
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, typename std::enable_if< std::is_same< typename std::remove_const< T1 >::type, T2 >::value >::type *=nullptr)
Definition: SmallVector.h:308
void swap(SmallVectorImpl &RHS)
Definition: SmallVector.h:698
span_CONFIG_SIZE_TYPE size_t
Definition: span.hpp:561
size_t capacity() const
Return the total number of elements in the currently allocated buffer.
Definition: SmallVector.h:160
size_t capacity_in_bytes() const
capacity_in_bytes - This returns capacity()*sizeof(T).
Definition: SmallVector.h:76
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Definition: SmallVector.h:292
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Definition: SmallVector.h:222
SmallVector(std::initializer_list< T > IL)
Definition: SmallVector.h:891
SmallVectorStorage< T, N > Storage
Inline space for elements which aren&#39;t stored in the base class.
Definition: SmallVector.h:868
iterator erase(const_iterator CS, const_iterator CE)
Definition: SmallVector.h:468
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE const_iterator end() const
Definition: SmallVector.h:143
size_t size_in_bytes() const
This returns size()*sizeof(T).
Definition: SmallVector.h:71
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE reference operator[](size_type idx)
Definition: SmallVector.h:168
#define LLVM_VECSMALL_NODISCARD
Definition: SmallVector.h:27
void reserve(T &, std::size_t)
Definition: sol.hpp:11364
uint64_t NextPowerOf2(uint64_t A)
Definition: SmallVector.h:36
void emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:657
SmallVector(size_t Size, const T &Value=T())
Definition: SmallVector.h:873
SmallVectorBase(void *FirstEl, size_t Size)
Definition: SmallVector.h:62
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition: format.h:408
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: SmallVector.h:127
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Definition: SmallVector.h:214
#define S(x)
Definition: luac.c:667
Definition: lobject.h:49
bool operator==(const SmallVectorImpl &RHS) const
Definition: SmallVector.h:668
type
Definition: core.h:1059
SmallVectorImpl & operator=(const SmallVectorImpl &RHS)
Definition: SmallVector.h:737
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:137
void grow_pod(size_t MinSizeInBytes, size_t TSize)
Definition: SmallVector.h:104
A ROSMessage will contain one or more ROSField(s). Each field is little more than a name / type pair...
Definition: ros_field.hpp:45
OutputIterator copy(const RangeT &range, OutputIterator out)
Definition: ranges.h:50
const_reverse_iterator rend() const
Definition: SmallVector.h:153
SuperClass::const_iterator const_iterator
Definition: SmallVector.h:349
bool operator!=(const SmallVectorImpl &RHS) const
Definition: SmallVector.h:672
void assign(size_type NumElts, const T &Elt)
Definition: SmallVector.h:440
Definition: args.h:19
#define assert(condition)
Definition: lz4.c:245
void insert(iterator I, std::initializer_list< T > IL)
Definition: SmallVector.h:653
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:21884
void assign(std::initializer_list< T > IL)
Definition: SmallVector.h:448
void append(size_type NumInputs, const T &Elt)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:426
const SmallVector & operator=(SmallVectorImpl< T > &&RHS)
Definition: SmallVector.h:920
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Definition: SmallVector.h:300
This is all the non-templated stuff common to all SmallVectors.
Definition: SmallVector.h:57
std::reverse_iterator< iterator > reverse_iterator
Definition: SmallVector.h:128
iterator insert(iterator I, ItTy From, ItTy To)
Definition: SmallVector.h:597
LLVM_VECSMALL_NODISCARD T pop_back_val()
Definition: SmallVector.h:404
SmallVector(SmallVector &&RHS)
Definition: SmallVector.h:905
const SmallVector & operator=(SmallVector &&RHS)
Definition: SmallVector.h:910
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE const_iterator begin() const
Definition: SmallVector.h:139
void resetToSmall()
Put this vector in a state of being small.
Definition: SmallVector.h:115
iterator erase(const_iterator CI)
Definition: SmallVector.h:453
const T & move(const T &v)
Definition: backward.hpp:394
iterator insert(iterator I, size_type NumToInsert, const T &Elt)
Definition: SmallVector.h:545
SmallVector(SmallVectorImpl< T > &&RHS)
Definition: SmallVector.h:915
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:486
SmallVector(ItTy S, ItTy E)
Definition: SmallVector.h:879
iterator insert(iterator I, const T &Elt)
Definition: SmallVector.h:516
SmallVector(const SmallVector &RHS)
Definition: SmallVector.h:895
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE const_reference operator[](size_type idx) const
Definition: SmallVector.h:173
static void destroy_range(T *S, T *E)
Definition: SmallVector.h:204
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:156
void append(std::initializer_list< T > IL)
Definition: SmallVector.h:436
span_constexpr std::size_t size(span< T, Extent > const &spn)
Definition: span.hpp:1485
void clear(lua_State *L, int table_index)
Definition: sol.hpp:11710
static size_t capacity_in_bytes(const SmallVector< T, N > &X)
Definition: SmallVector.h:932
Definition: core.h:1131
LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:141
SuperClass::iterator iterator
Definition: SmallVector.h:348
const_pointer data() const
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:165
bool operator<(const SmallVectorImpl &RHS) const
Definition: SmallVector.h:676
std::aligned_union< 1, T >::type U
Definition: SmallVector.h:97
void swap(llvm_vecsmall::SmallVector< T, N > &LHS, llvm_vecsmall::SmallVector< T, N > &RHS)
Implement std::swap in terms of SmallVector swap.
Definition: SmallVector.h:949
#define LLVM_VECSMALL_UNLIKELY(x)
Definition: SmallVector.h:29
const_reverse_iterator rbegin() const
Definition: SmallVector.h:151
#define LLVM_VECSMALL_ATTRIBUTE_ALWAYS_INLINE
Definition: SmallVector.h:28
QCXXHighlighter::QCXXHighlighter(QTextDocument *document) m_highlightRule append)({ QRegularExpression(R"(#[a-zA-Z_]+)"), "Preprocessor" })


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:39