1 | //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// |
---|
2 | // |
---|
3 | // The LLVM Compiler Infrastructure |
---|
4 | // |
---|
5 | // This file is distributed under the University of Illinois Open Source |
---|
6 | // License. |
---|
7 | // ============================================================================== |
---|
8 | // LLVM Release License |
---|
9 | // ============================================================================== |
---|
10 | // University of Illinois/NCSA |
---|
11 | // Open Source License |
---|
12 | // |
---|
13 | // Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign. |
---|
14 | // All rights reserved. |
---|
15 | // |
---|
16 | // Developed by: |
---|
17 | // |
---|
18 | // LLVM Team |
---|
19 | // |
---|
20 | // University of Illinois at Urbana-Champaign |
---|
21 | // |
---|
22 | // http://llvm.org |
---|
23 | // |
---|
24 | // Permission is hereby granted, free of charge, to any person obtaining a copy of |
---|
25 | // this software and associated documentation files (the "Software"), to deal with |
---|
26 | // the Software without restriction, including without limitation the rights to |
---|
27 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
---|
28 | // of the Software, and to permit persons to whom the Software is furnished to do |
---|
29 | // so, subject to the following conditions: |
---|
30 | // |
---|
31 | // * Redistributions of source code must retain the above copyright notice, |
---|
32 | // this list of conditions and the following disclaimers. |
---|
33 | // |
---|
34 | // * Redistributions in binary form must reproduce the above copyright notice, |
---|
35 | // this list of conditions and the following disclaimers in the |
---|
36 | // documentation and/or other materials provided with the distribution. |
---|
37 | // |
---|
38 | // * Neither the names of the LLVM Team, University of Illinois at |
---|
39 | // Urbana-Champaign, nor the names of its contributors may be used to |
---|
40 | // endorse or promote products derived from this Software without specific |
---|
41 | // prior written permission. |
---|
42 | // |
---|
43 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
44 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
---|
45 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
46 | // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
47 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
48 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE |
---|
49 | // SOFTWARE. |
---|
50 | // |
---|
51 | //===----------------------------------------------------------------------===// |
---|
52 | // |
---|
53 | // This file defines the SmallVector class. |
---|
54 | // |
---|
55 | //===----------------------------------------------------------------------===// |
---|
56 | |
---|
57 | #ifndef __SmallVector_H |
---|
58 | #define __SmallVector_H |
---|
59 | |
---|
60 | #include <algorithm> |
---|
61 | #include <cassert> |
---|
62 | #include <cstddef> |
---|
63 | #include <cstdlib> |
---|
64 | #include <cstring> |
---|
65 | #include <iterator> |
---|
66 | #include <memory> |
---|
67 | |
---|
68 | #ifdef _MSC_VER |
---|
69 | namespace std { |
---|
70 | #if _MSC_VER <= 1310 |
---|
71 | // Work around flawed VC++ implementation of std::uninitialized_copy. Define |
---|
72 | // additional overloads so that elements with pointer types are recognized as |
---|
73 | // scalars and not objects, causing bizarre type conversion errors. |
---|
74 | template<class T1, class T2> |
---|
75 | inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { |
---|
76 | _Scalar_ptr_iterator_tag _Cat; |
---|
77 | return _Cat; |
---|
78 | } |
---|
79 | |
---|
80 | template<class T1, class T2> |
---|
81 | inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { |
---|
82 | _Scalar_ptr_iterator_tag _Cat; |
---|
83 | return _Cat; |
---|
84 | } |
---|
85 | #else |
---|
86 | // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear |
---|
87 | // is that the above hack won't work if it wasn't fixed. |
---|
88 | #endif |
---|
89 | } |
---|
90 | #endif |
---|
91 | |
---|
92 | namespace Ogre { |
---|
93 | |
---|
94 | // some type traits |
---|
95 | template <typename T> struct isPodLike { static const bool value = false; }; |
---|
96 | |
---|
97 | template <> struct isPodLike<bool> { static const bool value = true; }; |
---|
98 | template <> struct isPodLike<char> { static const bool value = true; }; |
---|
99 | template <> struct isPodLike<signed char> { static const bool value = true; }; |
---|
100 | template <> struct isPodLike<unsigned char> { static const bool value = true; }; |
---|
101 | template <> struct isPodLike<int> { static const bool value = true; }; |
---|
102 | template <> struct isPodLike<unsigned> { static const bool value = true; }; |
---|
103 | template <> struct isPodLike<short> { static const bool value = true; }; |
---|
104 | template <> struct isPodLike<unsigned short> { static const bool value = true; }; |
---|
105 | template <> struct isPodLike<long> { static const bool value = true; }; |
---|
106 | template <> struct isPodLike<unsigned long> { static const bool value = true; }; |
---|
107 | template <> struct isPodLike<float> { static const bool value = true; }; |
---|
108 | template <> struct isPodLike<double> { static const bool value = true; }; |
---|
109 | template <typename T> struct isPodLike<T*> { static const bool value = true; }; |
---|
110 | |
---|
111 | template<typename T, typename U> |
---|
112 | struct isPodLike<std::pair<T, U> > { static const bool value = isPodLike<T>::value & isPodLike<U>::value; }; |
---|
113 | |
---|
114 | /// SmallVectorBase - This is all the non-templated stuff common to all |
---|
115 | /// SmallVectors. |
---|
116 | class SmallVectorBase { |
---|
117 | protected: |
---|
118 | void *BeginX, *EndX, *CapacityX; |
---|
119 | |
---|
120 | // Allocate raw space for N elements of type T. If T has a ctor or dtor, we |
---|
121 | // don't want it to be automatically run, so we need to represent the space as |
---|
122 | // something else. An array of char would work great, but might not be |
---|
123 | // aligned sufficiently. Instead we use some number of union instances for |
---|
124 | // the space, which guarantee maximal alignment. |
---|
125 | union U { |
---|
126 | double D; |
---|
127 | long double LD; |
---|
128 | long long L; |
---|
129 | void *P; |
---|
130 | } FirstEl; |
---|
131 | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. |
---|
132 | |
---|
133 | protected: |
---|
134 | SmallVectorBase(size_t Size) |
---|
135 | : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {} |
---|
136 | |
---|
137 | /// isSmall - Return true if this is a smallvector which has not had dynamic |
---|
138 | /// memory allocated for it. |
---|
139 | bool isSmall() const { |
---|
140 | return BeginX == static_cast<const void*>(&FirstEl); |
---|
141 | } |
---|
142 | |
---|
143 | /// size_in_bytes - This returns size()*sizeof(T). |
---|
144 | size_t size_in_bytes() const { |
---|
145 | return size_t((char*)EndX - (char*)BeginX); |
---|
146 | } |
---|
147 | |
---|
148 | /// capacity_in_bytes - This returns capacity()*sizeof(T). |
---|
149 | size_t capacity_in_bytes() const { |
---|
150 | return size_t((char*)CapacityX - (char*)BeginX); |
---|
151 | } |
---|
152 | |
---|
153 | /// grow_pod - This is an implementation of the grow() method which only works |
---|
154 | /// on POD-like data types and is out of line to reduce code duplication. |
---|
155 | void grow_pod(size_t MinSizeInBytes, size_t TSize); |
---|
156 | |
---|
157 | public: |
---|
158 | bool empty() const { return BeginX == EndX; } |
---|
159 | }; |
---|
160 | |
---|
161 | |
---|
162 | template <typename T> |
---|
163 | class SmallVectorTemplateCommon : public SmallVectorBase { |
---|
164 | protected: |
---|
165 | void setEnd(T *P) { this->EndX = P; } |
---|
166 | public: |
---|
167 | SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} |
---|
168 | |
---|
169 | typedef size_t size_type; |
---|
170 | typedef ptrdiff_t difference_type; |
---|
171 | typedef T value_type; |
---|
172 | typedef T *iterator; |
---|
173 | typedef const T *const_iterator; |
---|
174 | |
---|
175 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
---|
176 | typedef std::reverse_iterator<iterator> reverse_iterator; |
---|
177 | |
---|
178 | typedef T &reference; |
---|
179 | typedef const T &const_reference; |
---|
180 | typedef T *pointer; |
---|
181 | typedef const T *const_pointer; |
---|
182 | |
---|
183 | // forward iterator creation methods. |
---|
184 | iterator begin() { return (iterator)this->BeginX; } |
---|
185 | const_iterator begin() const { return (const_iterator)this->BeginX; } |
---|
186 | iterator end() { return (iterator)this->EndX; } |
---|
187 | const_iterator end() const { return (const_iterator)this->EndX; } |
---|
188 | protected: |
---|
189 | iterator capacity_ptr() { return (iterator)this->CapacityX; } |
---|
190 | const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} |
---|
191 | public: |
---|
192 | |
---|
193 | // reverse iterator creation methods. |
---|
194 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
---|
195 | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } |
---|
196 | reverse_iterator rend() { return reverse_iterator(begin()); } |
---|
197 | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} |
---|
198 | |
---|
199 | size_type size() const { return end()-begin(); } |
---|
200 | size_type max_size() const { return size_type(-1) / sizeof(T); } |
---|
201 | |
---|
202 | /// capacity - Return the total number of elements in the currently allocated |
---|
203 | /// buffer. |
---|
204 | size_t capacity() const { return capacity_ptr() - begin(); } |
---|
205 | |
---|
206 | /// data - Return a pointer to the vector's buffer, even if empty(). |
---|
207 | pointer data() { return pointer(begin()); } |
---|
208 | /// data - Return a pointer to the vector's buffer, even if empty(). |
---|
209 | const_pointer data() const { return const_pointer(begin()); } |
---|
210 | |
---|
211 | reference operator[](unsigned idx) { |
---|
212 | assert(begin() + idx < end()); |
---|
213 | return begin()[idx]; |
---|
214 | } |
---|
215 | const_reference operator[](unsigned idx) const { |
---|
216 | assert(begin() + idx < end()); |
---|
217 | return begin()[idx]; |
---|
218 | } |
---|
219 | |
---|
220 | reference front() { |
---|
221 | return begin()[0]; |
---|
222 | } |
---|
223 | const_reference front() const { |
---|
224 | return begin()[0]; |
---|
225 | } |
---|
226 | |
---|
227 | reference back() { |
---|
228 | return end()[-1]; |
---|
229 | } |
---|
230 | const_reference back() const { |
---|
231 | return end()[-1]; |
---|
232 | } |
---|
233 | }; |
---|
234 | |
---|
235 | /// SmallVectorTemplateBase<isPodLike = false> - This is where we put method |
---|
236 | /// implementations that are designed to work with non-POD-like T's. |
---|
237 | template <typename T, bool isPodLike> |
---|
238 | class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { |
---|
239 | public: |
---|
240 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
---|
241 | |
---|
242 | static void destroy_range(T *S, T *E) { |
---|
243 | while (S != E) { |
---|
244 | --E; |
---|
245 | E->~T(); |
---|
246 | } |
---|
247 | } |
---|
248 | |
---|
249 | /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory |
---|
250 | /// starting with "Dest", constructing elements into it as needed. |
---|
251 | template<typename It1, typename It2> |
---|
252 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
---|
253 | std::uninitialized_copy(I, E, Dest); |
---|
254 | } |
---|
255 | |
---|
256 | /// grow - double the size of the allocated memory, guaranteeing space for at |
---|
257 | /// least one more element or MinSize if specified. |
---|
258 | void grow(size_t MinSize = 0); |
---|
259 | }; |
---|
260 | |
---|
261 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
---|
262 | template <typename T, bool isPodLike> |
---|
263 | void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { |
---|
264 | size_t CurCapacity = this->capacity(); |
---|
265 | size_t CurSize = this->size(); |
---|
266 | size_t NewCapacity = 2*CurCapacity + 1; // Always grow, even from zero. |
---|
267 | if (NewCapacity < MinSize) |
---|
268 | NewCapacity = MinSize; |
---|
269 | T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); |
---|
270 | |
---|
271 | // Copy the elements over. |
---|
272 | this->uninitialized_copy(this->begin(), this->end(), NewElts); |
---|
273 | |
---|
274 | // Destroy the original elements. |
---|
275 | destroy_range(this->begin(), this->end()); |
---|
276 | |
---|
277 | // If this wasn't grown from the inline copy, deallocate the old space. |
---|
278 | if (!this->isSmall()) |
---|
279 | free(this->begin()); |
---|
280 | |
---|
281 | this->setEnd(NewElts+CurSize); |
---|
282 | this->BeginX = NewElts; |
---|
283 | this->CapacityX = this->begin()+NewCapacity; |
---|
284 | } |
---|
285 | |
---|
286 | |
---|
287 | /// SmallVectorTemplateBase<isPodLike = true> - This is where we put method |
---|
288 | /// implementations that are designed to work with POD-like T's. |
---|
289 | template <typename T> |
---|
290 | class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { |
---|
291 | public: |
---|
292 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
---|
293 | |
---|
294 | // No need to do a destroy loop for POD's. |
---|
295 | static void destroy_range(T *, T *) {} |
---|
296 | |
---|
297 | /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory |
---|
298 | /// starting with "Dest", constructing elements into it as needed. |
---|
299 | template<typename It1, typename It2> |
---|
300 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
---|
301 | // Arbitrary iterator types; just use the basic implementation. |
---|
302 | std::uninitialized_copy(I, E, Dest); |
---|
303 | } |
---|
304 | |
---|
305 | /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory |
---|
306 | /// starting with "Dest", constructing elements into it as needed. |
---|
307 | template<typename T1, typename T2> |
---|
308 | static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { |
---|
309 | // Use memcpy for PODs iterated by pointers (which includes SmallVector |
---|
310 | // iterators): std::uninitialized_copy optimizes to memmove, but we can |
---|
311 | // use memcpy here. |
---|
312 | memcpy(Dest, I, (E-I)*sizeof(T)); |
---|
313 | } |
---|
314 | |
---|
315 | /// grow - double the size of the allocated memory, guaranteeing space for at |
---|
316 | /// least one more element or MinSize if specified. |
---|
317 | void grow(size_t MinSize = 0) { |
---|
318 | this->grow_pod(MinSize*sizeof(T), sizeof(T)); |
---|
319 | } |
---|
320 | }; |
---|
321 | |
---|
322 | |
---|
323 | /// SmallVectorImpl - This class consists of common code factored out of the |
---|
324 | /// SmallVector class to reduce code duplication based on the SmallVector 'N' |
---|
325 | /// template parameter. |
---|
326 | template <typename T> |
---|
327 | class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { |
---|
328 | typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; |
---|
329 | |
---|
330 | SmallVectorImpl(const SmallVectorImpl&); // DISABLED. |
---|
331 | public: |
---|
332 | typedef typename SuperClass::iterator iterator; |
---|
333 | typedef typename SuperClass::size_type size_type; |
---|
334 | |
---|
335 | // Default ctor - Initialize to empty. |
---|
336 | explicit SmallVectorImpl(unsigned N) |
---|
337 | : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) { |
---|
338 | } |
---|
339 | |
---|
340 | ~SmallVectorImpl() { |
---|
341 | // Destroy the constructed elements in the vector. |
---|
342 | this->destroy_range(this->begin(), this->end()); |
---|
343 | |
---|
344 | // If this wasn't grown from the inline copy, deallocate the old space. |
---|
345 | if (!this->isSmall()) |
---|
346 | free(this->begin()); |
---|
347 | } |
---|
348 | |
---|
349 | |
---|
350 | void clear() { |
---|
351 | this->destroy_range(this->begin(), this->end()); |
---|
352 | this->EndX = this->BeginX; |
---|
353 | } |
---|
354 | |
---|
355 | void resize(unsigned N) { |
---|
356 | if (N < this->size()) { |
---|
357 | this->destroy_range(this->begin()+N, this->end()); |
---|
358 | this->setEnd(this->begin()+N); |
---|
359 | } else if (N > this->size()) { |
---|
360 | if (this->capacity() < N) |
---|
361 | this->grow(N); |
---|
362 | this->construct_range(this->end(), this->begin()+N, T()); |
---|
363 | this->setEnd(this->begin()+N); |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | void resize(unsigned N, const T &NV) { |
---|
368 | if (N < this->size()) { |
---|
369 | this->destroy_range(this->begin()+N, this->end()); |
---|
370 | this->setEnd(this->begin()+N); |
---|
371 | } else if (N > this->size()) { |
---|
372 | if (this->capacity() < N) |
---|
373 | this->grow(N); |
---|
374 | construct_range(this->end(), this->begin()+N, NV); |
---|
375 | this->setEnd(this->begin()+N); |
---|
376 | } |
---|
377 | } |
---|
378 | |
---|
379 | void reserve(unsigned N) { |
---|
380 | if (this->capacity() < N) |
---|
381 | this->grow(N); |
---|
382 | } |
---|
383 | |
---|
384 | void push_back(const T &Elt) { |
---|
385 | if (this->EndX < this->CapacityX) { |
---|
386 | Retry: |
---|
387 | new (this->end()) T(Elt); |
---|
388 | this->setEnd(this->end()+1); |
---|
389 | return; |
---|
390 | } |
---|
391 | this->grow(); |
---|
392 | goto Retry; |
---|
393 | } |
---|
394 | |
---|
395 | void pop_back() { |
---|
396 | this->setEnd(this->end()-1); |
---|
397 | this->end()->~T(); |
---|
398 | } |
---|
399 | |
---|
400 | T pop_back_val() { |
---|
401 | T Result = this->back(); |
---|
402 | pop_back(); |
---|
403 | return Result; |
---|
404 | } |
---|
405 | |
---|
406 | void swap(SmallVectorImpl &RHS); |
---|
407 | |
---|
408 | /// append - Add the specified range to the end of the SmallVector. |
---|
409 | /// |
---|
410 | template<typename in_iter> |
---|
411 | void append(in_iter in_start, in_iter in_end) { |
---|
412 | size_type NumInputs = std::distance(in_start, in_end); |
---|
413 | // Grow allocated space if needed. |
---|
414 | if (NumInputs > size_type(this->capacity_ptr()-this->end())) |
---|
415 | this->grow(this->size()+NumInputs); |
---|
416 | |
---|
417 | // Copy the new elements over. |
---|
418 | // TODO: NEED To compile time dispatch on whether in_iter is a random access |
---|
419 | // iterator to use the fast uninitialized_copy. |
---|
420 | std::uninitialized_copy(in_start, in_end, this->end()); |
---|
421 | this->setEnd(this->end() + NumInputs); |
---|
422 | } |
---|
423 | |
---|
424 | /// append - Add the specified range to the end of the SmallVector. |
---|
425 | /// |
---|
426 | void append(size_type NumInputs, const T &Elt) { |
---|
427 | // Grow allocated space if needed. |
---|
428 | if (NumInputs > size_type(this->capacity_ptr()-this->end())) |
---|
429 | this->grow(this->size()+NumInputs); |
---|
430 | |
---|
431 | // Copy the new elements over. |
---|
432 | std::uninitialized_fill_n(this->end(), NumInputs, Elt); |
---|
433 | this->setEnd(this->end() + NumInputs); |
---|
434 | } |
---|
435 | |
---|
436 | void assign(unsigned NumElts, const T &Elt) { |
---|
437 | clear(); |
---|
438 | if (this->capacity() < NumElts) |
---|
439 | this->grow(NumElts); |
---|
440 | this->setEnd(this->begin()+NumElts); |
---|
441 | construct_range(this->begin(), this->end(), Elt); |
---|
442 | } |
---|
443 | |
---|
444 | iterator erase(iterator I) { |
---|
445 | iterator N = I; |
---|
446 | // Shift all elts down one. |
---|
447 | std::copy(I+1, this->end(), I); |
---|
448 | // Drop the last elt. |
---|
449 | pop_back(); |
---|
450 | return(N); |
---|
451 | } |
---|
452 | |
---|
453 | iterator erase(iterator S, iterator E) { |
---|
454 | iterator N = S; |
---|
455 | // Shift all elts down. |
---|
456 | iterator I = std::copy(E, this->end(), S); |
---|
457 | // Drop the last elts. |
---|
458 | this->destroy_range(I, this->end()); |
---|
459 | this->setEnd(I); |
---|
460 | return(N); |
---|
461 | } |
---|
462 | |
---|
463 | iterator insert(iterator I, const T &Elt) { |
---|
464 | if (I == this->end()) { // Important special case for empty vector. |
---|
465 | push_back(Elt); |
---|
466 | return this->end()-1; |
---|
467 | } |
---|
468 | |
---|
469 | if (this->EndX < this->CapacityX) { |
---|
470 | Retry: |
---|
471 | new (this->end()) T(this->back()); |
---|
472 | this->setEnd(this->end()+1); |
---|
473 | // Push everything else over. |
---|
474 | std::copy_backward(I, this->end()-1, this->end()); |
---|
475 | *I = Elt; |
---|
476 | return I; |
---|
477 | } |
---|
478 | size_t EltNo = I-this->begin(); |
---|
479 | this->grow(); |
---|
480 | I = this->begin()+EltNo; |
---|
481 | goto Retry; |
---|
482 | } |
---|
483 | |
---|
484 | iterator insert(iterator I, size_type NumToInsert, const T &Elt) { |
---|
485 | if (I == this->end()) { // Important special case for empty vector. |
---|
486 | append(NumToInsert, Elt); |
---|
487 | return this->end()-1; |
---|
488 | } |
---|
489 | |
---|
490 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
---|
491 | size_t InsertElt = I - this->begin(); |
---|
492 | |
---|
493 | // Ensure there is enough space. |
---|
494 | reserve(static_cast<unsigned>(this->size() + NumToInsert)); |
---|
495 | |
---|
496 | // Uninvalidate the iterator. |
---|
497 | I = this->begin()+InsertElt; |
---|
498 | |
---|
499 | // If there are more elements between the insertion point and the end of the |
---|
500 | // range than there are being inserted, we can use a simple approach to |
---|
501 | // insertion. Since we already reserved space, we know that this won't |
---|
502 | // reallocate the vector. |
---|
503 | if (size_t(this->end()-I) >= NumToInsert) { |
---|
504 | T *OldEnd = this->end(); |
---|
505 | append(this->end()-NumToInsert, this->end()); |
---|
506 | |
---|
507 | // Copy the existing elements that get replaced. |
---|
508 | std::copy_backward(I, OldEnd-NumToInsert, OldEnd); |
---|
509 | |
---|
510 | std::fill_n(I, NumToInsert, Elt); |
---|
511 | return I; |
---|
512 | } |
---|
513 | |
---|
514 | // Otherwise, we're inserting more elements than exist already, and we're |
---|
515 | // not inserting at the end. |
---|
516 | |
---|
517 | // Copy over the elements that we're about to overwrite. |
---|
518 | T *OldEnd = this->end(); |
---|
519 | this->setEnd(this->end() + NumToInsert); |
---|
520 | size_t NumOverwritten = OldEnd-I; |
---|
521 | this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); |
---|
522 | |
---|
523 | // Replace the overwritten part. |
---|
524 | std::fill_n(I, NumOverwritten, Elt); |
---|
525 | |
---|
526 | // Insert the non-overwritten middle part. |
---|
527 | std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); |
---|
528 | return I; |
---|
529 | } |
---|
530 | |
---|
531 | template<typename ItTy> |
---|
532 | iterator insert(iterator I, ItTy From, ItTy To) { |
---|
533 | if (I == this->end()) { // Important special case for empty vector. |
---|
534 | append(From, To); |
---|
535 | return this->end()-1; |
---|
536 | } |
---|
537 | |
---|
538 | size_t NumToInsert = std::distance(From, To); |
---|
539 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
---|
540 | size_t InsertElt = I - this->begin(); |
---|
541 | |
---|
542 | // Ensure there is enough space. |
---|
543 | reserve(static_cast<unsigned>(this->size() + NumToInsert)); |
---|
544 | |
---|
545 | // Uninvalidate the iterator. |
---|
546 | I = this->begin()+InsertElt; |
---|
547 | |
---|
548 | // If there are more elements between the insertion point and the end of the |
---|
549 | // range than there are being inserted, we can use a simple approach to |
---|
550 | // insertion. Since we already reserved space, we know that this won't |
---|
551 | // reallocate the vector. |
---|
552 | if (size_t(this->end()-I) >= NumToInsert) { |
---|
553 | T *OldEnd = this->end(); |
---|
554 | append(this->end()-NumToInsert, this->end()); |
---|
555 | |
---|
556 | // Copy the existing elements that get replaced. |
---|
557 | std::copy_backward(I, OldEnd-NumToInsert, OldEnd); |
---|
558 | |
---|
559 | std::copy(From, To, I); |
---|
560 | return I; |
---|
561 | } |
---|
562 | |
---|
563 | // Otherwise, we're inserting more elements than exist already, and we're |
---|
564 | // not inserting at the end. |
---|
565 | |
---|
566 | // Copy over the elements that we're about to overwrite. |
---|
567 | T *OldEnd = this->end(); |
---|
568 | this->setEnd(this->end() + NumToInsert); |
---|
569 | size_t NumOverwritten = OldEnd-I; |
---|
570 | this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); |
---|
571 | |
---|
572 | // Replace the overwritten part. |
---|
573 | for (; NumOverwritten > 0; --NumOverwritten) { |
---|
574 | *I = *From; |
---|
575 | ++I; ++From; |
---|
576 | } |
---|
577 | |
---|
578 | // Insert the non-overwritten middle part. |
---|
579 | this->uninitialized_copy(From, To, OldEnd); |
---|
580 | return I; |
---|
581 | } |
---|
582 | |
---|
583 | const SmallVectorImpl |
---|
584 | &operator=(const SmallVectorImpl &RHS); |
---|
585 | |
---|
586 | bool operator==(const SmallVectorImpl &RHS) const { |
---|
587 | if (this->size() != RHS.size()) return false; |
---|
588 | return std::equal(this->begin(), this->end(), RHS.begin()); |
---|
589 | } |
---|
590 | bool operator!=(const SmallVectorImpl &RHS) const { |
---|
591 | return !(*this == RHS); |
---|
592 | } |
---|
593 | |
---|
594 | bool operator<(const SmallVectorImpl &RHS) const { |
---|
595 | return std::lexicographical_compare(this->begin(), this->end(), |
---|
596 | RHS.begin(), RHS.end()); |
---|
597 | } |
---|
598 | |
---|
599 | /// set_size - Set the array size to \arg N, which the current array must have |
---|
600 | /// enough capacity for. |
---|
601 | /// |
---|
602 | /// This does not construct or destroy any elements in the vector. |
---|
603 | /// |
---|
604 | /// Clients can use this in conjunction with capacity() to write past the end |
---|
605 | /// of the buffer when they know that more elements are available, and only |
---|
606 | /// update the size later. This avoids the cost of value initializing elements |
---|
607 | /// which will only be overwritten. |
---|
608 | void set_size(unsigned N) { |
---|
609 | assert(N <= this->capacity()); |
---|
610 | this->setEnd(this->begin() + N); |
---|
611 | } |
---|
612 | |
---|
613 | private: |
---|
614 | static void construct_range(T *S, T *E, const T &Elt) { |
---|
615 | for (; S != E; ++S) |
---|
616 | new (S) T(Elt); |
---|
617 | } |
---|
618 | }; |
---|
619 | |
---|
620 | |
---|
621 | template <typename T> |
---|
622 | void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { |
---|
623 | if (this == &RHS) return; |
---|
624 | |
---|
625 | // We can only avoid copying elements if neither vector is small. |
---|
626 | if (!this->isSmall() && !RHS.isSmall()) { |
---|
627 | std::swap(this->BeginX, RHS.BeginX); |
---|
628 | std::swap(this->EndX, RHS.EndX); |
---|
629 | std::swap(this->CapacityX, RHS.CapacityX); |
---|
630 | return; |
---|
631 | } |
---|
632 | if (RHS.size() > this->capacity()) |
---|
633 | this->grow(RHS.size()); |
---|
634 | if (this->size() > RHS.capacity()) |
---|
635 | RHS.grow(this->size()); |
---|
636 | |
---|
637 | // Swap the shared elements. |
---|
638 | size_t NumShared = this->size(); |
---|
639 | if (NumShared > RHS.size()) NumShared = RHS.size(); |
---|
640 | for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i) |
---|
641 | std::swap((*this)[i], RHS[i]); |
---|
642 | |
---|
643 | // Copy over the extra elts. |
---|
644 | if (this->size() > RHS.size()) { |
---|
645 | size_t EltDiff = this->size() - RHS.size(); |
---|
646 | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); |
---|
647 | RHS.setEnd(RHS.end()+EltDiff); |
---|
648 | this->destroy_range(this->begin()+NumShared, this->end()); |
---|
649 | this->setEnd(this->begin()+NumShared); |
---|
650 | } else if (RHS.size() > this->size()) { |
---|
651 | size_t EltDiff = RHS.size() - this->size(); |
---|
652 | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); |
---|
653 | this->setEnd(this->end() + EltDiff); |
---|
654 | this->destroy_range(RHS.begin()+NumShared, RHS.end()); |
---|
655 | RHS.setEnd(RHS.begin()+NumShared); |
---|
656 | } |
---|
657 | } |
---|
658 | |
---|
659 | template <typename T> |
---|
660 | const SmallVectorImpl<T> &SmallVectorImpl<T>:: |
---|
661 | operator=(const SmallVectorImpl<T> &RHS) { |
---|
662 | // Avoid self-assignment. |
---|
663 | if (this == &RHS) return *this; |
---|
664 | |
---|
665 | // If we already have sufficient space, assign the common elements, then |
---|
666 | // destroy any excess. |
---|
667 | size_t RHSSize = RHS.size(); |
---|
668 | size_t CurSize = this->size(); |
---|
669 | if (CurSize >= RHSSize) { |
---|
670 | // Assign common elements. |
---|
671 | iterator NewEnd; |
---|
672 | if (RHSSize) |
---|
673 | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); |
---|
674 | else |
---|
675 | NewEnd = this->begin(); |
---|
676 | |
---|
677 | // Destroy excess elements. |
---|
678 | this->destroy_range(NewEnd, this->end()); |
---|
679 | |
---|
680 | // Trim. |
---|
681 | this->setEnd(NewEnd); |
---|
682 | return *this; |
---|
683 | } |
---|
684 | |
---|
685 | // If we have to grow to have enough elements, destroy the current elements. |
---|
686 | // This allows us to avoid copying them during the grow. |
---|
687 | if (this->capacity() < RHSSize) { |
---|
688 | // Destroy current elements. |
---|
689 | this->destroy_range(this->begin(), this->end()); |
---|
690 | this->setEnd(this->begin()); |
---|
691 | CurSize = 0; |
---|
692 | this->grow(RHSSize); |
---|
693 | } else if (CurSize) { |
---|
694 | // Otherwise, use assignment for the already-constructed elements. |
---|
695 | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); |
---|
696 | } |
---|
697 | |
---|
698 | // Copy construct the new elements in place. |
---|
699 | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), |
---|
700 | this->begin()+CurSize); |
---|
701 | |
---|
702 | // Set end. |
---|
703 | this->setEnd(this->begin()+RHSSize); |
---|
704 | return *this; |
---|
705 | } |
---|
706 | |
---|
707 | |
---|
708 | /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized |
---|
709 | /// for the case when the array is small. It contains some number of elements |
---|
710 | /// in-place, which allows it to avoid heap allocation when the actual number of |
---|
711 | /// elements is below that threshold. This allows normal "small" cases to be |
---|
712 | /// fast without losing generality for large inputs. |
---|
713 | /// |
---|
714 | /// Note that this does not attempt to be exception safe. |
---|
715 | /// |
---|
716 | template <typename T, unsigned N> |
---|
717 | class SmallVector : public SmallVectorImpl<T> { |
---|
718 | /// InlineElts - These are 'N-1' elements that are stored inline in the body |
---|
719 | /// of the vector. The extra '1' element is stored in SmallVectorImpl. |
---|
720 | typedef typename SmallVectorImpl<T>::U U; |
---|
721 | enum { |
---|
722 | // MinUs - The number of U's require to cover N T's. |
---|
723 | MinUs = (static_cast<unsigned int>(sizeof(T))*N + |
---|
724 | static_cast<unsigned int>(sizeof(U)) - 1) / |
---|
725 | static_cast<unsigned int>(sizeof(U)), |
---|
726 | |
---|
727 | // NumInlineEltsElts - The number of elements actually in this array. There |
---|
728 | // is already one in the parent class, and we have to round up to avoid |
---|
729 | // having a zero-element array. |
---|
730 | NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, |
---|
731 | |
---|
732 | // NumTsAvailable - The number of T's we actually have space for, which may |
---|
733 | // be more than N due to rounding. |
---|
734 | NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/ |
---|
735 | static_cast<unsigned int>(sizeof(T)) |
---|
736 | }; |
---|
737 | U InlineElts[NumInlineEltsElts]; |
---|
738 | public: |
---|
739 | SmallVector() : SmallVectorImpl<T>(NumTsAvailable) { |
---|
740 | } |
---|
741 | |
---|
742 | explicit SmallVector(unsigned Size, const T &Value = T()) |
---|
743 | : SmallVectorImpl<T>(NumTsAvailable) { |
---|
744 | this->reserve(Size); |
---|
745 | while (Size--) |
---|
746 | this->push_back(Value); |
---|
747 | } |
---|
748 | |
---|
749 | template<typename ItTy> |
---|
750 | SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) { |
---|
751 | this->append(S, E); |
---|
752 | } |
---|
753 | |
---|
754 | SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) { |
---|
755 | if (!RHS.empty()) |
---|
756 | SmallVectorImpl<T>::operator=(RHS); |
---|
757 | } |
---|
758 | |
---|
759 | const SmallVector &operator=(const SmallVector &RHS) { |
---|
760 | SmallVectorImpl<T>::operator=(RHS); |
---|
761 | return *this; |
---|
762 | } |
---|
763 | |
---|
764 | }; |
---|
765 | |
---|
766 | /// Specialize SmallVector at N=0. This specialization guarantees |
---|
767 | /// that it can be instantiated at an incomplete T if none of its |
---|
768 | /// members are required. |
---|
769 | template <typename T> |
---|
770 | class SmallVector<T,0> : public SmallVectorImpl<T> { |
---|
771 | public: |
---|
772 | SmallVector() : SmallVectorImpl<T>(0) {} |
---|
773 | |
---|
774 | explicit SmallVector(unsigned Size, const T &Value = T()) |
---|
775 | : SmallVectorImpl<T>(0) { |
---|
776 | this->reserve(Size); |
---|
777 | while (Size--) |
---|
778 | this->push_back(Value); |
---|
779 | } |
---|
780 | |
---|
781 | template<typename ItTy> |
---|
782 | SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(0) { |
---|
783 | this->append(S, E); |
---|
784 | } |
---|
785 | |
---|
786 | SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(0) { |
---|
787 | SmallVectorImpl<T>::operator=(RHS); |
---|
788 | } |
---|
789 | |
---|
790 | SmallVector &operator=(const SmallVectorImpl<T> &RHS) { |
---|
791 | return SmallVectorImpl<T>::operator=(RHS); |
---|
792 | } |
---|
793 | |
---|
794 | }; |
---|
795 | |
---|
796 | } // End Ogre namespace |
---|
797 | |
---|
798 | namespace std { |
---|
799 | /// Implement std::swap in terms of SmallVector swap. |
---|
800 | template<typename T> |
---|
801 | inline void |
---|
802 | swap(Ogre::SmallVectorImpl<T> &LHS, Ogre::SmallVectorImpl<T> &RHS) { |
---|
803 | LHS.swap(RHS); |
---|
804 | } |
---|
805 | |
---|
806 | /// Implement std::swap in terms of SmallVector swap. |
---|
807 | template<typename T, unsigned N> |
---|
808 | inline void |
---|
809 | swap(Ogre::SmallVector<T, N> &LHS, Ogre::SmallVector<T, N> &RHS) { |
---|
810 | LHS.swap(RHS); |
---|
811 | } |
---|
812 | } |
---|
813 | |
---|
814 | #endif |
---|