TinyPtrVector.h revision b4c28fc93f5149a0bd7967af44c429412e751c56
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(const TinyPtrVector &RHS) : Val(RHS.Val) {
36    if (VecTy *V = Val.template dyn_cast<VecTy*>())
37      Val = new VecTy(*V);
38  }
39#if LLVM_USE_RVALUE_REFERENCES
40  TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
41    RHS.Val = (EltTy)0;
42  }
43#endif
44  ~TinyPtrVector() {
45    if (VecTy *V = Val.template dyn_cast<VecTy*>())
46      delete V;
47  }
48
49  // implicit conversion operator to ArrayRef.
50  operator ArrayRef<EltTy>() const {
51    if (Val.isNull())
52      return ArrayRef<EltTy>();
53    if (Val.template is<EltTy>())
54      return *Val.getAddrOfPtr1();
55    return *Val.template get<VecTy*>();
56  }
57
58  bool empty() const {
59    // This vector can be empty if it contains no element, or if it
60    // contains a pointer to an empty vector.
61    if (Val.isNull()) return true;
62    if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
63      return Vec->empty();
64    return false;
65  }
66
67  unsigned size() const {
68    if (empty())
69      return 0;
70    if (Val.template is<EltTy>())
71      return 1;
72    return Val.template get<VecTy*>()->size();
73  }
74
75  typedef const EltTy *const_iterator;
76  typedef EltTy *iterator;
77
78  iterator begin() {
79    if (Val.template is<EltTy>())
80      return Val.getAddrOfPtr1();
81
82    return Val.template get<VecTy *>()->begin();
83
84  }
85  iterator end() {
86    if (Val.template is<EltTy>())
87      return begin() + (Val.isNull() ? 0 : 1);
88
89    return Val.template get<VecTy *>()->end();
90  }
91
92  const_iterator begin() const {
93    return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
94  }
95
96  const_iterator end() const {
97    return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
98  }
99
100  EltTy operator[](unsigned i) const {
101    assert(!Val.isNull() && "can't index into an empty vector");
102    if (EltTy V = Val.template dyn_cast<EltTy>()) {
103      assert(i == 0 && "tinyvector index out of range");
104      return V;
105    }
106
107    assert(i < Val.template get<VecTy*>()->size() &&
108           "tinyvector index out of range");
109    return (*Val.template get<VecTy*>())[i];
110  }
111
112  EltTy front() const {
113    assert(!empty() && "vector empty");
114    if (EltTy V = Val.template dyn_cast<EltTy>())
115      return V;
116    return Val.template get<VecTy*>()->front();
117  }
118
119  EltTy back() const {
120    assert(!empty() && "vector empty");
121    if (EltTy V = Val.template dyn_cast<EltTy>())
122      return V;
123    return Val.template get<VecTy*>()->back();
124  }
125
126  void push_back(EltTy NewVal) {
127    assert(NewVal != 0 && "Can't add a null value");
128
129    // If we have nothing, add something.
130    if (Val.isNull()) {
131      Val = NewVal;
132      return;
133    }
134
135    // If we have a single value, convert to a vector.
136    if (EltTy V = Val.template dyn_cast<EltTy>()) {
137      Val = new VecTy();
138      Val.template get<VecTy*>()->push_back(V);
139    }
140
141    // Add the new value, we know we have a vector.
142    Val.template get<VecTy*>()->push_back(NewVal);
143  }
144
145  void pop_back() {
146    // If we have a single value, convert to empty.
147    if (Val.template is<EltTy>())
148      Val = (EltTy)0;
149    else if (VecTy *Vec = Val.template get<VecTy*>())
150      Vec->pop_back();
151  }
152
153  void clear() {
154    // If we have a single value, convert to empty.
155    if (Val.template is<EltTy>()) {
156      Val = (EltTy)0;
157    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
158      // If we have a vector form, just clear it.
159      Vec->clear();
160    }
161    // Otherwise, we're already empty.
162  }
163
164  iterator erase(iterator I) {
165    // If we have a single value, convert to empty.
166    if (Val.template is<EltTy>()) {
167      if (I == begin())
168        Val = (EltTy)0;
169    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
170      // multiple items in a vector; just do the erase, there is no
171      // benefit to collapsing back to a pointer
172      return Vec->erase(I);
173    }
174    return end();
175  }
176
177private:
178  void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
179#if LLVM_USE_RVALUE_REFERENCES
180  void operator=(TinyPtrVector&&); // NOT IMPLEMENTED YET.
181#endif
182};
183} // end namespace llvm
184
185#endif
186