LLVM API Documentation
00001 //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_ADT_TINYPTRVECTOR_H 00011 #define LLVM_ADT_TINYPTRVECTOR_H 00012 00013 #include "llvm/ADT/ArrayRef.h" 00014 #include "llvm/ADT/PointerUnion.h" 00015 #include "llvm/ADT/SmallVector.h" 00016 00017 namespace llvm { 00018 00019 /// TinyPtrVector - This class is specialized for cases where there are 00020 /// normally 0 or 1 element in a vector, but is general enough to go beyond that 00021 /// when required. 00022 /// 00023 /// NOTE: This container doesn't allow you to store a null pointer into it. 00024 /// 00025 template <typename EltTy> 00026 class TinyPtrVector { 00027 public: 00028 typedef llvm::SmallVector<EltTy, 4> VecTy; 00029 typedef typename VecTy::value_type value_type; 00030 00031 llvm::PointerUnion<EltTy, VecTy*> Val; 00032 00033 TinyPtrVector() {} 00034 ~TinyPtrVector() { 00035 if (VecTy *V = Val.template dyn_cast<VecTy*>()) 00036 delete V; 00037 } 00038 00039 TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { 00040 if (VecTy *V = Val.template dyn_cast<VecTy*>()) 00041 Val = new VecTy(*V); 00042 } 00043 TinyPtrVector &operator=(const TinyPtrVector &RHS) { 00044 if (this == &RHS) 00045 return *this; 00046 if (RHS.empty()) { 00047 this->clear(); 00048 return *this; 00049 } 00050 00051 // Try to squeeze into the single slot. If it won't fit, allocate a copied 00052 // vector. 00053 if (Val.template is<EltTy>()) { 00054 if (RHS.size() == 1) 00055 Val = RHS.front(); 00056 else 00057 Val = new VecTy(*RHS.Val.template get<VecTy*>()); 00058 return *this; 00059 } 00060 00061 // If we have a full vector allocated, try to re-use it. 00062 if (RHS.Val.template is<EltTy>()) { 00063 Val.template get<VecTy*>()->clear(); 00064 Val.template get<VecTy*>()->push_back(RHS.front()); 00065 } else { 00066 *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>(); 00067 } 00068 return *this; 00069 } 00070 00071 TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { 00072 RHS.Val = (EltTy)nullptr; 00073 } 00074 TinyPtrVector &operator=(TinyPtrVector &&RHS) { 00075 if (this == &RHS) 00076 return *this; 00077 if (RHS.empty()) { 00078 this->clear(); 00079 return *this; 00080 } 00081 00082 // If this vector has been allocated on the heap, re-use it if cheap. If it 00083 // would require more copying, just delete it and we'll steal the other 00084 // side. 00085 if (VecTy *V = Val.template dyn_cast<VecTy*>()) { 00086 if (RHS.Val.template is<EltTy>()) { 00087 V->clear(); 00088 V->push_back(RHS.front()); 00089 return *this; 00090 } 00091 delete V; 00092 } 00093 00094 Val = RHS.Val; 00095 RHS.Val = (EltTy)nullptr; 00096 return *this; 00097 } 00098 00099 // implicit conversion operator to ArrayRef. 00100 operator ArrayRef<EltTy>() const { 00101 if (Val.isNull()) 00102 return None; 00103 if (Val.template is<EltTy>()) 00104 return *Val.getAddrOfPtr1(); 00105 return *Val.template get<VecTy*>(); 00106 } 00107 00108 bool empty() const { 00109 // This vector can be empty if it contains no element, or if it 00110 // contains a pointer to an empty vector. 00111 if (Val.isNull()) return true; 00112 if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) 00113 return Vec->empty(); 00114 return false; 00115 } 00116 00117 unsigned size() const { 00118 if (empty()) 00119 return 0; 00120 if (Val.template is<EltTy>()) 00121 return 1; 00122 return Val.template get<VecTy*>()->size(); 00123 } 00124 00125 typedef const EltTy *const_iterator; 00126 typedef EltTy *iterator; 00127 00128 iterator begin() { 00129 if (Val.template is<EltTy>()) 00130 return Val.getAddrOfPtr1(); 00131 00132 return Val.template get<VecTy *>()->begin(); 00133 00134 } 00135 iterator end() { 00136 if (Val.template is<EltTy>()) 00137 return begin() + (Val.isNull() ? 0 : 1); 00138 00139 return Val.template get<VecTy *>()->end(); 00140 } 00141 00142 const_iterator begin() const { 00143 return (const_iterator)const_cast<TinyPtrVector*>(this)->begin(); 00144 } 00145 00146 const_iterator end() const { 00147 return (const_iterator)const_cast<TinyPtrVector*>(this)->end(); 00148 } 00149 00150 EltTy operator[](unsigned i) const { 00151 assert(!Val.isNull() && "can't index into an empty vector"); 00152 if (EltTy V = Val.template dyn_cast<EltTy>()) { 00153 assert(i == 0 && "tinyvector index out of range"); 00154 return V; 00155 } 00156 00157 assert(i < Val.template get<VecTy*>()->size() && 00158 "tinyvector index out of range"); 00159 return (*Val.template get<VecTy*>())[i]; 00160 } 00161 00162 EltTy front() const { 00163 assert(!empty() && "vector empty"); 00164 if (EltTy V = Val.template dyn_cast<EltTy>()) 00165 return V; 00166 return Val.template get<VecTy*>()->front(); 00167 } 00168 00169 EltTy back() const { 00170 assert(!empty() && "vector empty"); 00171 if (EltTy V = Val.template dyn_cast<EltTy>()) 00172 return V; 00173 return Val.template get<VecTy*>()->back(); 00174 } 00175 00176 void push_back(EltTy NewVal) { 00177 assert(NewVal && "Can't add a null value"); 00178 00179 // If we have nothing, add something. 00180 if (Val.isNull()) { 00181 Val = NewVal; 00182 return; 00183 } 00184 00185 // If we have a single value, convert to a vector. 00186 if (EltTy V = Val.template dyn_cast<EltTy>()) { 00187 Val = new VecTy(); 00188 Val.template get<VecTy*>()->push_back(V); 00189 } 00190 00191 // Add the new value, we know we have a vector. 00192 Val.template get<VecTy*>()->push_back(NewVal); 00193 } 00194 00195 void pop_back() { 00196 // If we have a single value, convert to empty. 00197 if (Val.template is<EltTy>()) 00198 Val = (EltTy)nullptr; 00199 else if (VecTy *Vec = Val.template get<VecTy*>()) 00200 Vec->pop_back(); 00201 } 00202 00203 void clear() { 00204 // If we have a single value, convert to empty. 00205 if (Val.template is<EltTy>()) { 00206 Val = (EltTy)nullptr; 00207 } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { 00208 // If we have a vector form, just clear it. 00209 Vec->clear(); 00210 } 00211 // Otherwise, we're already empty. 00212 } 00213 00214 iterator erase(iterator I) { 00215 assert(I >= begin() && "Iterator to erase is out of bounds."); 00216 assert(I < end() && "Erasing at past-the-end iterator."); 00217 00218 // If we have a single value, convert to empty. 00219 if (Val.template is<EltTy>()) { 00220 if (I == begin()) 00221 Val = (EltTy)nullptr; 00222 } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { 00223 // multiple items in a vector; just do the erase, there is no 00224 // benefit to collapsing back to a pointer 00225 return Vec->erase(I); 00226 } 00227 return end(); 00228 } 00229 00230 iterator erase(iterator S, iterator E) { 00231 assert(S >= begin() && "Range to erase is out of bounds."); 00232 assert(S <= E && "Trying to erase invalid range."); 00233 assert(E <= end() && "Trying to erase past the end."); 00234 00235 if (Val.template is<EltTy>()) { 00236 if (S == begin() && S != E) 00237 Val = (EltTy)nullptr; 00238 } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { 00239 return Vec->erase(S, E); 00240 } 00241 return end(); 00242 } 00243 00244 iterator insert(iterator I, const EltTy &Elt) { 00245 assert(I >= this->begin() && "Insertion iterator is out of bounds."); 00246 assert(I <= this->end() && "Inserting past the end of the vector."); 00247 if (I == end()) { 00248 push_back(Elt); 00249 return std::prev(end()); 00250 } 00251 assert(!Val.isNull() && "Null value with non-end insert iterator."); 00252 if (EltTy V = Val.template dyn_cast<EltTy>()) { 00253 assert(I == begin()); 00254 Val = Elt; 00255 push_back(V); 00256 return begin(); 00257 } 00258 00259 return Val.template get<VecTy*>()->insert(I, Elt); 00260 } 00261 00262 template<typename ItTy> 00263 iterator insert(iterator I, ItTy From, ItTy To) { 00264 assert(I >= this->begin() && "Insertion iterator is out of bounds."); 00265 assert(I <= this->end() && "Inserting past the end of the vector."); 00266 if (From == To) 00267 return I; 00268 00269 // If we have a single value, convert to a vector. 00270 ptrdiff_t Offset = I - begin(); 00271 if (Val.isNull()) { 00272 if (std::next(From) == To) { 00273 Val = *From; 00274 return begin(); 00275 } 00276 00277 Val = new VecTy(); 00278 } else if (EltTy V = Val.template dyn_cast<EltTy>()) { 00279 Val = new VecTy(); 00280 Val.template get<VecTy*>()->push_back(V); 00281 } 00282 return Val.template get<VecTy*>()->insert(begin() + Offset, From, To); 00283 } 00284 }; 00285 } // end namespace llvm 00286 00287 #endif