SmallVector.h revision 80b65823147ba498efd9a5df72afc7ff7d9dc0d9
1//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source 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 <algorithm> 18#include <iterator> 19#include <memory> 20 21namespace llvm { 22 23/// SmallVectorImpl - This class consists of common code factored out of the 24/// SmallVector class to reduce code duplication based on the SmallVector 'N' 25/// template parameter. 26template <typename T> 27class SmallVectorImpl { 28 T *Begin, *End, *Capacity; 29 30 // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 31 // don't want it to be automatically run, so we need to represent the space as 32 // something else. An array of char would work great, but might not be 33 // aligned sufficiently. Instead, we either use GCC extensions, or some 34 // number of union instances for the space, which guarantee maximal alignment. 35protected: 36 union U { 37 double D; 38 long double LD; 39 long long L; 40 void *P; 41 } FirstEl; 42 // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 43public: 44 // Default ctor - Initialize to empty. 45 SmallVectorImpl(unsigned N) 46 : Begin((T*)&FirstEl), End((T*)&FirstEl), Capacity((T*)&FirstEl+N) { 47 } 48 49 ~SmallVectorImpl() { 50 // Destroy the constructed elements in the vector. 51 for (iterator I = Begin, E = End; I != E; ++I) 52 I->~T(); 53 54 // If this wasn't grown from the inline copy, deallocate the old space. 55 if (!isSmall()) 56 delete[] (char*)Begin; 57 } 58 59 typedef size_t size_type; 60 typedef T* iterator; 61 typedef const T* const_iterator; 62 typedef T& reference; 63 typedef const T& const_reference; 64 65 bool empty() const { return Begin == End; } 66 size_type size() const { return End-Begin; } 67 68 iterator begin() { return Begin; } 69 const_iterator begin() const { return Begin; } 70 71 iterator end() { return End; } 72 const_iterator end() const { return End; } 73 74 reference operator[](unsigned idx) { 75 return Begin[idx]; 76 } 77 const_reference operator[](unsigned idx) const { 78 return Begin[idx]; 79 } 80 81 reference back() { 82 return end()[-1]; 83 } 84 const_reference back() const { 85 return end()[-1]; 86 } 87 88 void push_back(const_reference Elt) { 89 if (End < Capacity) { 90 Retry: 91 new (End) T(Elt); 92 ++End; 93 return; 94 } 95 grow(); 96 goto Retry; 97 } 98 99 void pop_back() { 100 --End; 101 End->~T(); 102 } 103 104 void clear() { 105 while (End != Begin) { 106 End->~T(); 107 --End; 108 } 109 } 110 111 /// append - Add the specified range to the end of the SmallVector. 112 /// 113 template<typename in_iter> 114 void append(in_iter in_start, in_iter in_end) { 115 unsigned NumInputs = std::distance(in_start, in_end); 116 // Grow allocated space if needed. 117 if (End+NumInputs > Capacity) 118 grow(size()+NumInputs); 119 120 // Copy the new elements over. 121 std::uninitialized_copy(in_start, in_end, End); 122 End += NumInputs; 123 } 124 125 void assign(unsigned NumElts, const T &Elt) { 126 clear(); 127 if (Begin+NumElts > Capacity) 128 grow(NumElts); 129 End = Begin+NumElts; 130 for (; NumElts; --NumElts) 131 new (Begin+NumElts-1) T(Elt); 132 } 133 134 const SmallVectorImpl &operator=(const SmallVectorImpl &RHS) { 135 // Avoid self-assignment. 136 if (this == &RHS) return *this; 137 138 // If we already have sufficient space, assign the common elements, then 139 // destroy any excess. 140 unsigned RHSSize = RHS.size(); 141 unsigned CurSize = size(); 142 if (CurSize >= RHSSize) { 143 // Assign common elements. 144 std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); 145 146 // Destroy excess elements. 147 for (unsigned i = RHSSize; i != CurSize; ++i) 148 Begin[i].~T(); 149 150 // Trim. 151 End = Begin + RHSSize; 152 return *this; 153 } 154 155 // If we have to grow to have enough elements, destroy the current elements. 156 // This allows us to avoid copying them during the grow. 157 if (Capacity-Begin < RHSSize) { 158 // Destroy current elements. 159 for (iterator I = Begin, E = End; I != E; ++I) 160 I->~T(); 161 End = Begin; 162 CurSize = 0; 163 grow(RHSSize); 164 } else if (CurSize) { 165 // Otherwise, use assignment for the already-constructed elements. 166 std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); 167 } 168 169 // Copy construct the new elements in place. 170 std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); 171 172 // Set end. 173 End = Begin+RHSSize; 174 } 175 176private: 177 /// isSmall - Return true if this is a smallvector which has not had dynamic 178 /// memory allocated for it. 179 bool isSmall() const { 180 return (void*)Begin == (void*)&FirstEl; 181 } 182 183 /// grow - double the size of the allocated memory, guaranteeing space for at 184 /// least one more element or MinSize if specified. 185 void grow(unsigned MinSize = 0) { 186 unsigned CurCapacity = Capacity-Begin; 187 unsigned CurSize = size(); 188 unsigned NewCapacity = 2*CurCapacity; 189 if (NewCapacity < MinSize) 190 NewCapacity = MinSize; 191 T *NewElts = reinterpret_cast<T*>(new char[NewCapacity*sizeof(T)]); 192 193 // Copy the elements over. 194 std::uninitialized_copy(Begin, End, NewElts); 195 196 // Destroy the original elements. 197 for (iterator I = Begin, E = End; I != E; ++I) 198 I->~T(); 199 200 // If this wasn't grown from the inline copy, deallocate the old space. 201 if (!isSmall()) 202 delete[] (char*)Begin; 203 204 Begin = NewElts; 205 End = NewElts+CurSize; 206 Capacity = Begin+NewCapacity; 207 } 208}; 209 210 211/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized 212/// for the case when the array is small. It contains some number of elements 213/// in-place, which allows it to avoid heap allocation when the actual number of 214/// elements is below that threshold. This allows normal "small" cases to be 215/// fast without losing generality for large inputs. 216/// 217/// Note that this does not attempt to be exception safe. 218/// 219template <typename T, unsigned N> 220class SmallVector : public SmallVectorImpl<T> { 221 /// InlineElts - These are 'N-1' elements that are stored inline in the body 222 /// of the vector. The extra '1' element is stored in SmallVectorImpl. 223 typedef typename SmallVectorImpl<T>::U U; 224 U InlineElts[(sizeof(T)*N+sizeof(U)-1)/sizeof(U) - 1]; 225public: 226 SmallVector() : SmallVectorImpl<T>(N) { 227 } 228 229 template<typename ItTy> 230 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) { 231 append(S, E); 232 } 233 234 SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { 235 operator=(RHS); 236 } 237}; 238 239} // End llvm namespace 240 241#endif 242