Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
6.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef UTLMAP_H
  9. #define UTLMAP_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/dbg.h"
  14. #include "utlrbtree.h"
  15. //-----------------------------------------------------------------------------
  16. //
  17. // Purpose: An associative container. Pretty much identical to std::map.
  18. //
  19. //-----------------------------------------------------------------------------
  20. // This is a useful macro to iterate from start to end in order in a map
  21. #define FOR_EACH_MAP( mapName, iteratorName ) \
  22. for ( int iteratorName = (mapName).FirstInorder(); (mapName).IsUtlMap && iteratorName != (mapName).InvalidIndex(); iteratorName = (mapName).NextInorder( iteratorName ) )
  23. // faster iteration, but in an unspecified order
  24. #define FOR_EACH_MAP_FAST( mapName, iteratorName ) \
  25. for ( int iteratorName = 0; (mapName).IsUtlMap && iteratorName < (mapName).MaxElement(); ++iteratorName ) if ( !(mapName).IsValidIndex( iteratorName ) ) continue; else
  26. struct base_utlmap_t
  27. {
  28. public:
  29. // This enum exists so that FOR_EACH_MAP and FOR_EACH_MAP_FAST cannot accidentally
  30. // be used on a type that is not a CUtlMap. If the code compiles then all is well.
  31. // The check for IsUtlMap being true should be free.
  32. // Using an enum rather than a static const bool ensures that this trick works even
  33. // with optimizations disabled on gcc.
  34. enum CompileTimeCheck
  35. {
  36. IsUtlMap = 1
  37. };
  38. };
  39. template <typename K, typename T, typename I = unsigned short>
  40. class CUtlMap : public base_utlmap_t
  41. {
  42. public:
  43. typedef K KeyType_t;
  44. typedef T ElemType_t;
  45. typedef I IndexType_t;
  46. // Less func typedef
  47. // Returns true if the first parameter is "less" than the second
  48. typedef bool (*LessFunc_t)( const KeyType_t &, const KeyType_t & );
  49. // constructor, destructor
  50. // Left at growSize = 0, the memory will first allocate 1 element and double in size
  51. // at each increment.
  52. // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
  53. CUtlMap( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 )
  54. : m_Tree( growSize, initSize, CKeyLess( lessfunc ) )
  55. {
  56. }
  57. CUtlMap( LessFunc_t lessfunc )
  58. : m_Tree( CKeyLess( lessfunc ) )
  59. {
  60. }
  61. void EnsureCapacity( int num ) { m_Tree.EnsureCapacity( num ); }
  62. // gets particular elements
  63. ElemType_t & Element( IndexType_t i ) { return m_Tree.Element( i ).elem; }
  64. const ElemType_t & Element( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
  65. ElemType_t & operator[]( IndexType_t i ) { return m_Tree.Element( i ).elem; }
  66. const ElemType_t & operator[]( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
  67. KeyType_t & Key( IndexType_t i ) { return m_Tree.Element( i ).key; }
  68. const KeyType_t & Key( IndexType_t i ) const { return m_Tree.Element( i ).key; }
  69. // Num elements
  70. unsigned int Count() const { return m_Tree.Count(); }
  71. // Max "size" of the vector
  72. IndexType_t MaxElement() const { return m_Tree.MaxElement(); }
  73. // Checks if a node is valid and in the map
  74. bool IsValidIndex( IndexType_t i ) const { return m_Tree.IsValidIndex( i ); }
  75. // Checks if the map as a whole is valid
  76. bool IsValid() const { return m_Tree.IsValid(); }
  77. // Invalid index
  78. static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); }
  79. // Sets the less func
  80. void SetLessFunc( LessFunc_t func )
  81. {
  82. m_Tree.SetLessFunc( CKeyLess( func ) );
  83. }
  84. // Insert method (inserts in order)
  85. IndexType_t Insert( const KeyType_t &key, const ElemType_t &insert )
  86. {
  87. Node_t node;
  88. node.key = key;
  89. node.elem = insert;
  90. return m_Tree.Insert( node );
  91. }
  92. IndexType_t Insert( const KeyType_t &key )
  93. {
  94. Node_t node;
  95. node.key = key;
  96. return m_Tree.Insert( node );
  97. }
  98. // Find method
  99. IndexType_t Find( const KeyType_t &key ) const
  100. {
  101. Node_t dummyNode;
  102. dummyNode.key = key;
  103. return m_Tree.Find( dummyNode );
  104. }
  105. // Remove methods
  106. void RemoveAt( IndexType_t i ) { m_Tree.RemoveAt( i ); }
  107. bool Remove( const KeyType_t &key )
  108. {
  109. Node_t dummyNode;
  110. dummyNode.key = key;
  111. return m_Tree.Remove( dummyNode );
  112. }
  113. void RemoveAll( ) { m_Tree.RemoveAll(); }
  114. void Purge( ) { m_Tree.Purge(); }
  115. // Purges the list and calls delete on each element in it.
  116. void PurgeAndDeleteElements();
  117. // Iteration
  118. IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); }
  119. IndexType_t NextInorder( IndexType_t i ) const { return m_Tree.NextInorder( i ); }
  120. IndexType_t PrevInorder( IndexType_t i ) const { return m_Tree.PrevInorder( i ); }
  121. IndexType_t LastInorder() const { return m_Tree.LastInorder(); }
  122. // If you change the search key, this can be used to reinsert the
  123. // element into the map.
  124. void Reinsert( const KeyType_t &key, IndexType_t i )
  125. {
  126. m_Tree[i].key = key;
  127. m_Tree.Reinsert(i);
  128. }
  129. IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert )
  130. {
  131. IndexType_t i = Find( key );
  132. if ( i != InvalidIndex() )
  133. {
  134. Element( i ) = insert;
  135. return i;
  136. }
  137. return Insert( key, insert );
  138. }
  139. void Swap( CUtlMap< K, T, I > &that )
  140. {
  141. m_Tree.Swap( that.m_Tree );
  142. }
  143. struct Node_t
  144. {
  145. Node_t()
  146. {
  147. }
  148. Node_t( const Node_t &from )
  149. : key( from.key ),
  150. elem( from.elem )
  151. {
  152. }
  153. KeyType_t key;
  154. ElemType_t elem;
  155. };
  156. class CKeyLess
  157. {
  158. public:
  159. CKeyLess( LessFunc_t lessFunc ) : m_LessFunc(lessFunc) {}
  160. bool operator!() const
  161. {
  162. return !m_LessFunc;
  163. }
  164. bool operator()( const Node_t &left, const Node_t &right ) const
  165. {
  166. return m_LessFunc( left.key, right.key );
  167. }
  168. LessFunc_t m_LessFunc;
  169. };
  170. typedef CUtlRBTree<Node_t, I, CKeyLess> CTree;
  171. CTree *AccessTree() { return &m_Tree; }
  172. protected:
  173. CTree m_Tree;
  174. };
  175. //-----------------------------------------------------------------------------
  176. // Purges the list and calls delete on each element in it.
  177. template< typename K, typename T, typename I >
  178. inline void CUtlMap<K, T, I>::PurgeAndDeleteElements()
  179. {
  180. for ( I i = 0; i < MaxElement(); ++i )
  181. {
  182. if ( !IsValidIndex( i ) )
  183. continue;
  184. delete Element( i );
  185. }
  186. Purge();
  187. }
  188. //-----------------------------------------------------------------------------
  189. // This is horrible and slow and meant to be used only when you're dealing with really
  190. // non-time/memory-critical code and desperately want to copy a whole map element-by-element
  191. // for whatever reason.
  192. template < typename K, typename T, typename I >
  193. void DeepCopyMap( const CUtlMap<K,T,I>& pmapIn, CUtlMap<K,T,I> *out_pmapOut )
  194. {
  195. Assert( out_pmapOut );
  196. out_pmapOut->Purge();
  197. FOR_EACH_MAP_FAST( pmapIn, i )
  198. {
  199. out_pmapOut->Insert( pmapIn.Key( i ), pmapIn.Element( i ) );
  200. }
  201. }
  202. #endif // UTLMAP_H