diff options
Diffstat (limited to 'libs/ode-0.16.1/OPCODE/Ice/IceContainer.h')
-rw-r--r-- | libs/ode-0.16.1/OPCODE/Ice/IceContainer.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/libs/ode-0.16.1/OPCODE/Ice/IceContainer.h b/libs/ode-0.16.1/OPCODE/Ice/IceContainer.h new file mode 100644 index 0000000..2c3c597 --- /dev/null +++ b/libs/ode-0.16.1/OPCODE/Ice/IceContainer.h @@ -0,0 +1,243 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 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 Container + { + public: + // Constructor / Destructor + Container(); + Container(const Container& object); + Container(udword size, float growth_factor); + ~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_ Container& Add(udword entry) + { + // Resize if needed + if (mCurNbEntries == mMaxNbEntries + && !Resize()) + { + IceAbort(); + } + + // Add new entry + mEntries[mCurNbEntries++] = entry; + return *this; + } + + inline_ Container& Add(const uword* entries, udword nb) + { + // Resize if needed + if (mCurNbEntries + nb > mMaxNbEntries + && !Resize(nb)) + { + IceAbort(); + } + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(uword)); + mCurNbEntries+=nb; + return *this; + } + + inline_ Container& Add(const udword* entries, udword nb) + { + // Resize if needed + if (mCurNbEntries + nb > mMaxNbEntries + && !Resize(nb)) + { + IceAbort(); + } + + // 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_ Container& Add(float entry) + { + // Resize if needed + if (mCurNbEntries == mMaxNbEntries + && !Resize()) + { + IceAbort(); + } + + // Add new entry + mEntries[mCurNbEntries++] = IR(entry); + return *this; + } + + inline_ Container& Add(const float* entries, udword nb) + { + // Resize if needed + if (mCurNbEntries + nb > mMaxNbEntries + && !Resize(nb)) + { + IceAbort(); + } + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); + mCurNbEntries+=nb; + return *this; + } + + //! Add unique [slow] + inline_ 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 + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + 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) { ASSERT(index < mCurNbEntries); mEntries[index] = mEntries[--mCurNbEntries]; } + + // Helpers + Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); + 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_ udword GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor + inline_ void SetGrowthFactor(udword 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 "Container A = Container B" + //void operator = (const 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 + udword mGrowthFactor; //!< Resize: new number of entries = old number * mGrowthFactor + }; + +#endif // __ICECONTAINER_H__ |