123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Contains a simple container class.
- * \file IceContainer.h
- * \author Pierre Terdiman
- * \date February, 5, 2000
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Include Guard
- #ifndef __ICECONTAINER_H__
- #define __ICECONTAINER_H__
- #define CONTAINER_STATS
- enum FindMode
- {
- FIND_CLAMP,
- FIND_WRAP,
- FIND_FORCE_DWORD = 0x7fffffff
- };
- class ICECORE_API OPC_Container
- {
- public:
- // Constructor / Destructor
- OPC_Container();
- OPC_Container(const OPC_Container& object);
- OPC_Container(udword size, float growth_factor);
- ~OPC_Container();
- // Management
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * A O(1) method to add a value in the container. The container is automatically resized if needed.
- * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
- * costs a lot more than the call overhead...
- *
- * \param entry [in] a udword to store in the container
- * \see Add(float entry)
- * \see Empty()
- * \see Contains(udword entry)
- * \return Self-Reference
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ OPC_Container& Add(udword entry)
- {
- // Resize if needed
- if(mCurNbEntries==mMaxNbEntries) Resize();
- // Add new entry
- mEntries[mCurNbEntries++] = entry;
- return *this;
- }
- inline_ OPC_Container& Add(const udword* entries, udword nb)
- {
- // Resize if needed
- if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
- // Add new entry
- CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
- mCurNbEntries+=nb;
- return *this;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * A O(1) method to add a value in the container. The container is automatically resized if needed.
- * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
- * costs a lot more than the call overhead...
- *
- * \param entry [in] a float to store in the container
- * \see Add(udword entry)
- * \see Empty()
- * \see Contains(udword entry)
- * \return Self-Reference
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ OPC_Container& Add(float entry)
- {
- // Resize if needed
- if(mCurNbEntries==mMaxNbEntries) Resize();
- // Add new entry
- mEntries[mCurNbEntries++] = IR(entry);
- return *this;
- }
- inline_ OPC_Container& Add(const float* entries, udword nb)
- {
- // Resize if needed
- if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
- // Add new entry
- CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
- mCurNbEntries+=nb;
- return *this;
- }
- //! Add unique [slow]
- inline_ OPC_Container& AddUnique(udword entry)
- {
- if(!Contains(entry)) Add(entry);
- return *this;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Clears the container. All stored values are deleted, and it frees used ram.
- * \see Reset()
- * \return Self-Reference
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- OPC_Container& Empty();
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
- * That's a kind of temporal coherence.
- * \see Empty()
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ void Reset()
- {
- // Avoid the write if possible
- // ### CMOV
- if(mCurNbEntries) mCurNbEntries = 0;
- }
- // HANDLE WITH CARE
- inline_ void ForceSize(udword size)
- {
- mCurNbEntries = size;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Sets the initial size of the container. If it already contains something, it's discarded.
- * \param nb [in] Number of entries
- * \return true if success
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- bool SetSize(udword nb);
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Refits the container and get rid of unused bytes.
- * \return true if success
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- bool Refit();
- // Checks whether the container already contains a given value.
- bool Contains(udword entry, udword* location=null) const;
- // Deletes an entry - doesn't preserve insertion order.
- bool Delete(udword entry);
- // Deletes an entry - does preserve insertion order.
- bool DeleteKeepingOrder(udword entry);
- //! Deletes the very last entry.
- inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; }
- //! Deletes the entry whose index is given
- inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; }
- // Helpers
- OPC_Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
- OPC_Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
- // Data access.
- inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries.
- inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry
- inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries.
- inline_ udword GetFirst() const { return mEntries[0]; }
- inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; }
- // Growth control
- inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor
- inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor
- inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full
- inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty
- //! Read-access as an array
- inline_ udword operator[](udword i) const { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
- //! Write-access as an array
- inline_ udword& operator[](udword i) { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
- // Stats
- udword GetUsedRam() const;
- //! Operator for "OPC_Container A = OPC_Container B"
- void operator = (const OPC_Container& object);
- #ifdef CONTAINER_STATS
- inline_ udword GetNbContainers() const { return mNbContainers; }
- inline_ udword GetTotalBytes() const { return mUsedRam; }
- private:
- static udword mNbContainers; //!< Number of containers around
- static udword mUsedRam; //!< Amount of bytes used by containers in the system
- #endif
- private:
- // Resizing
- bool Resize(udword needed=1);
- // Data
- udword mMaxNbEntries; //!< Maximum possible number of entries
- udword mCurNbEntries; //!< Current number of entries
- udword* mEntries; //!< List of entries
- float mGrowthFactor; //!< Resize: new number of entries = old number * mGrowthFactor
- };
- #endif // __ICECONTAINER_H__
|