/*==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 hsTempPointer_inc #define hsTempPointer_inc #include "hsMemory.h" #include "hsExceptions.h" template class hsTempPointer { private: T** fArray; UInt32 fCurrBlock; UInt32 fNumBlockAlloc; UInt32 fCurrElem; UInt32 fNumElemAlloc; UInt32 fGrowBy; // def = 0, to double UInt32 fMinSize; // def = 1 hsTempPointer& operator=(const hsTempPointer&); void IConsolidate(); void IGrow(); public: hsTempPointer(UInt32 minSize = 1, UInt32 growBy = 0); ~hsTempPointer(); void Reset(); T* Next(); T* Array(int n); }; template hsTempPointer::~hsTempPointer() { int i; for( i = 0; i <= fCurrBlock; i++ ) delete [] fArray[i]; delete [] fArray; } template hsTempPointer::hsTempPointer(UInt32 minSize, UInt32 growBy) { fGrowBy = growBy; fMinSize = minSize; fArray = TRACKED_NEW T*[2]; fNumBlockAlloc = 2; fCurrBlock = 0; fArray[fCurrBlock] = TRACKED_NEW T[fMinSize]; fNumElemAlloc = minSize; fCurrElem = 0; } template void hsTempPointer::IConsolidate() { hsAssert(fCurrBlock > 0, "Shouldn't consolidate when nothing to do"); UInt32 numUsed = fCurrBlock * fNumElemAlloc + fCurrElem; UInt32 newSize = fNumElemAlloc; if( !fGrowBy ) { while( newSize <= numUsed ) newSize <<= 1; } else { while( newSize <= numUsed ) newSize += fGrowBy; } int i; for( i = 0; i <= fCurrBlock; i++ ) delete [] fArray[i]; fArray[0] = TRACKED_NEW T[newSize]; fNumElemAlloc = newSize; fCurrElem = 0; fCurrBlock = 0; } template void hsTempPointer::IGrow() { if( ++fCurrBlock >= fNumBlockAlloc ) { T** newBlockArray = TRACKED_NEW T*[fNumBlockAlloc <<= 1]; HSMemory::BlockMove(fArray, newBlockArray, fCurrBlock * sizeof(*fArray)); delete [] fArray; fArray = newBlockArray; } fArray[fCurrBlock] = TRACKED_NEW T[fNumElemAlloc]; fCurrElem = 0; } template T* hsTempPointer::Next() { if( fCurrElem >= fNumElemAlloc ) IGrow(); return fArray[fCurrBlock] + fCurrElem++; } template T* hsTempPointer::Array(int n) { // minSize (on constructor) should be greater than max n hsDebugCode(hsThrowIfBadParam((UInt32)n > (UInt32)fNumElemAlloc);) if( fCurrElem + n >= fNumElemAlloc ) IGrow(); int idx = fCurrElem; fCurrElem += n; return fArray[fCurrBlock] + idx; } template void hsTempPointer::Reset() { if( fCurrBlock > 0 ) IConsolidate(); fCurrElem = 0; } #endif // hsTempPointer_inc