TinyPtrVector.h revision 22e522e08640be459f237796009cf7666d6d75e7
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
16namespace 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///
24template <typename EltTy>
25class TinyPtrVector {
26public:
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  bool empty() const {
41    // This vector can be empty if it contains no element, or if it
42    // contains a pointer to an empty vector.
43    if (Val.isNull()) return true;
44    if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
45      return Vec->empty();
46    return false;
47  }
48
49  unsigned size() const {
50    if (empty())
51      return 0;
52    if (Val.template is<EltTy>())
53      return 1;
54    return Val.template get<VecTy*>()->size();
55  }
56
57  typedef const EltTy *iterator;
58  iterator begin() const {
59    if (empty())
60      return 0;
61
62    if (Val.template is<EltTy>())
63      return Val.template getAddrOf<EltTy>();
64
65    return Val.template get<VecTy *>()->begin();
66
67  }
68  iterator end() const {
69    if (empty())
70      return 0;
71
72    if (Val.template is<EltTy>())
73      return begin() + 1;
74
75    return Val.template get<VecTy *>()->end();
76  }
77
78
79  EltTy operator[](unsigned i) const {
80    assert(!Val.isNull() && "can't index into an empty vector");
81    if (EltTy V = Val.template dyn_cast<EltTy>()) {
82      assert(i == 0 && "tinyvector index out of range");
83      return V;
84    }
85
86    assert(i < Val.template get<VecTy*>()->size() &&
87           "tinyvector index out of range");
88    return (*Val.template get<VecTy*>())[i];
89  }
90
91  EltTy front() const {
92    assert(!empty() && "vector empty");
93    if (EltTy V = Val.template dyn_cast<EltTy>())
94      return V;
95    return Val.template get<VecTy*>()->front();
96  }
97
98  void push_back(EltTy NewVal) {
99    assert(NewVal != 0 && "Can't add a null value");
100
101    // If we have nothing, add something.
102    if (Val.isNull()) {
103      Val = NewVal;
104      return;
105    }
106
107    // If we have a single value, convert to a vector.
108    if (EltTy V = Val.template dyn_cast<EltTy>()) {
109      Val = new VecTy();
110      Val.template get<VecTy*>()->push_back(V);
111    }
112
113    // Add the new value, we know we have a vector.
114    Val.template get<VecTy*>()->push_back(NewVal);
115  }
116
117  void clear() {
118    // If we have a single value, convert to empty.
119    if (Val.template is<EltTy>()) {
120      Val = (EltTy)0;
121    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
122      // If we have a vector form, just clear it.
123      Vec->clear();
124    }
125    // Otherwise, we're already empty.
126  }
127
128private:
129  void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
130};
131} // end namespace llvm
132
133#endif
134