e27dd4b78507cd3cc50930d4326ee5e08f0afe4d
[oota-llvm.git] / include / llvm / ADT / TinyPtrVector.h
1 //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_ADT_TINYPTRVECTOR_H
11 #define LLVM_ADT_TINYPTRVECTOR_H
12
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/PointerUnion.h"
15
16 namespace llvm {
17   
18 /// TinyPtrVector - This class is specialized for cases where there are
19 /// normally 0 or 1 element in a vector, but is general enough to go beyond that
20 /// when required.
21 ///
22 /// NOTE: This container doesn't allow you to store a null pointer into it.
23 ///
24 template <typename EltTy>
25 class TinyPtrVector {
26 public:
27   typedef llvm::SmallVector<EltTy, 4> VecTy;
28   llvm::PointerUnion<EltTy, VecTy*> Val;
29   
30   TinyPtrVector() {}
31   TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
32     if (VecTy *V = Val.template dyn_cast<VecTy*>())
33       Val = new VecTy(*V);
34   }
35   ~TinyPtrVector() {
36     if (VecTy *V = Val.template dyn_cast<VecTy*>())
37       delete V;
38   }
39   
40   // implicit conversion operator to ArrayRef.
41   operator ArrayRef<EltTy>() const {
42     if (Val.isNull())
43       return ArrayRef<EltTy>();
44     if (Val.template is<EltTy>())
45       return *Val.template getAddrOf<EltTy>();
46     return *Val.template get<VecTy*>();
47   }
48   
49   bool empty() const {
50     // This vector can be empty if it contains no element, or if it
51     // contains a pointer to an empty vector.
52     if (Val.isNull()) return true;
53     if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
54       return Vec->empty();
55     return false;
56   }
57   
58   unsigned size() const {
59     if (empty())
60       return 0;
61     if (Val.template is<EltTy>())
62       return 1;
63     return Val.template get<VecTy*>()->size();
64   }
65   
66   typedef const EltTy *iterator;
67   iterator begin() const {
68     if (empty())
69       return 0;
70     
71     if (Val.template is<EltTy>())
72       return Val.template getAddrOf<EltTy>();
73     
74     return Val.template get<VecTy *>()->begin();
75
76   }
77   iterator end() const {
78     if (empty())
79       return 0;
80     
81     if (Val.template is<EltTy>())
82       return begin() + 1;
83     
84     return Val.template get<VecTy *>()->end();
85   }
86
87   
88   EltTy operator[](unsigned i) const {
89     assert(!Val.isNull() && "can't index into an empty vector");
90     if (EltTy V = Val.template dyn_cast<EltTy>()) {
91       assert(i == 0 && "tinyvector index out of range");
92       return V;
93     }
94     
95     assert(i < Val.template get<VecTy*>()->size() && 
96            "tinyvector index out of range");
97     return (*Val.template get<VecTy*>())[i];
98   }
99   
100   EltTy front() const {
101     assert(!empty() && "vector empty");
102     if (EltTy V = Val.template dyn_cast<EltTy>())
103       return V;
104     return Val.template get<VecTy*>()->front();
105   }
106   
107   void push_back(EltTy NewVal) {
108     assert(NewVal != 0 && "Can't add a null value");
109     
110     // If we have nothing, add something.
111     if (Val.isNull()) {
112       Val = NewVal;
113       return;
114     }
115     
116     // If we have a single value, convert to a vector.
117     if (EltTy V = Val.template dyn_cast<EltTy>()) {
118       Val = new VecTy();
119       Val.template get<VecTy*>()->push_back(V);
120     }
121     
122     // Add the new value, we know we have a vector.
123     Val.template get<VecTy*>()->push_back(NewVal);
124   }
125   
126   void clear() {
127     // If we have a single value, convert to empty.
128     if (Val.template is<EltTy>()) {
129       Val = (EltTy)0;
130     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
131       // If we have a vector form, just clear it.
132       Vec->clear();
133     }
134     // Otherwise, we're already empty.
135   }
136   
137 private:
138   void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
139 };
140 } // end namespace llvm
141
142 #endif