/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a simple container class. * \file IceContainer.cpp * \author Pierre Terdiman * \date February, 5, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a list of 32-bits values. * Use this class when you need to store an unknown number of values. The list is automatically * resized and can contains 32-bits entities (dwords or floats) * * \class Container * \author Pierre Terdiman * \version 1.0 * \date 08.15.98 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "StdAfx.h" using namespace Opcode; // Static members #ifdef CONTAINER_STATS udword Container::mNbContainers = 0; udword Container::mUsedRam = 0; LinkedList Container::mContainers; #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. No entries allocated there. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) { #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); mContainers.AddElem(this); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. Also allocates a given number of entries. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null) { SetGrowthFactor(growth_factor); #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); mContainers.AddElem(this); #endif SetSize(size); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Copy constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) { #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); mContainers.AddElem(this); #endif *this = object; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. Frees everything and leaves. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::~Container() { Empty(); #ifdef CONTAINER_STATS mNbContainers--; mUsedRam-=GetUsedRam(); mContainers.RemElem(this); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled. * \param max_entries [in] max number of entries in the container * \param entries [in] external memory buffer */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Container::InitSharedBuffers(udword max_entries, udword* entries) { Empty(); // Make sure everything has been released mMaxNbEntries = max_entries; mEntries = entries; mGrowthFactor = -1.0f; // Negative growth ==> resize is disabled } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Clears the container. All stored values are deleted, and it frees used ram. * \see Reset() * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container& Container::Empty() { #ifdef CONTAINER_STATS mUsedRam-=mMaxNbEntries*sizeof(udword); #endif if(mGrowthFactor>=0.0f) ICE_FREE(mEntries); // Release memory if we own it mCurNbEntries = mMaxNbEntries = 0; return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Resizes the container. * \param needed [in] assume the container can be added at least "needed" values * \return true if success. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::Resize(udword needed) { // Check growth is allowed if(mGrowthFactor<=0.0f) { ASSERT(!"Invalid operation - trying to resize a static buffer!"); return false; } #ifdef CONTAINER_STATS // Subtract previous amount of bytes mUsedRam-=mMaxNbEntries*sizeof(udword); #endif // Get more entries mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 if(mMaxNbEntriesshrink(mEntries, sizeof(udword)*mCurNbEntries)) return false; #ifdef CONTAINER_STATS // Subtract previous amount of bytes mUsedRam-=mMaxNbEntries*sizeof(udword); #endif // Get just enough entries mMaxNbEntries = mCurNbEntries; #ifdef CONTAINER_STATS // Add current amount of bytes mUsedRam+=mMaxNbEntries*sizeof(udword); #endif return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the container already contains a given value. * \param entry [in] the value to look for in the container * \param location [out] a possible pointer to store the entry location * \see Add(udword entry) * \see Add(float entry) * \see Empty() * \return true if the value has been found in the container, else false. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::Contains(udword entry, udword* location) const { // Look for the entry for(udword i=0;i