TinyPtrVector.h revision 0b1bcbf6b87f19402d8aef1ef9f6e527a07de9d4
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/ArrayRef.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/PointerUnion.h"
16#include "llvm/Support/Compiler.h"
17
18namespace llvm {
19
20/// TinyPtrVector - This class is specialized for cases where there are
21/// normally 0 or 1 element in a vector, but is general enough to go beyond that
22/// when required.
23///
24/// NOTE: This container doesn't allow you to store a null pointer into it.
25///
26template <typename EltTy>
27class TinyPtrVector {
28public:
29  typedef llvm::SmallVector<EltTy, 4> VecTy;
30  typedef typename VecTy::value_type value_type;
31
32  llvm::PointerUnion<EltTy, VecTy*> Val;
33
34  TinyPtrVector() {}
35  ~TinyPtrVector() {
36    if (VecTy *V = Val.template dyn_cast<VecTy*>())
37      delete V;
38  }
39
40  TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
41    if (VecTy *V = Val.template dyn_cast<VecTy*>())
42      Val = new VecTy(*V);
43  }
44  TinyPtrVector &operator=(const TinyPtrVector &RHS) {
45    if (this == &RHS)
46      return *this;
47    if (RHS.empty()) {
48      this->clear();
49      return *this;
50    }
51
52    // Try to squeeze into the single slot. If it won't fit, allocate a copied
53    // vector.
54    if (Val.template is<EltTy>()) {
55      if (RHS.size() == 1)
56        Val = RHS.front();
57      else
58        Val = new VecTy(*RHS.Val.template get<VecTy*>());
59      return *this;
60    }
61
62    // If we have a full vector allocated, try to re-use it.
63    if (RHS.Val.template is<EltTy>()) {
64      Val.template get<VecTy*>()->clear();
65      Val.template get<VecTy*>()->push_back(RHS.front());
66    } else {
67      *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>();
68    }
69    return *this;
70  }
71
72#if LLVM_USE_RVALUE_REFERENCES
73  TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
74    RHS.Val = (EltTy)0;
75  }
76  TinyPtrVector &operator=(TinyPtrVector &&RHS) {
77    if (this == &RHS)
78      return *this;
79    if (RHS.empty()) {
80      this->clear();
81      return *this;
82    }
83
84    // If this vector has been allocated on the heap, re-use it if cheap. If it
85    // would require more copying, just delete it and we'll steal the other
86    // side.
87    if (VecTy *V = Val.template dyn_cast<VecTy*>()) {
88      if (RHS.Val.template is<EltTy>()) {
89        V->clear();
90        V->push_back(RHS.front());
91        return *this;
92      }
93      delete V;
94    }
95
96    Val = RHS.Val;
97    RHS.Val = (EltTy)0;
98    return *this;
99  }
100#endif
101
102  // implicit conversion operator to ArrayRef.
103  operator ArrayRef<EltTy>() const {
104    if (Val.isNull())
105      return ArrayRef<EltTy>();
106    if (Val.template is<EltTy>())
107      return *Val.getAddrOfPtr1();
108    return *Val.template get<VecTy*>();
109  }
110
111  bool empty() const {
112    // This vector can be empty if it contains no element, or if it
113    // contains a pointer to an empty vector.
114    if (Val.isNull()) return true;
115    if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
116      return Vec->empty();
117    return false;
118  }
119
120  unsigned size() const {
121    if (empty())
122      return 0;
123    if (Val.template is<EltTy>())
124      return 1;
125    return Val.template get<VecTy*>()->size();
126  }
127
128  typedef const EltTy *const_iterator;
129  typedef EltTy *iterator;
130
131  iterator begin() {
132    if (Val.template is<EltTy>())
133      return Val.getAddrOfPtr1();
134
135    return Val.template get<VecTy *>()->begin();
136
137  }
138  iterator end() {
139    if (Val.template is<EltTy>())
140      return begin() + (Val.isNull() ? 0 : 1);
141
142    return Val.template get<VecTy *>()->end();
143  }
144
145  const_iterator begin() const {
146    return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
147  }
148
149  const_iterator end() const {
150    return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
151  }
152
153  EltTy operator[](unsigned i) const {
154    assert(!Val.isNull() && "can't index into an empty vector");
155    if (EltTy V = Val.template dyn_cast<EltTy>()) {
156      assert(i == 0 && "tinyvector index out of range");
157      return V;
158    }
159
160    assert(i < Val.template get<VecTy*>()->size() &&
161           "tinyvector index out of range");
162    return (*Val.template get<VecTy*>())[i];
163  }
164
165  EltTy front() const {
166    assert(!empty() && "vector empty");
167    if (EltTy V = Val.template dyn_cast<EltTy>())
168      return V;
169    return Val.template get<VecTy*>()->front();
170  }
171
172  EltTy back() const {
173    assert(!empty() && "vector empty");
174    if (EltTy V = Val.template dyn_cast<EltTy>())
175      return V;
176    return Val.template get<VecTy*>()->back();
177  }
178
179  void push_back(EltTy NewVal) {
180    assert(NewVal != 0 && "Can't add a null value");
181
182    // If we have nothing, add something.
183    if (Val.isNull()) {
184      Val = NewVal;
185      return;
186    }
187
188    // If we have a single value, convert to a vector.
189    if (EltTy V = Val.template dyn_cast<EltTy>()) {
190      Val = new VecTy();
191      Val.template get<VecTy*>()->push_back(V);
192    }
193
194    // Add the new value, we know we have a vector.
195    Val.template get<VecTy*>()->push_back(NewVal);
196  }
197
198  void pop_back() {
199    // If we have a single value, convert to empty.
200    if (Val.template is<EltTy>())
201      Val = (EltTy)0;
202    else if (VecTy *Vec = Val.template get<VecTy*>())
203      Vec->pop_back();
204  }
205
206  void clear() {
207    // If we have a single value, convert to empty.
208    if (Val.template is<EltTy>()) {
209      Val = (EltTy)0;
210    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
211      // If we have a vector form, just clear it.
212      Vec->clear();
213    }
214    // Otherwise, we're already empty.
215  }
216
217  iterator erase(iterator I) {
218    assert(I >= begin() && "Iterator to erase is out of bounds.");
219    assert(I < end() && "Erasing at past-the-end iterator.");
220
221    // If we have a single value, convert to empty.
222    if (Val.template is<EltTy>()) {
223      if (I == begin())
224        Val = (EltTy)0;
225    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
226      // multiple items in a vector; just do the erase, there is no
227      // benefit to collapsing back to a pointer
228      return Vec->erase(I);
229    }
230    return end();
231  }
232};
233} // end namespace llvm
234
235#endif
236