OgreSmallVector.h
Go to the documentation of this file.

    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 Sun Sep 2 2012 07:27:24