LLVM API Documentation

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