diff options
Diffstat (limited to 'include/llvm/ADT/TinyPtrVector.h')
-rw-r--r-- | include/llvm/ADT/TinyPtrVector.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h new file mode 100644 index 0000000..ee86d8b --- /dev/null +++ b/include/llvm/ADT/TinyPtrVector.h @@ -0,0 +1,133 @@ +//===- 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 |