SmallVector.h revision dae2206390be0b1886cf0c1dba3edf079d28274f
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_ADT_SMALLVECTOR_H
15#define LLVM_ADT_SMALLVECTOR_H
16
17#include "llvm/ADT/iterator.h"
18#include "llvm/Support/type_traits.h"
19#include <algorithm>
20#include <cassert>
21#include <cstring>
22#include <memory>
23
24#ifdef _MSC_VER
25namespace std {
26#if _MSC_VER <= 1310
27  // Work around flawed VC++ implementation of std::uninitialized_copy.  Define
28  // additional overloads so that elements with pointer types are recognized as
29  // scalars and not objects, causing bizarre type conversion errors.
30  template<class T1, class T2>
31  inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
32    _Scalar_ptr_iterator_tag _Cat;
33    return _Cat;
34  }
35
36  template<class T1, class T2>
37  inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
38    _Scalar_ptr_iterator_tag _Cat;
39    return _Cat;
40  }
41#else
42// FIXME: It is not clear if the problem is fixed in VS 2005.  What is clear
43// is that the above hack won't work if it wasn't fixed.
44#endif
45}
46#endif
47
48namespace llvm {
49
50/// SmallVectorImpl - This class consists of common code factored out of the
51/// SmallVector class to reduce code duplication based on the SmallVector 'N'
52/// template parameter.
53template <typename T>
54class SmallVectorImpl {
55protected:
56  T *Begin, *End, *Capacity;
57
58  // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
59  // don't want it to be automatically run, so we need to represent the space as
60  // something else.  An array of char would work great, but might not be
61  // aligned sufficiently.  Instead, we either use GCC extensions, or some
62  // number of union instances for the space, which guarantee maximal alignment.
63protected:
64#ifdef __GNUC__
65  typedef char U;
66  U FirstEl __attribute__((aligned));
67#else
68  union U {
69    double D;
70    long double LD;
71    long long L;
72    void *P;
73  } FirstEl;
74#endif
75  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
76public:
77  // Default ctor - Initialize to empty.
78  explicit SmallVectorImpl(unsigned N)
79    : Begin(reinterpret_cast<T*>(&FirstEl)),
80      End(reinterpret_cast<T*>(&FirstEl)),
81      Capacity(reinterpret_cast<T*>(&FirstEl)+N) {
82  }
83
84  ~SmallVectorImpl() {
85    // Destroy the constructed elements in the vector.
86    destroy_range(Begin, End);
87
88    // If this wasn't grown from the inline copy, deallocate the old space.
89    if (!isSmall())
90      operator delete(Begin);
91  }
92
93  typedef size_t size_type;
94  typedef ptrdiff_t difference_type;
95  typedef T value_type;
96  typedef T* iterator;
97  typedef const T* const_iterator;
98
99  typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
100  typedef std::reverse_iterator<iterator>  reverse_iterator;
101
102  typedef T& reference;
103  typedef const T& const_reference;
104  typedef T* pointer;
105  typedef const T* const_pointer;
106
107  bool empty() const { return Begin == End; }
108  size_type size() const { return End-Begin; }
109  size_type max_size() const { return size_type(-1) / sizeof(T); }
110
111  // forward iterator creation methods.
112  iterator begin() { return Begin; }
113  const_iterator begin() const { return Begin; }
114  iterator end() { return End; }
115  const_iterator end() const { return End; }
116
117  // reverse iterator creation methods.
118  reverse_iterator rbegin()            { return reverse_iterator(end()); }
119  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
120  reverse_iterator rend()              { return reverse_iterator(begin()); }
121  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
122
123
124  /* These asserts could be "Begin + idx < End", but there are lots of places
125     in llvm where we use &v[v.size()] instead of v.end(). */
126  reference operator[](unsigned idx) {
127    assert (Begin + idx <= End);
128    return Begin[idx];
129  }
130  const_reference operator[](unsigned idx) const {
131    assert (Begin + idx <= End);
132    return Begin[idx];
133  }
134
135  reference front() {
136    return begin()[0];
137  }
138  const_reference front() const {
139    return begin()[0];
140  }
141
142  reference back() {
143    return end()[-1];
144  }
145  const_reference back() const {
146    return end()[-1];
147  }
148
149  void push_back(const_reference Elt) {
150    if (End < Capacity) {
151  Retry:
152      new (End) T(Elt);
153      ++End;
154      return;
155    }
156    grow();
157    goto Retry;
158  }
159
160  void pop_back() {
161    --End;
162    End->~T();
163  }
164
165  T pop_back_val() {
166    T Result = back();
167    pop_back();
168    return Result;
169  }
170
171  void clear() {
172    destroy_range(Begin, End);
173    End = Begin;
174  }
175
176  void resize(unsigned N) {
177    if (N < size()) {
178      destroy_range(Begin+N, End);
179      End = Begin+N;
180    } else if (N > size()) {
181      if (unsigned(Capacity-Begin) < N)
182        grow(N);
183      construct_range(End, Begin+N, T());
184      End = Begin+N;
185    }
186  }
187
188  void resize(unsigned N, const T &NV) {
189    if (N < size()) {
190      destroy_range(Begin+N, End);
191      End = Begin+N;
192    } else if (N > size()) {
193      if (unsigned(Capacity-Begin) < N)
194        grow(N);
195      construct_range(End, Begin+N, NV);
196      End = Begin+N;
197    }
198  }
199
200  void reserve(unsigned N) {
201    if (unsigned(Capacity-Begin) < N)
202      grow(N);
203  }
204
205  void swap(SmallVectorImpl &RHS);
206
207  /// append - Add the specified range to the end of the SmallVector.
208  ///
209  template<typename in_iter>
210  void append(in_iter in_start, in_iter in_end) {
211    size_type NumInputs = std::distance(in_start, in_end);
212    // Grow allocated space if needed.
213    if (End+NumInputs > Capacity)
214      grow(size()+NumInputs);
215
216    // Copy the new elements over.
217    std::uninitialized_copy(in_start, in_end, End);
218    End += NumInputs;
219  }
220
221  /// append - Add the specified range to the end of the SmallVector.
222  ///
223  void append(size_type NumInputs, const T &Elt) {
224    // Grow allocated space if needed.
225    if (End+NumInputs > Capacity)
226      grow(size()+NumInputs);
227
228    // Copy the new elements over.
229    std::uninitialized_fill_n(End, NumInputs, Elt);
230    End += NumInputs;
231  }
232
233  void assign(unsigned NumElts, const T &Elt) {
234    clear();
235    if (unsigned(Capacity-Begin) < NumElts)
236      grow(NumElts);
237    End = Begin+NumElts;
238    construct_range(Begin, End, Elt);
239  }
240
241  iterator erase(iterator I) {
242    iterator N = I;
243    // Shift all elts down one.
244    std::copy(I+1, End, I);
245    // Drop the last elt.
246    pop_back();
247    return(N);
248  }
249
250  iterator erase(iterator S, iterator E) {
251    iterator N = S;
252    // Shift all elts down.
253    iterator I = std::copy(E, End, S);
254    // Drop the last elts.
255    destroy_range(I, End);
256    End = I;
257    return(N);
258  }
259
260  iterator insert(iterator I, const T &Elt) {
261    if (I == End) {  // Important special case for empty vector.
262      push_back(Elt);
263      return end()-1;
264    }
265
266    if (End < Capacity) {
267  Retry:
268      new (End) T(back());
269      ++End;
270      // Push everything else over.
271      std::copy_backward(I, End-1, End);
272      *I = Elt;
273      return I;
274    }
275    size_t EltNo = I-Begin;
276    grow();
277    I = Begin+EltNo;
278    goto Retry;
279  }
280
281  iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
282    if (I == End) {  // Important special case for empty vector.
283      append(NumToInsert, Elt);
284      return end()-1;
285    }
286
287    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
288    size_t InsertElt = I-begin();
289
290    // Ensure there is enough space.
291    reserve(static_cast<unsigned>(size() + NumToInsert));
292
293    // Uninvalidate the iterator.
294    I = begin()+InsertElt;
295
296    // If there are more elements between the insertion point and the end of the
297    // range than there are being inserted, we can use a simple approach to
298    // insertion.  Since we already reserved space, we know that this won't
299    // reallocate the vector.
300    if (size_t(end()-I) >= NumToInsert) {
301      T *OldEnd = End;
302      append(End-NumToInsert, End);
303
304      // Copy the existing elements that get replaced.
305      std::copy(I, OldEnd-NumToInsert, I+NumToInsert);
306
307      std::fill_n(I, NumToInsert, Elt);
308      return I;
309    }
310
311    // Otherwise, we're inserting more elements than exist already, and we're
312    // not inserting at the end.
313
314    // Copy over the elements that we're about to overwrite.
315    T *OldEnd = End;
316    End += NumToInsert;
317    size_t NumOverwritten = OldEnd-I;
318    std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
319
320    // Replace the overwritten part.
321    std::fill_n(I, NumOverwritten, Elt);
322
323    // Insert the non-overwritten middle part.
324    std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
325    return I;
326  }
327
328  template<typename ItTy>
329  iterator insert(iterator I, ItTy From, ItTy To) {
330    if (I == End) {  // Important special case for empty vector.
331      append(From, To);
332      return end()-1;
333    }
334
335    size_t NumToInsert = std::distance(From, To);
336    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
337    size_t InsertElt = I-begin();
338
339    // Ensure there is enough space.
340    reserve(static_cast<unsigned>(size() + NumToInsert));
341
342    // Uninvalidate the iterator.
343    I = begin()+InsertElt;
344
345    // If there are more elements between the insertion point and the end of the
346    // range than there are being inserted, we can use a simple approach to
347    // insertion.  Since we already reserved space, we know that this won't
348    // reallocate the vector.
349    if (size_t(end()-I) >= NumToInsert) {
350      T *OldEnd = End;
351      append(End-NumToInsert, End);
352
353      // Copy the existing elements that get replaced.
354      std::copy(I, OldEnd-NumToInsert, I+NumToInsert);
355
356      std::copy(From, To, I);
357      return I;
358    }
359
360    // Otherwise, we're inserting more elements than exist already, and we're
361    // not inserting at the end.
362
363    // Copy over the elements that we're about to overwrite.
364    T *OldEnd = End;
365    End += NumToInsert;
366    size_t NumOverwritten = OldEnd-I;
367    std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
368
369    // Replace the overwritten part.
370    std::copy(From, From+NumOverwritten, I);
371
372    // Insert the non-overwritten middle part.
373    std::uninitialized_copy(From+NumOverwritten, To, OldEnd);
374    return I;
375  }
376
377  const SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
378
379  bool operator==(const SmallVectorImpl &RHS) const {
380    if (size() != RHS.size()) return false;
381    for (T *This = Begin, *That = RHS.Begin, *E = Begin+size();
382         This != E; ++This, ++That)
383      if (*This != *That)
384        return false;
385    return true;
386  }
387  bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); }
388
389  bool operator<(const SmallVectorImpl &RHS) const {
390    return std::lexicographical_compare(begin(), end(),
391                                        RHS.begin(), RHS.end());
392  }
393
394private:
395  /// isSmall - Return true if this is a smallvector which has not had dynamic
396  /// memory allocated for it.
397  bool isSmall() const {
398    return static_cast<const void*>(Begin) ==
399           static_cast<const void*>(&FirstEl);
400  }
401
402  /// grow - double the size of the allocated memory, guaranteeing space for at
403  /// least one more element or MinSize if specified.
404  void grow(size_type MinSize = 0);
405
406  void construct_range(T *S, T *E, const T &Elt) {
407    for (; S != E; ++S)
408      new (S) T(Elt);
409  }
410
411  void destroy_range(T *S, T *E) {
412    while (S != E) {
413      --E;
414      E->~T();
415    }
416  }
417};
418
419// Define this out-of-line to dissuade the C++ compiler from inlining it.
420template <typename T>
421void SmallVectorImpl<T>::grow(size_t MinSize) {
422  size_t CurCapacity = Capacity-Begin;
423  size_t CurSize = size();
424  size_t NewCapacity = 2*CurCapacity;
425  if (NewCapacity < MinSize)
426    NewCapacity = MinSize;
427  T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T)));
428
429  // Copy the elements over.
430  if (is_class<T>::value)
431    std::uninitialized_copy(Begin, End, NewElts);
432  else
433    // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
434    memcpy(NewElts, Begin, CurSize * sizeof(T));
435
436  // Destroy the original elements.
437  destroy_range(Begin, End);
438
439  // If this wasn't grown from the inline copy, deallocate the old space.
440  if (!isSmall())
441    operator delete(Begin);
442
443  Begin = NewElts;
444  End = NewElts+CurSize;
445  Capacity = Begin+NewCapacity;
446}
447
448template <typename T>
449void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
450  if (this == &RHS) return;
451
452  // We can only avoid copying elements if neither vector is small.
453  if (!isSmall() && !RHS.isSmall()) {
454    std::swap(Begin, RHS.Begin);
455    std::swap(End, RHS.End);
456    std::swap(Capacity, RHS.Capacity);
457    return;
458  }
459  if (Begin+RHS.size() > Capacity)
460    grow(RHS.size());
461  if (RHS.begin()+size() > RHS.Capacity)
462    RHS.grow(size());
463
464  // Swap the shared elements.
465  size_t NumShared = size();
466  if (NumShared > RHS.size()) NumShared = RHS.size();
467  for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
468    std::swap(Begin[i], RHS[i]);
469
470  // Copy over the extra elts.
471  if (size() > RHS.size()) {
472    size_t EltDiff = size() - RHS.size();
473    std::uninitialized_copy(Begin+NumShared, End, RHS.End);
474    RHS.End += EltDiff;
475    destroy_range(Begin+NumShared, End);
476    End = Begin+NumShared;
477  } else if (RHS.size() > size()) {
478    size_t EltDiff = RHS.size() - size();
479    std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End);
480    End += EltDiff;
481    destroy_range(RHS.Begin+NumShared, RHS.End);
482    RHS.End = RHS.Begin+NumShared;
483  }
484}
485
486template <typename T>
487const SmallVectorImpl<T> &
488SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) {
489  // Avoid self-assignment.
490  if (this == &RHS) return *this;
491
492  // If we already have sufficient space, assign the common elements, then
493  // destroy any excess.
494  unsigned RHSSize = unsigned(RHS.size());
495  unsigned CurSize = unsigned(size());
496  if (CurSize >= RHSSize) {
497    // Assign common elements.
498    iterator NewEnd;
499    if (RHSSize)
500      NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin);
501    else
502      NewEnd = Begin;
503
504    // Destroy excess elements.
505    destroy_range(NewEnd, End);
506
507    // Trim.
508    End = NewEnd;
509    return *this;
510  }
511
512  // If we have to grow to have enough elements, destroy the current elements.
513  // This allows us to avoid copying them during the grow.
514  if (unsigned(Capacity-Begin) < RHSSize) {
515    // Destroy current elements.
516    destroy_range(Begin, End);
517    End = Begin;
518    CurSize = 0;
519    grow(RHSSize);
520  } else if (CurSize) {
521    // Otherwise, use assignment for the already-constructed elements.
522    std::copy(RHS.Begin, RHS.Begin+CurSize, Begin);
523  }
524
525  // Copy construct the new elements in place.
526  std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
527
528  // Set end.
529  End = Begin+RHSSize;
530  return *this;
531}
532
533/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
534/// for the case when the array is small.  It contains some number of elements
535/// in-place, which allows it to avoid heap allocation when the actual number of
536/// elements is below that threshold.  This allows normal "small" cases to be
537/// fast without losing generality for large inputs.
538///
539/// Note that this does not attempt to be exception safe.
540///
541template <typename T, unsigned N>
542class SmallVector : public SmallVectorImpl<T> {
543  /// InlineElts - These are 'N-1' elements that are stored inline in the body
544  /// of the vector.  The extra '1' element is stored in SmallVectorImpl.
545  typedef typename SmallVectorImpl<T>::U U;
546  enum {
547    // MinUs - The number of U's require to cover N T's.
548    MinUs = (static_cast<unsigned int>(sizeof(T))*N +
549             static_cast<unsigned int>(sizeof(U)) - 1) /
550            static_cast<unsigned int>(sizeof(U)),
551
552    // NumInlineEltsElts - The number of elements actually in this array.  There
553    // is already one in the parent class, and we have to round up to avoid
554    // having a zero-element array.
555    NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1,
556
557    // NumTsAvailable - The number of T's we actually have space for, which may
558    // be more than N due to rounding.
559    NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/
560                     static_cast<unsigned int>(sizeof(T))
561  };
562  U InlineElts[NumInlineEltsElts];
563public:
564  SmallVector() : SmallVectorImpl<T>(NumTsAvailable) {
565  }
566
567  explicit SmallVector(unsigned Size, const T &Value = T())
568    : SmallVectorImpl<T>(NumTsAvailable) {
569    this->reserve(Size);
570    while (Size--)
571      this->push_back(Value);
572  }
573
574  template<typename ItTy>
575  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) {
576    this->append(S, E);
577  }
578
579  SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) {
580    if (!RHS.empty())
581      SmallVectorImpl<T>::operator=(RHS);
582  }
583
584  const SmallVector &operator=(const SmallVector &RHS) {
585    SmallVectorImpl<T>::operator=(RHS);
586    return *this;
587  }
588
589};
590
591} // End llvm namespace
592
593namespace std {
594  /// Implement std::swap in terms of SmallVector swap.
595  template<typename T>
596  inline void
597  swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
598    LHS.swap(RHS);
599  }
600
601  /// Implement std::swap in terms of SmallVector swap.
602  template<typename T, unsigned N>
603  inline void
604  swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
605    LHS.swap(RHS);
606  }
607}
608
609#endif
610