1 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the SmallVector class.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_ADT_SMALLVECTOR_H
15 #define LLVM_ADT_SMALLVECTOR_H
22 /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
23 /// for the case when the array is small. It contains some number of elements
24 /// in-place, which allows it to avoid heap allocation when the actual number of
25 /// elements is below that threshold. This allows normal "small" cases to be
26 /// fast without losing generality for large inputs.
28 /// Note that this does not attempt to be exception safe.
30 template <typename T, unsigned N>
32 // Allocate raw space for N elements of type T. If T has a ctor or dtor, we
33 // don't want it to be automatically run, so we need to represent the space as
34 // something else. An array of char would work great, but might not be
35 // aligned sufficiently. Instead, we either use GCC extensions, or some
36 // number of union instances for the space, which guarantee maximal alignment.
44 /// InlineElts - These are the 'N' elements that are stored inline in the body
46 U InlineElts[(sizeof(T)*N+sizeof(U)-1)/sizeof(U)];
47 T *Begin, *End, *Capacity;
49 // Default ctor - Initialize to empty.
50 SmallVector() : Begin((T*)InlineElts), End(Begin), Capacity(Begin+N) {
53 SmallVector(const SmallVector &RHS) {
54 unsigned RHSSize = RHS.size();
55 Begin = (T*)InlineElts;
57 // Doesn't fit in the small case? Allocate space.
59 End = Capacity = Begin;
64 std::uninitialized_copy(RHS.begin(), RHS.end(), Begin);
67 // If this wasn't grown from the inline copy, deallocate the old space.
68 if ((void*)Begin != (void*)InlineElts)
69 delete[] (char*)Begin;
72 typedef size_t size_type;
74 typedef const T* const_iterator;
76 typedef const T& const_reference;
78 bool empty() const { return Begin == End; }
79 size_type size() const { return End-Begin; }
81 iterator begin() { return Begin; }
82 const_iterator begin() const { return Begin; }
84 iterator end() { return End; }
85 const_iterator end() const { return End; }
87 reference operator[](unsigned idx) {
88 assert(idx < size() && "out of range reference!");
91 const_reference operator[](unsigned idx) const {
92 assert(idx < size() && "out of range reference!");
97 assert(!empty() && "SmallVector is empty!");
100 const_reference back() const {
101 assert(!empty() && "SmallVector is empty!");
105 void push_back(const_reference Elt) {
106 if (End < Capacity) {
116 const SmallVector &operator=(const SmallVector &RHS) {
117 // Avoid self-assignment.
118 if (this == &RHS) return *this;
120 // If we already have sufficient space, assign the common elements, then
121 // destroy any excess.
122 unsigned RHSSize = RHS.size();
123 unsigned CurSize = size();
124 if (CurSize >= RHSSize) {
125 // Assign common elements.
126 for (unsigned i = 0; i != RHSSize; ++i)
127 Begin[i] = RHS.Begin[i];
129 // Destroy excess elements.
130 for (unsigned i = RHSSize; i != CurSize; ++i)
134 End = Begin + RHSSize;
138 // If we have to grow to have enough elements, destroy the current elements.
139 // This allows us to avoid copying them during the grow.
140 if (Capacity-Begin < RHSSize) {
141 // Destroy current elements.
142 for (T *I = Begin, E = End; I != E; ++I)
148 // Otherwise, use assignment for the already-constructed elements.
149 for (unsigned i = 0; i != CurSize; ++i)
150 Begin[i] = RHS.Begin[i];
153 // Copy construct the new elements in place.
154 std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
161 /// isSmall - Return true if this is a smallvector which has not had dynamic
162 /// memory allocated for it.
163 bool isSmall() const {
164 return (void*)Begin == (void*)InlineElts;
167 /// grow - double the size of the allocated memory, guaranteeing space for at
168 /// least one more element or MinSize if specified.
169 void grow(unsigned MinSize = 0) {
170 unsigned CurCapacity = Capacity-Begin;
171 unsigned CurSize = size();
172 unsigned NewCapacity = 2*CurCapacity;
173 if (NewCapacity < MinSize)
174 NewCapacity = MinSize;
175 T *NewElts = reinterpret_cast<T*>(new char[NewCapacity*sizeof(T)]);
177 // Copy the elements over.
178 std::uninitialized_copy(Begin, End, NewElts);
180 // Destroy the original elements.
181 for (T *I = Begin, *E = End; I != E; ++I)
184 // If this wasn't grown from the inline copy, deallocate the old space.
186 delete[] (char*)Begin;
189 End = NewElts+CurSize;
190 Capacity = Begin+NewCapacity*2;
194 } // End llvm namespace