| //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_ADT_TINYPTRVECTOR_H | |
| #define LLVM_ADT_TINYPTRVECTOR_H | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/ADT/PointerUnion.h" | |
| namespace llvm { | |
| /// TinyPtrVector - This class is specialized for cases where there are | |
| /// normally 0 or 1 element in a vector, but is general enough to go beyond that | |
| /// when required. | |
| /// | |
| /// NOTE: This container doesn't allow you to store a null pointer into it. | |
| /// | |
| template <typename EltTy> | |
| class TinyPtrVector { | |
| public: | |
| typedef llvm::SmallVector<EltTy, 4> VecTy; | |
| llvm::PointerUnion<EltTy, VecTy*> Val; | |
| TinyPtrVector() {} | |
| TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { | |
| if (VecTy *V = Val.template dyn_cast<VecTy*>()) | |
| Val = new VecTy(*V); | |
| } | |
| ~TinyPtrVector() { | |
| if (VecTy *V = Val.template dyn_cast<VecTy*>()) | |
| delete V; | |
| } | |
| bool empty() const { | |
| // This vector can be empty if it contains no element, or if it | |
| // contains a pointer to an empty vector. | |
| if (Val.isNull()) return true; | |
| if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) | |
| return Vec->empty(); | |
| return false; | |
| } | |
| unsigned size() const { | |
| if (empty()) | |
| return 0; | |
| if (Val.template is<EltTy>()) | |
| return 1; | |
| return Val.template get<VecTy*>()->size(); | |
| } | |
| typedef const EltTy *iterator; | |
| iterator begin() const { | |
| if (empty()) | |
| return 0; | |
| if (Val.template is<EltTy>()) | |
| return Val.template getAddrOf<EltTy>(); | |
| return Val.template get<VecTy *>()->begin(); | |
| } | |
| iterator end() const { | |
| if (empty()) | |
| return 0; | |
| if (Val.template is<EltTy>()) | |
| return begin() + 1; | |
| return Val.template get<VecTy *>()->end(); | |
| } | |
| EltTy operator[](unsigned i) const { | |
| assert(!Val.isNull() && "can't index into an empty vector"); | |
| if (EltTy V = Val.template dyn_cast<EltTy>()) { | |
| assert(i == 0 && "tinyvector index out of range"); | |
| return V; | |
| } | |
| assert(i < Val.template get<VecTy*>()->size() && | |
| "tinyvector index out of range"); | |
| return (*Val.template get<VecTy*>())[i]; | |
| } | |
| EltTy front() const { | |
| assert(!empty() && "vector empty"); | |
| if (EltTy V = Val.template dyn_cast<EltTy>()) | |
| return V; | |
| return Val.template get<VecTy*>()->front(); | |
| } | |
| void push_back(EltTy NewVal) { | |
| assert(NewVal != 0 && "Can't add a null value"); | |
| // If we have nothing, add something. | |
| if (Val.isNull()) { | |
| Val = NewVal; | |
| return; | |
| } | |
| // If we have a single value, convert to a vector. | |
| if (EltTy V = Val.template dyn_cast<EltTy>()) { | |
| Val = new VecTy(); | |
| Val.template get<VecTy*>()->push_back(V); | |
| } | |
| // Add the new value, we know we have a vector. | |
| Val.template get<VecTy*>()->push_back(NewVal); | |
| } | |
| void clear() { | |
| // If we have a single value, convert to empty. | |
| if (Val.template is<EltTy>()) { | |
| Val = (EltTy)0; | |
| } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { | |
| // If we have a vector form, just clear it. | |
| Vec->clear(); | |
| } | |
| // Otherwise, we're already empty. | |
| } | |
| private: | |
| void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET. | |
| }; | |
| } // end namespace llvm | |
| #endif |