[148] | 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 |
---|