]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/include/llvm/ADT/TinyPtrVector.h
MFC r234353:
[FreeBSD/stable/9.git] / contrib / llvm / 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.getAddrOfPtr1();
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 *const_iterator;
67   typedef EltTy *iterator;
68
69   iterator begin() {
70     if (empty())
71       return 0;
72     
73     if (Val.template is<EltTy>())
74       return Val.getAddrOfPtr1();
75     
76     return Val.template get<VecTy *>()->begin();
77
78   }
79   iterator end() {
80     if (empty())
81       return 0;
82     
83     if (Val.template is<EltTy>())
84       return begin() + 1;
85     
86     return Val.template get<VecTy *>()->end();
87   }
88
89   const_iterator begin() const {
90     return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
91   }
92
93   const_iterator end() const {
94     return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
95   }
96
97   EltTy operator[](unsigned i) const {
98     assert(!Val.isNull() && "can't index into an empty vector");
99     if (EltTy V = Val.template dyn_cast<EltTy>()) {
100       assert(i == 0 && "tinyvector index out of range");
101       return V;
102     }
103     
104     assert(i < Val.template get<VecTy*>()->size() && 
105            "tinyvector index out of range");
106     return (*Val.template get<VecTy*>())[i];
107   }
108   
109   EltTy front() const {
110     assert(!empty() && "vector empty");
111     if (EltTy V = Val.template dyn_cast<EltTy>())
112       return V;
113     return Val.template get<VecTy*>()->front();
114   }
115   
116   void push_back(EltTy NewVal) {
117     assert(NewVal != 0 && "Can't add a null value");
118     
119     // If we have nothing, add something.
120     if (Val.isNull()) {
121       Val = NewVal;
122       return;
123     }
124     
125     // If we have a single value, convert to a vector.
126     if (EltTy V = Val.template dyn_cast<EltTy>()) {
127       Val = new VecTy();
128       Val.template get<VecTy*>()->push_back(V);
129     }
130     
131     // Add the new value, we know we have a vector.
132     Val.template get<VecTy*>()->push_back(NewVal);
133   }
134   
135   void clear() {
136     // If we have a single value, convert to empty.
137     if (Val.template is<EltTy>()) {
138       Val = (EltTy)0;
139     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
140       // If we have a vector form, just clear it.
141       Vec->clear();
142     }
143     // Otherwise, we're already empty.
144   }
145
146   iterator erase(iterator I) {
147     // If we have a single value, convert to empty.
148     if (Val.template is<EltTy>()) {
149       if (I == begin())
150         Val = (EltTy)0;
151     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
152       // multiple items in a vector; just do the erase, there is no
153       // benefit to collapsing back to a pointer
154       return Vec->erase(I);
155     }
156
157     return 0;
158   }
159   
160 private:
161   void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
162 };
163 } // end namespace llvm
164
165 #endif