IceContainer.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /**
  3. * Contains a simple container class.
  4. * \file IceContainer.h
  5. * \author Pierre Terdiman
  6. * \date February, 5, 2000
  7. */
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. // Include Guard
  11. #ifndef __ICECONTAINER_H__
  12. #define __ICECONTAINER_H__
  13. #define CONTAINER_STATS
  14. enum FindMode
  15. {
  16. FIND_CLAMP,
  17. FIND_WRAP,
  18. FIND_FORCE_DWORD = 0x7fffffff
  19. };
  20. class ICECORE_API OPC_Container
  21. {
  22. public:
  23. // Constructor / Destructor
  24. OPC_Container();
  25. OPC_Container(const OPC_Container& object);
  26. OPC_Container(udword size, float growth_factor);
  27. ~OPC_Container();
  28. // Management
  29. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  30. /**
  31. * A O(1) method to add a value in the container. The container is automatically resized if needed.
  32. * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
  33. * costs a lot more than the call overhead...
  34. *
  35. * \param entry [in] a udword to store in the container
  36. * \see Add(float entry)
  37. * \see Empty()
  38. * \see Contains(udword entry)
  39. * \return Self-Reference
  40. */
  41. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  42. inline_ OPC_Container& Add(udword entry)
  43. {
  44. // Resize if needed
  45. if(mCurNbEntries==mMaxNbEntries) Resize();
  46. // Add new entry
  47. mEntries[mCurNbEntries++] = entry;
  48. return *this;
  49. }
  50. inline_ OPC_Container& Add(const udword* entries, udword nb)
  51. {
  52. // Resize if needed
  53. if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
  54. // Add new entry
  55. CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
  56. mCurNbEntries+=nb;
  57. return *this;
  58. }
  59. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. /**
  61. * A O(1) method to add a value in the container. The container is automatically resized if needed.
  62. * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
  63. * costs a lot more than the call overhead...
  64. *
  65. * \param entry [in] a float to store in the container
  66. * \see Add(udword entry)
  67. * \see Empty()
  68. * \see Contains(udword entry)
  69. * \return Self-Reference
  70. */
  71. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. inline_ OPC_Container& Add(float entry)
  73. {
  74. // Resize if needed
  75. if(mCurNbEntries==mMaxNbEntries) Resize();
  76. // Add new entry
  77. mEntries[mCurNbEntries++] = IR(entry);
  78. return *this;
  79. }
  80. inline_ OPC_Container& Add(const float* entries, udword nb)
  81. {
  82. // Resize if needed
  83. if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
  84. // Add new entry
  85. CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
  86. mCurNbEntries+=nb;
  87. return *this;
  88. }
  89. //! Add unique [slow]
  90. inline_ OPC_Container& AddUnique(udword entry)
  91. {
  92. if(!Contains(entry)) Add(entry);
  93. return *this;
  94. }
  95. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. /**
  97. * Clears the container. All stored values are deleted, and it frees used ram.
  98. * \see Reset()
  99. * \return Self-Reference
  100. */
  101. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. OPC_Container& Empty();
  103. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  104. /**
  105. * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
  106. * That's a kind of temporal coherence.
  107. * \see Empty()
  108. */
  109. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  110. inline_ void Reset()
  111. {
  112. // Avoid the write if possible
  113. // ### CMOV
  114. if(mCurNbEntries) mCurNbEntries = 0;
  115. }
  116. // HANDLE WITH CARE
  117. inline_ void ForceSize(udword size)
  118. {
  119. mCurNbEntries = size;
  120. }
  121. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. /**
  123. * Sets the initial size of the container. If it already contains something, it's discarded.
  124. * \param nb [in] Number of entries
  125. * \return true if success
  126. */
  127. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. bool SetSize(udword nb);
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. /**
  131. * Refits the container and get rid of unused bytes.
  132. * \return true if success
  133. */
  134. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. bool Refit();
  136. // Checks whether the container already contains a given value.
  137. bool Contains(udword entry, udword* location=null) const;
  138. // Deletes an entry - doesn't preserve insertion order.
  139. bool Delete(udword entry);
  140. // Deletes an entry - does preserve insertion order.
  141. bool DeleteKeepingOrder(udword entry);
  142. //! Deletes the very last entry.
  143. inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; }
  144. //! Deletes the entry whose index is given
  145. inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; }
  146. // Helpers
  147. OPC_Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
  148. OPC_Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
  149. // Data access.
  150. inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries.
  151. inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry
  152. inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries.
  153. inline_ udword GetFirst() const { return mEntries[0]; }
  154. inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; }
  155. // Growth control
  156. inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor
  157. inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor
  158. inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full
  159. inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty
  160. //! Read-access as an array
  161. inline_ udword operator[](udword i) const { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
  162. //! Write-access as an array
  163. inline_ udword& operator[](udword i) { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
  164. // Stats
  165. udword GetUsedRam() const;
  166. //! Operator for "OPC_Container A = OPC_Container B"
  167. void operator = (const OPC_Container& object);
  168. #ifdef CONTAINER_STATS
  169. inline_ udword GetNbContainers() const { return mNbContainers; }
  170. inline_ udword GetTotalBytes() const { return mUsedRam; }
  171. private:
  172. static udword mNbContainers; //!< Number of containers around
  173. static udword mUsedRam; //!< Amount of bytes used by containers in the system
  174. #endif
  175. private:
  176. // Resizing
  177. bool Resize(udword needed=1);
  178. // Data
  179. udword mMaxNbEntries; //!< Maximum possible number of entries
  180. udword mCurNbEntries; //!< Current number of entries
  181. udword* mEntries; //!< List of entries
  182. float mGrowthFactor; //!< Resize: new number of entries = old number * mGrowthFactor
  183. };
  184. #endif // __ICECONTAINER_H__