/* =========================================================================== Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. =========================================================================== */ //////////////////////////////////////////////////////////////////////////////////////// // RAVEN STANDARD TEMPLATE LIBRARY // (c) 2002 Activision // // // Vector // ------ // The vector class is a simple addition to the array. It supports some useful additions // like sort and binary search, as well as keeping track of the number of objects // contained within. // // // // // // NOTES: // // //////////////////////////////////////////////////////////////////////////////////////// #if !defined(RATL_VECTOR_VS_INC) #define RATL_VECTOR_VS_INC //////////////////////////////////////////////////////////////////////////////////////// // Includes //////////////////////////////////////////////////////////////////////////////////////// #if !defined(RATL_COMMON_INC) #include "ratl_common.h" #endif namespace ratl { //////////////////////////////////////////////////////////////////////////////////////// // The Vector Class //////////////////////////////////////////////////////////////////////////////////////// template<class T> class vector_base : public ratl_base { public: typedef T TStorageTraits; typedef typename T::TValue TTValue; //////////////////////////////////////////////////////////////////////////////////// // Capacity Enum //////////////////////////////////////////////////////////////////////////////////// static const int CAPACITY = T::CAPACITY; private: array_base<TStorageTraits> mArray; // The Memory int mSize; public: //////////////////////////////////////////////////////////////////////////////////// // Constructor //////////////////////////////////////////////////////////////////////////////////// vector_base() { mSize = 0; } //////////////////////////////////////////////////////////////////////////////////// // Copy Constructor //////////////////////////////////////////////////////////////////////////////////// vector_base(const vector_base &B) { for (int i=0; i<B.size(); i++) { mArray[i] = B.mArray[i]; } mSize = B.mSize; } //////////////////////////////////////////////////////////////////////////////////// // How Many Objects Can Be Added? //////////////////////////////////////////////////////////////////////////////////// int capacity() const { assert(mSize>=0&&mSize<=CAPACITY); return (CAPACITY); } //////////////////////////////////////////////////////////////////////////////////// // How Many Objects Have Been Added To This Vector? //////////////////////////////////////////////////////////////////////////////////// int size() const { assert(mSize>=0&&mSize<=CAPACITY); return (mSize); } //////////////////////////////////////////////////////////////////////////////////// // Have Any Objects Have Been Added To This Vector? //////////////////////////////////////////////////////////////////////////////////// bool empty() const { assert(mSize>=0&&mSize<=CAPACITY); return (!mSize); } //////////////////////////////////////////////////////////////////////////////////// // Have Any Objects Have Been Added To This Vector? //////////////////////////////////////////////////////////////////////////////////// bool full() const { assert(mSize>=0&&mSize<=CAPACITY); return (mSize==CAPACITY); } //////////////////////////////////////////////////////////////////////////////////// // Clear Out Entire Array //////////////////////////////////////////////////////////////////////////////////// void clear() { mArray.clear(); mSize = 0; } // Constant Access Operator //////////////////////////////////////////////////////////////////////////////////// const TTValue& operator[](int index) const { assert(index>=0&&index<mSize); return mArray[index]; } //////////////////////////////////////////////////////////////////////////////////// // Access Operator //////////////////////////////////////////////////////////////////////////////////// TTValue& operator[](int index) { assert(index>=0&&index<mSize); return mArray[index]; } //////////////////////////////////////////////////////////////////////////////////// // Access To The Raw Array Pointer //////////////////////////////////////////////////////////////////////////////////// TTValue * raw_array() { // this (intentionally) won't compile for anything except value semantics // could be done with object semantics, but I would want to assert that all objects are contructed return T::raw_array(mArray); } //////////////////////////////////////////////////////////////////////////////////// // Access To The Raw Array Pointer //////////////////////////////////////////////////////////////////////////////////// const TTValue* raw_array() const { // this (intentionally) won't compile for anything except value semantics // could be done with object semantics, but I would want to assert that all objects are contructed return T::raw_array(mArray); } //////////////////////////////////////////////////////////////////////////////////// // Assignment Operator //////////////////////////////////////////////////////////////////////////////////// vector_base& operator=(const vector_base& val) { for (int i=0; i<val.size(); i++) { mArray[i] = val.mArray[i]; } mSize = val.mSize; return *this; } //////////////////////////////////////////////////////////////////////////////////// // Add //////////////////////////////////////////////////////////////////////////////////// TTValue & push_back() { assert(mSize>=0&&mSize<CAPACITY); mArray.construct(mSize); mSize++; return (mArray[mSize-1]); } //////////////////////////////////////////////////////////////////////////////////// // Add (And Set) //////////////////////////////////////////////////////////////////////////////////// void push_back(const TTValue& value) { assert(mSize>=0&&mSize<CAPACITY); mArray.construct(mSize,value); mSize++; } //////////////////////////////////////////////////////////////////////////////////// // Add raw //////////////////////////////////////////////////////////////////////////////////// TRatlNew * push_back_raw() { assert(mSize>=0&&mSize<CAPACITY); mSize++; return mArray.alloc_raw(mSize-1); } //////////////////////////////////////////////////////////////////////////////////// // Remove //////////////////////////////////////////////////////////////////////////////////// void pop_back() { assert(mSize>0); mSize--; mArray.destruct(mSize); } //////////////////////////////////////////////////////////////////////////////////// // Resizes The Array. If New Elements Are Needed, It Uses The (value) Param //////////////////////////////////////////////////////////////////////////////////// void resize(int nSize, const TTValue& value) { int i; for (i=(mSize-1); i>=nSize; i--) { mArray.destruct(i); mSize--; } for (i=mSize; i<nSize; i++) { mArray.construct(i,value); } mSize = nSize; } //////////////////////////////////////////////////////////////////////////////////// // Resizes The Array. If New Elements Are Needed, It Uses The (value) Param //////////////////////////////////////////////////////////////////////////////////// void resize(int nSize) { int i; for (i=mSize-1; i>=nSize; i--) { mArray.destruct(i); mSize--; } for (i=mSize; i<nSize; i++) { mArray.construct(i); } mSize = nSize; } //////////////////////////////////////////////////////////////////////////////////// // Swap the values at two locations //////////////////////////////////////////////////////////////////////////////////// void swap(int i,int j) { assert(i<mSize && j<mSize); mArray.swap(i, j); } //////////////////////////////////////////////////////////////////////////////////// // Erase An Iterator Location... NOTE: THIS DOES NOT PRESERVE ORDER IN THE VECTOR!! //////////////////////////////////////////////////////////////////////////////////// void erase_swap(int Index) { assert(Index>=0 && Index<mSize); if (Index != mSize - 1) { mArray.swap(Index, mSize - 1); } pop_back(); } //////////////////////////////////////////////////////////////////////////////////// // Binary Search //////////////////////////////////////////////////////////////////////////////////// int find_index(const TTValue& value) const { int base = 0; int head = mSize-1; while (1) { int searchAt = (base+head)/2; if (base == head && searchAt == head) { break; } if (value < mArray[searchAt]) { head = searchAt-1; } else if (mArray[searchAt] < value) { base = searchAt; } else { return searchAt; } if (head < base) { break; } } return mSize; //not found! } //////////////////////////////////////////////////////////////////////////////////// // Heap Sort // // This sort algorithm has all the advantages of merge sort in terms of guarenteeing // O(n log n) worst case, as well as all the advantages of quick sort in that it is // "in place" and requires no additional storage. // //////////////////////////////////////////////////////////////////////////////////// void sort() { // Temporary Data //---------------- int HeapSize; // How Large The Heap Is (Grows In PHASE 1, Shrinks In PHASE 2) int Pos; // The Location We Are AT During "re-heapify" Loops int Compare; // The Location We Are Comparing AGAINST During "re-heapify" Loops // PHASE 1, CONSTRUCT THE HEAP O(n log n) //=============================================================================== for (HeapSize=1; HeapSize<mSize; HeapSize++) { // We Now Have An Element At Heap Size Which Is Not In It's Correct Place //------------------------------------------------------------------------ Pos = HeapSize; Compare = parent(Pos); while (mArray[Compare]<mArray[Pos]) { // Swap The Compare Element With The Pos Element //----------------------------------------------- mArray.swap(Compare, Pos); // Move Pos To The Current Compare, And Recalc Compare //------------------------------------------------------ Pos = Compare; Compare = parent(Pos); } } // PHASE 2, POP OFF THE TOP OF THE HEAP ONE AT A TIME (AND FIX) O(n log n) //=============================================================================== for (HeapSize=(mSize-1); HeapSize>0; HeapSize--) { // Swap The End And Front Of The "Heap" Half Of The Array //-------------------------------------------------------- mArray.swap(0, HeapSize); // We Now Have A Bogus Element At The Root, So Fix The Heap //---------------------------------------------------------- Pos = 0; Compare = largest_child(Pos, HeapSize); while (mArray[Pos]<mArray[Compare]) { // Swap The Compare Element With The Pos Element //----------------------------------------------- mArray.swap(Compare, Pos); // Move Pos To The Current Compare, And Recalc Compare //------------------------------------------------------ Pos = Compare; Compare = largest_child(Pos, HeapSize); } } } //////////////////////////////////////////////////////////////////////////////////// // THIS IS A QUICK VALIDATION OF A SORTED LIST //////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG void sort_validate() const { for (int a=0; a<(mSize-1); a++) { assert(mArray[a] < mArray[a+1]); } } #endif private: //////////////////////////////////////////////////////////////////////////////////// // For Heap Sort // Returns The Location Of Node (i)'s Parent Node (The Parent Node Of Zero Is Zero) //////////////////////////////////////////////////////////////////////////////////// static int parent(int i) { return ((i-1)/2); } //////////////////////////////////////////////////////////////////////////////////// // For Heap Sort // Returns The Location Of Node (i)'s Left Child (The Child Of A Leaf Is The Leaf) //////////////////////////////////////////////////////////////////////////////////// static int left(int i) { return ((2*i)+1); } //////////////////////////////////////////////////////////////////////////////////// // For Heap Sort // Returns The Location Of Node (i)'s Right Child (The Child Of A Leaf Is The Leaf) //////////////////////////////////////////////////////////////////////////////////// static int right(int i) { return ((2*i)+2); } //////////////////////////////////////////////////////////////////////////////////// // For Heap Sort // Returns The Location Of Largest Child Of Node (i) //////////////////////////////////////////////////////////////////////////////////// int largest_child(int i, int Size) const { if (left(i)<Size) { if (right(i)<Size) { return ( (mArray[right(i)] < mArray[left(i)]) ? (left(i)) : (right(i)) ); } return left(i); // Node i only has a left child, so by default it is the biggest } return i; // Node i is a leaf, so just return it } public: //////////////////////////////////////////////////////////////////////////////////// // Iterator //////////////////////////////////////////////////////////////////////////////////// class const_iterator; class iterator { friend class vector_base<T>; friend class const_iterator; // Data //------ int mLoc; vector_base<T>* mOwner; public: // Constructors //-------------- iterator() : mOwner(0), mLoc(0) {} iterator(vector_base<T>* p, int t) : mOwner(p), mLoc(t) {} iterator(const iterator &t) : mOwner(t.mOwner), mLoc(t.mLoc) {} // Assignment Operator //--------------------- void operator= (const iterator &t) { mOwner = t.mOwner; mLoc = t.mLoc; } // Equality Operators //-------------------- bool operator!=(const iterator &t) const { return (mLoc!=t.mLoc || mOwner!=t.mOwner); } bool operator==(const iterator &t) const { return (mLoc==t.mLoc && mOwner==t.mOwner); } // DeReference Operator //---------------------- TTValue& operator* () const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (mOwner->mArray[mLoc]); } // DeReference Operator //---------------------- TTValue& value() const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (mOwner->mArray[mLoc]); } // DeReference Operator //---------------------- TTValue* operator-> () const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (&mOwner->mArray[mLoc]); } // Inc Operator //-------------- iterator operator++(int) //postfix { assert(mLoc>=0 && mLoc<mOwner->mSize); iterator old(*this); mLoc ++; return old; } // Inc Operator //-------------- iterator operator++() { assert(mLoc>=0 && mLoc<mOwner->mSize); mLoc ++; return *this; } }; //////////////////////////////////////////////////////////////////////////////////// // Constant Iterator //////////////////////////////////////////////////////////////////////////////////// class const_iterator { friend class vector_base<T>; int mLoc; const vector_base<T>* mOwner; public: // Constructors //-------------- const_iterator() : mOwner(0), mLoc(0) {} const_iterator(const vector_base<T>* p, int t) : mOwner(p), mLoc(t) {} const_iterator(const const_iterator &t) : mOwner(t.mOwner), mLoc(t.mLoc) {} const_iterator(const iterator &t) : mOwner(t.mOwner), mLoc(t.mLoc) {} // Assignment Operator //--------------------- void operator= (const const_iterator &t) { mOwner = t.mOwner; mLoc = t.mLoc; } // Assignment Operator //--------------------- void operator= (const iterator &t) { mOwner = t.mOwner; mLoc = t.mLoc; } // Equality Operators //-------------------- bool operator!=(const iterator &t) const { return (mLoc!=t.mLoc || mOwner!=t.mOwner); } bool operator==(const iterator &t) const { return (mLoc==t.mLoc && mOwner==t.mOwner); } // Equality Operators //-------------------- bool operator!=(const const_iterator &t) const { return (mLoc!=t.mLoc || mOwner!=t.mOwner); } bool operator==(const const_iterator &t) const { return (mLoc==t.mLoc && mOwner==t.mOwner); } // DeReference Operator //---------------------- const TTValue& operator* () const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (mOwner->mArray[mLoc]); } // DeReference Operator //---------------------- const TTValue& value() const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (mOwner->mArray[mLoc]); } // DeReference Operator //---------------------- const TTValue* operator-> () const { assert(mLoc>=0 && mLoc<mOwner->mSize); return (&mOwner->mArray[mLoc]); } // Inc Operator //-------------- const_iterator operator++(int) { assert(mLoc>=0 && mLoc<mOwner->mSize); const_iterator old(*this); mLoc ++; return old; } // Inc Operator //-------------- const_iterator operator++() { assert(mLoc>=0 && mLoc<mOwner->mSize); mLoc ++; return *this; } }; friend class iterator; friend class const_iterator; //////////////////////////////////////////////////////////////////////////////////// // Iterator Begin (Starts At Address 0) //////////////////////////////////////////////////////////////////////////////////// iterator begin() { return iterator(this, 0); } //////////////////////////////////////////////////////////////////////////////////// // Iterator End (Set To Address mSize) //////////////////////////////////////////////////////////////////////////////////// iterator end() { return iterator(this, mSize); } //////////////////////////////////////////////////////////////////////////////////// // Iterator Begin (Starts At Address 0) //////////////////////////////////////////////////////////////////////////////////// const_iterator begin() const { return const_iterator(this, 0); } //////////////////////////////////////////////////////////////////////////////////// // Iterator End (Set To Address mSize) //////////////////////////////////////////////////////////////////////////////////// const_iterator end() const { return const_iterator(this, mSize); } //////////////////////////////////////////////////////////////////////////////////// // Iterator Find (If Fails To Find, Returns iterator end() //////////////////////////////////////////////////////////////////////////////////// iterator find(const TTValue& value) { int index = find_index(value); // Call Find By Index if (index<mSize) { return iterator(this, index); // Found It, Return An Iterator To Index } return end(); // Return "end" Iterator If Not Found } //////////////////////////////////////////////////////////////////////////////////// // Iterator Find (If Fails To Find, Returns iterator end() //////////////////////////////////////////////////////////////////////////////////// const_iterator find(const TTValue& value) const { int index = find_index(value); // Call Find By Index if (index<mSize) { return const_iterator(this, index); // Found It, Return An Iterator To Index } return end(); // Return "end" Iterator If Not Found } //////////////////////////////////////////////////////////////////////////////////// // Erase An Iterator Location... NOTE: THIS DOES NOT PRESERVE ORDER IN THE VECTOR!! //////////////////////////////////////////////////////////////////////////////////// iterator erase_swap(const iterator &it) { assert(it.mLoc>=0 && it.mLoc<it.mOwner->mSize); if (it.mLoc != mSize - 1) { mArray.swap(it.mLoc, mSize - 1); } pop_back(); return it; } template<class CAST_TO> CAST_TO *verify_alloc(CAST_TO *p) const { return mArray.verify_alloc(p); } }; template<class T, int ARG_CAPACITY> class vector_vs : public vector_base<storage::value_semantics<T,ARG_CAPACITY> > { public: typedef typename storage::value_semantics<T,ARG_CAPACITY> TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; vector_vs() {} }; template<class T, int ARG_CAPACITY> class vector_os : public vector_base<storage::object_semantics<T,ARG_CAPACITY> > { public: typedef typename storage::object_semantics<T,ARG_CAPACITY> TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; vector_os() {} }; template<class T, int ARG_CAPACITY, int ARG_MAX_CLASS_SIZE> class vector_is : public vector_base<storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> > { public: typedef typename storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; static const int MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE; vector_is() {} }; } #endif