summaryrefslogtreecommitdiff
path: root/include/llvm/ADT/TinyPtrVector.h
blob: 374357d9c6b7d2099ced4d2eca64ee0454012877 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ADT_TINYPTRVECTOR_H
#define LLVM_ADT_TINYPTRVECTOR_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/PointerUnion.h"

namespace llvm {
  
/// TinyPtrVector - This class is specialized for cases where there are
/// normally 0 or 1 element in a vector, but is general enough to go beyond that
/// when required.
///
/// NOTE: This container doesn't allow you to store a null pointer into it.
///
template <typename EltTy>
class TinyPtrVector {
public:
  typedef llvm::SmallVector<EltTy, 4> VecTy;
  llvm::PointerUnion<EltTy, VecTy*> Val;
  
  TinyPtrVector() {}
  TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
    if (VecTy *V = Val.template dyn_cast<VecTy*>())
      Val = new VecTy(*V);
  }
  ~TinyPtrVector() {
    if (VecTy *V = Val.template dyn_cast<VecTy*>())
      delete V;
  }
  
  // implicit conversion operator to ArrayRef.
  operator ArrayRef<EltTy>() const {
    if (Val.isNull())
      return ArrayRef<EltTy>();
    if (Val.template is<EltTy>())
      return *Val.template getAddrOf<EltTy>();
    return *Val.template get<VecTy*>();
  }
  
  bool empty() const {
    // This vector can be empty if it contains no element, or if it
    // contains a pointer to an empty vector.
    if (Val.isNull()) return true;
    if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
      return Vec->empty();
    return false;
  }
  
  unsigned size() const {
    if (empty())
      return 0;
    if (Val.template is<EltTy>())
      return 1;
    return Val.template get<VecTy*>()->size();
  }
  
  typedef const EltTy *iterator;
  iterator begin() const {
    if (empty())
      return 0;
    
    if (Val.template is<EltTy>())
      return Val.getAddrOfPtr1();
    
    return Val.template get<VecTy *>()->begin();

  }
  iterator end() const {
    if (empty())
      return 0;
    
    if (Val.template is<EltTy>())
      return begin() + 1;
    
    return Val.template get<VecTy *>()->end();
  }

  
  EltTy operator[](unsigned i) const {
    assert(!Val.isNull() && "can't index into an empty vector");
    if (EltTy V = Val.template dyn_cast<EltTy>()) {
      assert(i == 0 && "tinyvector index out of range");
      return V;
    }
    
    assert(i < Val.template get<VecTy*>()->size() && 
           "tinyvector index out of range");
    return (*Val.template get<VecTy*>())[i];
  }
  
  EltTy front() const {
    assert(!empty() && "vector empty");
    if (EltTy V = Val.template dyn_cast<EltTy>())
      return V;
    return Val.template get<VecTy*>()->front();
  }
  
  void push_back(EltTy NewVal) {
    assert(NewVal != 0 && "Can't add a null value");
    
    // If we have nothing, add something.
    if (Val.isNull()) {
      Val = NewVal;
      return;
    }
    
    // If we have a single value, convert to a vector.
    if (EltTy V = Val.template dyn_cast<EltTy>()) {
      Val = new VecTy();
      Val.template get<VecTy*>()->push_back(V);
    }
    
    // Add the new value, we know we have a vector.
    Val.template get<VecTy*>()->push_back(NewVal);
  }
  
  void clear() {
    // If we have a single value, convert to empty.
    if (Val.template is<EltTy>()) {
      Val = (EltTy)0;
    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
      // If we have a vector form, just clear it.
      Vec->clear();
    }
    // Otherwise, we're already empty.
  }
  
private:
  void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
};
} // end namespace llvm

#endif