/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #ifndef hsBiExpander_inc #define hsBiExpander_inc #include "hsMemory.h" #include "hsTemplates.h" /////////////////////////////////////////////////////////////////////////////// ////////////// Expander /////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template class hsExpander { private: Int32 fNumPost; Int32 fNumPostAlloc; T* fArray; Int32 fGrowBy; // default = 0, to double Int32 fMinSize; // default = 1, min == 1 Int32 fCurrent; hsExpander(const hsExpander& x); // make it passed as ref or pointer void IExpand(int newSize); public: enum { kMissingIndex = -1 }; hsExpander(Int32 minSize = 1, Int32 growBy = 0); virtual ~hsExpander(); hsExpander& operator=(const hsExpander&orig) { return Copy(orig); } hsExpander& Copy(const hsExpander& orig); void SetCount(int cnt) { if( cnt >= fNumPostAlloc )IExpand(cnt); fNumPost = cnt; } Int32 GetCount() const { return fNumPost; } hsBool Empty() const { return GetCount() == 0; } const T& Get(Int32 index) const; Int32 Get(Int32 index, Int32 count, T data[]) const; Int32 Find(const T&) const; // returns kMissingIndex if not found void SetArray(T* a, Int32 cnt); T* GetArray() { return fArray; } T& operator[]( Int32 index ); Int32 Append(const T&); // returns t's index T* Append(); Int32 Push(const T& t) { return Append(t); } T* Push() { return Append(); } T* Top() { return fNumPost ? fArray + fNumPost-1 : nil; } Int32 Pop(T* t); // returns count of remaining Int32 Pop(); void Reset(); // clears out everything T& Head() { return fArray[0]; } T& Tail() { return fArray[fNumPost-1]; } T& Current() { return fArray[fCurrent]; } void First(); void Last(); void Plus() { ++fCurrent; } hsBool More() { return (fCurrent < fNumPost); } }; template hsExpander& hsExpander::Copy(const hsExpander& orig) { SetCount(orig.GetCount()); int i; for( i = 0; i < GetCount(); i++ ) fArray[i] = orig.fArray[i]; return *this; } template void hsExpander::SetArray(T* a, Int32 cnt) { delete [] fArray; if( a ) fArray = a; fNumPost = fNumPostAlloc = cnt; } template void hsExpander::IExpand(int newSize) { Int32 newPostAlloc = fNumPostAlloc; if( !newPostAlloc ) newPostAlloc++; while( newPostAlloc <= newSize ) newPostAlloc = fGrowBy ? newPostAlloc + fGrowBy : newPostAlloc << 1; T* newArray = TRACKED_NEW T[newPostAlloc]; int i; for( i = 0; i < fNumPost; i++ ) newArray[i] = fArray[i]; delete [] (fArray); fArray = newArray; fNumPostAlloc = newPostAlloc; } template hsExpander::hsExpander(Int32 minSize, Int32 growBy) { hsThrowIfBadParam(minSize < 0); hsThrowIfBadParam(growBy < 0); fMinSize = minSize+1; fGrowBy = growBy; fArray = TRACKED_NEW T[fMinSize]; fNumPostAlloc = fMinSize; fNumPost = 0; } template hsExpander::~hsExpander() { delete [] fArray; } template void hsExpander::First() { fCurrent = 0; } template void hsExpander::Last() { fCurrent = fNumPost-1; } template T& hsExpander::operator[]( Int32 index ) { hsDebugCode(hsThrowIfBadParam((index < 0)||(index >= fNumPost));) return fArray[index]; } template const T& hsExpander::Get( Int32 index ) const { hsDebugCode(hsThrowIfBadParam((index < 0)||(index >= fNumPost));) return fArray[index]; } template Int32 hsExpander::Get(Int32 index, Int32 count, T data[]) const { if( count > 0 ) { hsThrowIfNilParam(data); hsThrowIfBadParam((index < 0)||(index >= fNumPost)); if (index + count > fNumPost) count = fNumPost - index; for (int i = 0; i < count; i++) data[i] = fArray[i + index]; } return count; } template Int32 hsExpander::Find(const T& obj) const { for (int i = 0; i < fNumPost; i++) if (fArray[i] == obj) return i; return kMissingIndex; } template Int32 hsExpander::Append(const T& obj) { hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less"); if( fNumPost == fNumPostAlloc-1 ) IExpand(fNumPostAlloc); fArray[fNumPost] = obj; return fNumPost++; } template T* hsExpander::Append() { hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less"); if( fNumPost == fNumPostAlloc-1 ) IExpand(fNumPostAlloc); return fArray + fNumPost++; } template Int32 hsExpander::Pop(T*t) { hsThrowIfBadParam(Empty()); --fNumPost; if( t ) *t = fArray[fNumPost]; return GetCount(); } template Int32 hsExpander::Pop() { hsThrowIfBadParam(Empty()); --fNumPost; return GetCount(); } template void hsExpander::Reset() { fNumPost = 0; } /////////////////////////////////////////////////////////////////////////////// ////////////// BiExpander ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template class hsBiExpander { private: Int32 fNumPre; Int32 fNumPost; Int32 fNumPreAlloc; Int32 fNumPostAlloc; T* fArray; Int32 fGrowBy; // default = 0, to double Int32 fMinSize; // default = 1, min == 1 Int32 fCurrent; hsBiExpander& operator=(const hsBiExpander&); // don't allow assignment hsBiExpander(const hsBiExpander&); // make it passed as ref or pointer void IExpand(int newSize, hsBool towardEnd = true); public: enum { kMissingIndex = -1 }; hsBiExpander(Int32 minSize = 1, Int32 growBy = 0); virtual ~hsBiExpander(); Int32 GetFirst() const { return -fNumPre; } Int32 GetCount() const { return fNumPre + fNumPost; } hsBool Empty() const { return GetCount() == 0; } const T& Get(Int32 index) const; Int32 Get(Int32 index, Int32 count, T data[]) const; Int32 Find(const T&) const; // returns kMissingIndex if not found void SetArray(T* a, Int32 cnt, Int32 numPre=0); T** GetArray() { return fArray - fNumPre; } T& operator[]( Int32 index ); T* Append(); // returns t's index T* Push(); // returns t's index Int32 Append(const T&); // returns t's index Int32 Push(const T&); // returns t's index Int32 Pop(T*t = nil) { return PopHead(t); } // returns count of remaining Int32 PopHead(T*t = nil); // returns count of remaining Int32 PopTail(T*t = nil); // returns count of remaining void Reset(); // clears out everything T& Head() { return fArray[-fNumPre]; } T& Tail() { return fArray[fNumPost-1]; } T& Current() { return fArray[fCurrent]; } void First(); void Last(); void Plus() { ++fCurrent; } void Minus() { --fCurrent; } hsBool More() { return (fCurrent < fNumPost)&&(fCurrent >= -fNumPre); } }; template void hsBiExpander::SetArray(T* a, Int32 cnt, Int32 numPre) { if( !numPre ) Reset(); else { fNumPreAlloc = fNumPre = numPre; fNumPostAlloc = fNumPost = cnt - numPre; fArray = a + numPre; } } template void hsBiExpander::IExpand(int newSize, hsBool towardEnd) { Int32 newPreAlloc = fNumPreAlloc; Int32 newPostAlloc = fNumPostAlloc; if( towardEnd ) { if( !newPostAlloc ) newPostAlloc++; while( newPostAlloc <= newSize ) newPostAlloc = fGrowBy ? newPostAlloc + fGrowBy : newPostAlloc << 1; } else { if( !newPreAlloc ) newPreAlloc++; while( newPreAlloc <= newSize ) newPreAlloc = fGrowBy ? newPreAlloc + fGrowBy : newPreAlloc << 1; } T* newArray = TRACKED_NEW T[newPreAlloc + newPostAlloc]; newArray += newPreAlloc; int i; for( i = -fNumPre; i < fNumPost; i++ ) newArray[i] = fArray[i]; // HSMemory::BlockMove(fArray-fNumPre, newArray-fNumPre, // (fNumPre+fNumPost)*sizeof(*fArray)); delete [] (fArray-fNumPreAlloc); fArray = newArray; fNumPreAlloc = newPreAlloc; fNumPostAlloc = newPostAlloc; } template hsBiExpander::hsBiExpander(Int32 minSize, Int32 growBy) { hsThrowIfBadParam(minSize < 0); hsThrowIfBadParam(growBy < 0); fMinSize = minSize+1; fGrowBy = growBy; fArray = TRACKED_NEW T[fMinSize << 1]; fNumPreAlloc = fNumPostAlloc = fMinSize; fArray += fNumPreAlloc; fNumPre = fNumPost = 0; } template hsBiExpander::~hsBiExpander() { delete [] (fArray - fNumPreAlloc); } template void hsBiExpander::First() { fCurrent = -fNumPre; } template void hsBiExpander::Last() { fCurrent = fNumPost-1; } template T& hsBiExpander::operator[]( Int32 index ) { hsDebugCode(hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost));) return fArray[index]; } template const T& hsBiExpander::Get( Int32 index ) const { hsDebugCode(hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost));) return fArray[index]; } template Int32 hsBiExpander::Get(Int32 index, Int32 count, T data[]) const { if( count > 0 ) { hsThrowIfNilParam(data); hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost)); if (index + count > fNumPost) count = fNumPost - index; for (int i = 0; i < count; i++) data[i] = fArray[i + index]; } return count; } template Int32 hsBiExpander::Find(const T& obj) const { for (int i = -fNumPre; i < fNumPost; i++) if (fArray[i] == obj) return i; return kMissingIndex; } template T* hsBiExpander::Append() { hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less"); if( fNumPost == fNumPostAlloc-1 ) IExpand(fNumPostAlloc, true); return fArray + fNumPost++; } template T* hsBiExpander::Push() { hsAssert(!(fNumPre >= fNumPreAlloc), "Must be less"); if( ++fNumPre == fNumPreAlloc ) IExpand(fNumPreAlloc, false); return fArray - fNumPre; } template Int32 hsBiExpander::Append(const T& obj) { hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less"); if( fNumPost == fNumPostAlloc-1 ) IExpand(fNumPostAlloc, true); fArray[fNumPost] = obj; return fNumPost++; } template Int32 hsBiExpander::Push(const T& obj) { hsAssert(!(fNumPre >= fNumPreAlloc), "Must be less"); if( ++fNumPre == fNumPreAlloc ) IExpand(fNumPreAlloc, false); fArray[-fNumPre] = obj; return -fNumPre; } template Int32 hsBiExpander::PopHead(T*t) { hsThrowIfBadParam(Empty()); if( t ) *t = fArray[-fNumPre]; --fNumPre; return GetCount(); } template Int32 hsBiExpander::PopTail(T*t) { hsThrowIfBadParam(Empty()); --fNumPost; if( t ) *t = fArray[fNumPost]; return GetCount(); } template void hsBiExpander::Reset() { fNumPre = fNumPost = 0; } #endif // hsBiExpander_inc