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