00001 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. 00007 // ============================================================================== 00008 // LLVM Release License 00009 // ============================================================================== 00010 // University of Illinois/NCSA 00011 // Open Source License 00012 // 00013 // Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign. 00014 // All rights reserved. 00015 // 00016 // Developed by: 00017 // 00018 // LLVM Team 00019 // 00020 // University of Illinois at Urbana-Champaign 00021 // 00022 // http://llvm.org 00023 // 00024 // Permission is hereby granted, free of charge, to any person obtaining a copy of 00025 // this software and associated documentation files (the "Software"), to deal with 00026 // the Software without restriction, including without limitation the rights to 00027 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 00028 // of the Software, and to permit persons to whom the Software is furnished to do 00029 // so, subject to the following conditions: 00030 // 00031 // * Redistributions of source code must retain the above copyright notice, 00032 // this list of conditions and the following disclaimers. 00033 // 00034 // * Redistributions in binary form must reproduce the above copyright notice, 00035 // this list of conditions and the following disclaimers in the 00036 // documentation and/or other materials provided with the distribution. 00037 // 00038 // * Neither the names of the LLVM Team, University of Illinois at 00039 // Urbana-Champaign, nor the names of its contributors may be used to 00040 // endorse or promote products derived from this Software without specific 00041 // prior written permission. 00042 // 00043 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00044 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 00045 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00046 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00047 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00048 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 00049 // SOFTWARE. 00050 // 00051 //===----------------------------------------------------------------------===// 00052 // 00053 // This file defines the SmallVector class. 00054 // 00055 //===----------------------------------------------------------------------===// 00056 00057 #ifndef __SmallVector_H 00058 #define __SmallVector_H 00059 00060 #include <algorithm> 00061 #include <cassert> 00062 #include <cstddef> 00063 #include <cstdlib> 00064 #include <cstring> 00065 #include <iterator> 00066 #include <memory> 00067 00068 #ifdef _MSC_VER 00069 namespace std { 00070 #if _MSC_VER <= 1310 00071 // Work around flawed VC++ implementation of std::uninitialized_copy. Define 00072 // additional overloads so that elements with pointer types are recognized as 00073 // scalars and not objects, causing bizarre type conversion errors. 00074 template<class T1, class T2> 00075 inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { 00076 _Scalar_ptr_iterator_tag _Cat; 00077 return _Cat; 00078 } 00079 00080 template<class T1, class T2> 00081 inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { 00082 _Scalar_ptr_iterator_tag _Cat; 00083 return _Cat; 00084 } 00085 #else 00086 // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear 00087 // is that the above hack won't work if it wasn't fixed. 00088 #endif 00089 } 00090 #endif 00091 00092 namespace Ogre { 00093 00094 // some type traits 00095 template <typename T> struct isPodLike { static const bool value = false; }; 00096 00097 template <> struct isPodLike<bool> { static const bool value = true; }; 00098 template <> struct isPodLike<char> { static const bool value = true; }; 00099 template <> struct isPodLike<signed char> { static const bool value = true; }; 00100 template <> struct isPodLike<unsigned char> { static const bool value = true; }; 00101 template <> struct isPodLike<int> { static const bool value = true; }; 00102 template <> struct isPodLike<unsigned> { static const bool value = true; }; 00103 template <> struct isPodLike<short> { static const bool value = true; }; 00104 template <> struct isPodLike<unsigned short> { static const bool value = true; }; 00105 template <> struct isPodLike<long> { static const bool value = true; }; 00106 template <> struct isPodLike<unsigned long> { static const bool value = true; }; 00107 template <> struct isPodLike<float> { static const bool value = true; }; 00108 template <> struct isPodLike<double> { static const bool value = true; }; 00109 template <typename T> struct isPodLike<T*> { static const bool value = true; }; 00110 00111 template<typename T, typename U> 00112 struct isPodLike<std::pair<T, U> > { static const bool value = isPodLike<T>::value & isPodLike<U>::value; }; 00113 00116 class SmallVectorBase { 00117 protected: 00118 void *BeginX, *EndX, *CapacityX; 00119 00120 // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 00121 // don't want it to be automatically run, so we need to represent the space as 00122 // something else. An array of char would work great, but might not be 00123 // aligned sufficiently. Instead we use some number of union instances for 00124 // the space, which guarantee maximal alignment. 00125 union U { 00126 double D; 00127 long double LD; 00128 long long L; 00129 void *P; 00130 } FirstEl; 00131 // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 00132 00133 protected: 00134 SmallVectorBase(size_t Size) 00135 : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {} 00136 00139 bool isSmall() const { 00140 return BeginX == static_cast<const void*>(&FirstEl); 00141 } 00142 00144 size_t size_in_bytes() const { 00145 return size_t((char*)EndX - (char*)BeginX); 00146 } 00147 00149 size_t capacity_in_bytes() const { 00150 return size_t((char*)CapacityX - (char*)BeginX); 00151 } 00152 00155 void grow_pod(size_t MinSizeInBytes, size_t TSize); 00156 00157 public: 00158 bool empty() const { return BeginX == EndX; } 00159 }; 00160 00161 00162 template <typename T> 00163 class SmallVectorTemplateCommon : public SmallVectorBase { 00164 protected: 00165 void setEnd(T *P) { this->EndX = P; } 00166 public: 00167 SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} 00168 00169 typedef size_t size_type; 00170 typedef ptrdiff_t difference_type; 00171 typedef T value_type; 00172 typedef T *iterator; 00173 typedef const T *const_iterator; 00174 00175 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00176 typedef std::reverse_iterator<iterator> reverse_iterator; 00177 00178 typedef T &reference; 00179 typedef const T &const_reference; 00180 typedef T *pointer; 00181 typedef const T *const_pointer; 00182 00183 // forward iterator creation methods. 00184 iterator begin() { return (iterator)this->BeginX; } 00185 const_iterator begin() const { return (const_iterator)this->BeginX; } 00186 iterator end() { return (iterator)this->EndX; } 00187 const_iterator end() const { return (const_iterator)this->EndX; } 00188 protected: 00189 iterator capacity_ptr() { return (iterator)this->CapacityX; } 00190 const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} 00191 public: 00192 00193 // reverse iterator creation methods. 00194 reverse_iterator rbegin() { return reverse_iterator(end()); } 00195 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 00196 reverse_iterator rend() { return reverse_iterator(begin()); } 00197 const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 00198 00199 size_type size() const { return end()-begin(); } 00200 size_type max_size() const { return size_type(-1) / sizeof(T); } 00201 00204 size_t capacity() const { return capacity_ptr() - begin(); } 00205 00207 pointer data() { return pointer(begin()); } 00209 const_pointer data() const { return const_pointer(begin()); } 00210 00211 reference operator[](unsigned idx) { 00212 assert(begin() + idx < end()); 00213 return begin()[idx]; 00214 } 00215 const_reference operator[](unsigned idx) const { 00216 assert(begin() + idx < end()); 00217 return begin()[idx]; 00218 } 00219 00220 reference front() { 00221 return begin()[0]; 00222 } 00223 const_reference front() const { 00224 return begin()[0]; 00225 } 00226 00227 reference back() { 00228 return end()[-1]; 00229 } 00230 const_reference back() const { 00231 return end()[-1]; 00232 } 00233 }; 00234 00237 template <typename T, bool isPodLike> 00238 class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { 00239 public: 00240 SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} 00241 00242 static void destroy_range(T *S, T *E) { 00243 while (S != E) { 00244 --E; 00245 E->~T(); 00246 } 00247 } 00248 00251 template<typename It1, typename It2> 00252 static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 00253 std::uninitialized_copy(I, E, Dest); 00254 } 00255 00258 void grow(size_t MinSize = 0); 00259 }; 00260 00261 // Define this out-of-line to dissuade the C++ compiler from inlining it. 00262 template <typename T, bool isPodLike> 00263 void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { 00264 size_t CurCapacity = this->capacity(); 00265 size_t CurSize = this->size(); 00266 size_t NewCapacity = 2*CurCapacity + 1; // Always grow, even from zero. 00267 if (NewCapacity < MinSize) 00268 NewCapacity = MinSize; 00269 T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); 00270 00271 // Copy the elements over. 00272 this->uninitialized_copy(this->begin(), this->end(), NewElts); 00273 00274 // Destroy the original elements. 00275 destroy_range(this->begin(), this->end()); 00276 00277 // If this wasn't grown from the inline copy, deallocate the old space. 00278 if (!this->isSmall()) 00279 free(this->begin()); 00280 00281 this->setEnd(NewElts+CurSize); 00282 this->BeginX = NewElts; 00283 this->CapacityX = this->begin()+NewCapacity; 00284 } 00285 00286 00289 template <typename T> 00290 class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { 00291 public: 00292 SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} 00293 00294 // No need to do a destroy loop for POD's. 00295 static void destroy_range(T *, T *) {} 00296 00299 template<typename It1, typename It2> 00300 static void uninitialized_copy(It1 I, It1 E, It2 Dest) { 00301 // Arbitrary iterator types; just use the basic implementation. 00302 std::uninitialized_copy(I, E, Dest); 00303 } 00304 00307 template<typename T1, typename T2> 00308 static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { 00309 // Use memcpy for PODs iterated by pointers (which includes SmallVector 00310 // iterators): std::uninitialized_copy optimizes to memmove, but we can 00311 // use memcpy here. 00312 memcpy(Dest, I, (E-I)*sizeof(T)); 00313 } 00314 00317 void grow(size_t MinSize = 0) { 00318 this->grow_pod(MinSize*sizeof(T), sizeof(T)); 00319 } 00320 }; 00321 00322 00326 template <typename T> 00327 class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { 00328 typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; 00329 00330 SmallVectorImpl(const SmallVectorImpl&); // DISABLED. 00331 public: 00332 typedef typename SuperClass::iterator iterator; 00333 typedef typename SuperClass::size_type size_type; 00334 00335 // Default ctor - Initialize to empty. 00336 explicit SmallVectorImpl(unsigned N) 00337 : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) { 00338 } 00339 00340 ~SmallVectorImpl() { 00341 // Destroy the constructed elements in the vector. 00342 this->destroy_range(this->begin(), this->end()); 00343 00344 // If this wasn't grown from the inline copy, deallocate the old space. 00345 if (!this->isSmall()) 00346 free(this->begin()); 00347 } 00348 00349 00350 void clear() { 00351 this->destroy_range(this->begin(), this->end()); 00352 this->EndX = this->BeginX; 00353 } 00354 00355 void resize(unsigned N) { 00356 if (N < this->size()) { 00357 this->destroy_range(this->begin()+N, this->end()); 00358 this->setEnd(this->begin()+N); 00359 } else if (N > this->size()) { 00360 if (this->capacity() < N) 00361 this->grow(N); 00362 this->construct_range(this->end(), this->begin()+N, T()); 00363 this->setEnd(this->begin()+N); 00364 } 00365 } 00366 00367 void resize(unsigned N, const T &NV) { 00368 if (N < this->size()) { 00369 this->destroy_range(this->begin()+N, this->end()); 00370 this->setEnd(this->begin()+N); 00371 } else if (N > this->size()) { 00372 if (this->capacity() < N) 00373 this->grow(N); 00374 construct_range(this->end(), this->begin()+N, NV); 00375 this->setEnd(this->begin()+N); 00376 } 00377 } 00378 00379 void reserve(unsigned N) { 00380 if (this->capacity() < N) 00381 this->grow(N); 00382 } 00383 00384 void push_back(const T &Elt) { 00385 if (this->EndX < this->CapacityX) { 00386 Retry: 00387 new (this->end()) T(Elt); 00388 this->setEnd(this->end()+1); 00389 return; 00390 } 00391 this->grow(); 00392 goto Retry; 00393 } 00394 00395 void pop_back() { 00396 this->setEnd(this->end()-1); 00397 this->end()->~T(); 00398 } 00399 00400 T pop_back_val() { 00401 T Result = this->back(); 00402 pop_back(); 00403 return Result; 00404 } 00405 00406 void swap(SmallVectorImpl &RHS); 00407 00410 template<typename in_iter> 00411 void append(in_iter in_start, in_iter in_end) { 00412 size_type NumInputs = std::distance(in_start, in_end); 00413 // Grow allocated space if needed. 00414 if (NumInputs > size_type(this->capacity_ptr()-this->end())) 00415 this->grow(this->size()+NumInputs); 00416 00417 // Copy the new elements over. 00418 // TODO: NEED To compile time dispatch on whether in_iter is a random access 00419 // iterator to use the fast uninitialized_copy. 00420 std::uninitialized_copy(in_start, in_end, this->end()); 00421 this->setEnd(this->end() + NumInputs); 00422 } 00423 00426 void append(size_type NumInputs, const T &Elt) { 00427 // Grow allocated space if needed. 00428 if (NumInputs > size_type(this->capacity_ptr()-this->end())) 00429 this->grow(this->size()+NumInputs); 00430 00431 // Copy the new elements over. 00432 std::uninitialized_fill_n(this->end(), NumInputs, Elt); 00433 this->setEnd(this->end() + NumInputs); 00434 } 00435 00436 void assign(unsigned NumElts, const T &Elt) { 00437 clear(); 00438 if (this->capacity() < NumElts) 00439 this->grow(NumElts); 00440 this->setEnd(this->begin()+NumElts); 00441 construct_range(this->begin(), this->end(), Elt); 00442 } 00443 00444 iterator erase(iterator I) { 00445 iterator N = I; 00446 // Shift all elts down one. 00447 std::copy(I+1, this->end(), I); 00448 // Drop the last elt. 00449 pop_back(); 00450 return(N); 00451 } 00452 00453 iterator erase(iterator S, iterator E) { 00454 iterator N = S; 00455 // Shift all elts down. 00456 iterator I = std::copy(E, this->end(), S); 00457 // Drop the last elts. 00458 this->destroy_range(I, this->end()); 00459 this->setEnd(I); 00460 return(N); 00461 } 00462 00463 iterator insert(iterator I, const T &Elt) { 00464 if (I == this->end()) { // Important special case for empty vector. 00465 push_back(Elt); 00466 return this->end()-1; 00467 } 00468 00469 if (this->EndX < this->CapacityX) { 00470 Retry: 00471 new (this->end()) T(this->back()); 00472 this->setEnd(this->end()+1); 00473 // Push everything else over. 00474 std::copy_backward(I, this->end()-1, this->end()); 00475 *I = Elt; 00476 return I; 00477 } 00478 size_t EltNo = I-this->begin(); 00479 this->grow(); 00480 I = this->begin()+EltNo; 00481 goto Retry; 00482 } 00483 00484 iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 00485 if (I == this->end()) { // Important special case for empty vector. 00486 append(NumToInsert, Elt); 00487 return this->end()-1; 00488 } 00489 00490 // Convert iterator to elt# to avoid invalidating iterator when we reserve() 00491 size_t InsertElt = I - this->begin(); 00492 00493 // Ensure there is enough space. 00494 reserve(static_cast<unsigned>(this->size() + NumToInsert)); 00495 00496 // Uninvalidate the iterator. 00497 I = this->begin()+InsertElt; 00498 00499 // If there are more elements between the insertion point and the end of the 00500 // range than there are being inserted, we can use a simple approach to 00501 // insertion. Since we already reserved space, we know that this won't 00502 // reallocate the vector. 00503 if (size_t(this->end()-I) >= NumToInsert) { 00504 T *OldEnd = this->end(); 00505 append(this->end()-NumToInsert, this->end()); 00506 00507 // Copy the existing elements that get replaced. 00508 std::copy_backward(I, OldEnd-NumToInsert, OldEnd); 00509 00510 std::fill_n(I, NumToInsert, Elt); 00511 return I; 00512 } 00513 00514 // Otherwise, we're inserting more elements than exist already, and we're 00515 // not inserting at the end. 00516 00517 // Copy over the elements that we're about to overwrite. 00518 T *OldEnd = this->end(); 00519 this->setEnd(this->end() + NumToInsert); 00520 size_t NumOverwritten = OldEnd-I; 00521 this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); 00522 00523 // Replace the overwritten part. 00524 std::fill_n(I, NumOverwritten, Elt); 00525 00526 // Insert the non-overwritten middle part. 00527 std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 00528 return I; 00529 } 00530 00531 template<typename ItTy> 00532 iterator insert(iterator I, ItTy From, ItTy To) { 00533 if (I == this->end()) { // Important special case for empty vector. 00534 append(From, To); 00535 return this->end()-1; 00536 } 00537 00538 size_t NumToInsert = std::distance(From, To); 00539 // Convert iterator to elt# to avoid invalidating iterator when we reserve() 00540 size_t InsertElt = I - this->begin(); 00541 00542 // Ensure there is enough space. 00543 reserve(static_cast<unsigned>(this->size() + NumToInsert)); 00544 00545 // Uninvalidate the iterator. 00546 I = this->begin()+InsertElt; 00547 00548 // If there are more elements between the insertion point and the end of the 00549 // range than there are being inserted, we can use a simple approach to 00550 // insertion. Since we already reserved space, we know that this won't 00551 // reallocate the vector. 00552 if (size_t(this->end()-I) >= NumToInsert) { 00553 T *OldEnd = this->end(); 00554 append(this->end()-NumToInsert, this->end()); 00555 00556 // Copy the existing elements that get replaced. 00557 std::copy_backward(I, OldEnd-NumToInsert, OldEnd); 00558 00559 std::copy(From, To, I); 00560 return I; 00561 } 00562 00563 // Otherwise, we're inserting more elements than exist already, and we're 00564 // not inserting at the end. 00565 00566 // Copy over the elements that we're about to overwrite. 00567 T *OldEnd = this->end(); 00568 this->setEnd(this->end() + NumToInsert); 00569 size_t NumOverwritten = OldEnd-I; 00570 this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); 00571 00572 // Replace the overwritten part. 00573 for (; NumOverwritten > 0; --NumOverwritten) { 00574 *I = *From; 00575 ++I; ++From; 00576 } 00577 00578 // Insert the non-overwritten middle part. 00579 this->uninitialized_copy(From, To, OldEnd); 00580 return I; 00581 } 00582 00583 const SmallVectorImpl 00584 &operator=(const SmallVectorImpl &RHS); 00585 00586 bool operator==(const SmallVectorImpl &RHS) const { 00587 if (this->size() != RHS.size()) return false; 00588 return std::equal(this->begin(), this->end(), RHS.begin()); 00589 } 00590 bool operator!=(const SmallVectorImpl &RHS) const { 00591 return !(*this == RHS); 00592 } 00593 00594 bool operator<(const SmallVectorImpl &RHS) const { 00595 return std::lexicographical_compare(this->begin(), this->end(), 00596 RHS.begin(), RHS.end()); 00597 } 00598 00608 void set_size(unsigned N) { 00609 assert(N <= this->capacity()); 00610 this->setEnd(this->begin() + N); 00611 } 00612 00613 private: 00614 static void construct_range(T *S, T *E, const T &Elt) { 00615 for (; S != E; ++S) 00616 new (S) T(Elt); 00617 } 00618 }; 00619 00620 00621 template <typename T> 00622 void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { 00623 if (this == &RHS) return; 00624 00625 // We can only avoid copying elements if neither vector is small. 00626 if (!this->isSmall() && !RHS.isSmall()) { 00627 std::swap(this->BeginX, RHS.BeginX); 00628 std::swap(this->EndX, RHS.EndX); 00629 std::swap(this->CapacityX, RHS.CapacityX); 00630 return; 00631 } 00632 if (RHS.size() > this->capacity()) 00633 this->grow(RHS.size()); 00634 if (this->size() > RHS.capacity()) 00635 RHS.grow(this->size()); 00636 00637 // Swap the shared elements. 00638 size_t NumShared = this->size(); 00639 if (NumShared > RHS.size()) NumShared = RHS.size(); 00640 for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i) 00641 std::swap((*this)[i], RHS[i]); 00642 00643 // Copy over the extra elts. 00644 if (this->size() > RHS.size()) { 00645 size_t EltDiff = this->size() - RHS.size(); 00646 this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); 00647 RHS.setEnd(RHS.end()+EltDiff); 00648 this->destroy_range(this->begin()+NumShared, this->end()); 00649 this->setEnd(this->begin()+NumShared); 00650 } else if (RHS.size() > this->size()) { 00651 size_t EltDiff = RHS.size() - this->size(); 00652 this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); 00653 this->setEnd(this->end() + EltDiff); 00654 this->destroy_range(RHS.begin()+NumShared, RHS.end()); 00655 RHS.setEnd(RHS.begin()+NumShared); 00656 } 00657 } 00658 00659 template <typename T> 00660 const SmallVectorImpl<T> &SmallVectorImpl<T>:: 00661 operator=(const SmallVectorImpl<T> &RHS) { 00662 // Avoid self-assignment. 00663 if (this == &RHS) return *this; 00664 00665 // If we already have sufficient space, assign the common elements, then 00666 // destroy any excess. 00667 size_t RHSSize = RHS.size(); 00668 size_t CurSize = this->size(); 00669 if (CurSize >= RHSSize) { 00670 // Assign common elements. 00671 iterator NewEnd; 00672 if (RHSSize) 00673 NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); 00674 else 00675 NewEnd = this->begin(); 00676 00677 // Destroy excess elements. 00678 this->destroy_range(NewEnd, this->end()); 00679 00680 // Trim. 00681 this->setEnd(NewEnd); 00682 return *this; 00683 } 00684 00685 // If we have to grow to have enough elements, destroy the current elements. 00686 // This allows us to avoid copying them during the grow. 00687 if (this->capacity() < RHSSize) { 00688 // Destroy current elements. 00689 this->destroy_range(this->begin(), this->end()); 00690 this->setEnd(this->begin()); 00691 CurSize = 0; 00692 this->grow(RHSSize); 00693 } else if (CurSize) { 00694 // Otherwise, use assignment for the already-constructed elements. 00695 std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); 00696 } 00697 00698 // Copy construct the new elements in place. 00699 this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), 00700 this->begin()+CurSize); 00701 00702 // Set end. 00703 this->setEnd(this->begin()+RHSSize); 00704 return *this; 00705 } 00706 00707 00716 template <typename T, unsigned N> 00717 class SmallVector : public SmallVectorImpl<T> { 00720 typedef typename SmallVectorImpl<T>::U U; 00721 enum { 00722 // MinUs - The number of U's require to cover N T's. 00723 MinUs = (static_cast<unsigned int>(sizeof(T))*N + 00724 static_cast<unsigned int>(sizeof(U)) - 1) / 00725 static_cast<unsigned int>(sizeof(U)), 00726 00727 // NumInlineEltsElts - The number of elements actually in this array. There 00728 // is already one in the parent class, and we have to round up to avoid 00729 // having a zero-element array. 00730 NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, 00731 00732 // NumTsAvailable - The number of T's we actually have space for, which may 00733 // be more than N due to rounding. 00734 NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/ 00735 static_cast<unsigned int>(sizeof(T)) 00736 }; 00737 U InlineElts[NumInlineEltsElts]; 00738 public: 00739 SmallVector() : SmallVectorImpl<T>(NumTsAvailable) { 00740 } 00741 00742 explicit SmallVector(unsigned Size, const T &Value = T()) 00743 : SmallVectorImpl<T>(NumTsAvailable) { 00744 this->reserve(Size); 00745 while (Size--) 00746 this->push_back(Value); 00747 } 00748 00749 template<typename ItTy> 00750 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) { 00751 this->append(S, E); 00752 } 00753 00754 SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) { 00755 if (!RHS.empty()) 00756 SmallVectorImpl<T>::operator=(RHS); 00757 } 00758 00759 const SmallVector &operator=(const SmallVector &RHS) { 00760 SmallVectorImpl<T>::operator=(RHS); 00761 return *this; 00762 } 00763 00764 }; 00765 00769 template <typename T> 00770 class SmallVector<T,0> : public SmallVectorImpl<T> { 00771 public: 00772 SmallVector() : SmallVectorImpl<T>(0) {} 00773 00774 explicit SmallVector(unsigned Size, const T &Value = T()) 00775 : SmallVectorImpl<T>(0) { 00776 this->reserve(Size); 00777 while (Size--) 00778 this->push_back(Value); 00779 } 00780 00781 template<typename ItTy> 00782 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(0) { 00783 this->append(S, E); 00784 } 00785 00786 SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(0) { 00787 SmallVectorImpl<T>::operator=(RHS); 00788 } 00789 00790 SmallVector &operator=(const SmallVectorImpl<T> &RHS) { 00791 return SmallVectorImpl<T>::operator=(RHS); 00792 } 00793 00794 }; 00795 00796 } // End Ogre namespace 00797 00798 namespace std { 00800 template<typename T> 00801 inline void 00802 swap(Ogre::SmallVectorImpl<T> &LHS, Ogre::SmallVectorImpl<T> &RHS) { 00803 LHS.swap(RHS); 00804 } 00805 00807 template<typename T, unsigned N> 00808 inline void 00809 swap(Ogre::SmallVector<T, N> &LHS, Ogre::SmallVector<T, N> &RHS) { 00810 LHS.swap(RHS); 00811 } 00812 } 00813 00814 #endif
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:27 2012