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.

248 lines
6.4 KiB

  1. //========= Copyright � 1996-2005, 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. static const bool IsUtlMap = true; // Used to match this at compiletime
  30. };
  31. #if defined( GNUC ) && defined( DEBUG )
  32. const bool base_utlmap_t::IsUtlMap SELECTANY;
  33. #endif
  34. template <typename K, typename T, typename I = unsigned short>
  35. class CUtlMap : public base_utlmap_t
  36. {
  37. public:
  38. typedef K KeyType_t;
  39. typedef T ElemType_t;
  40. typedef I IndexType_t;
  41. // Less func typedef
  42. // Returns true if the first parameter is "less" than the second
  43. typedef bool (*LessFunc_t)( const KeyType_t &, const KeyType_t & );
  44. // constructor, destructor
  45. // Left at growSize = 0, the memory will first allocate 1 element and double in size
  46. // at each increment.
  47. // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
  48. CUtlMap( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 )
  49. : m_Tree( growSize, initSize, CKeyLess( lessfunc ) )
  50. {
  51. }
  52. CUtlMap( LessFunc_t lessfunc )
  53. : m_Tree( CKeyLess( lessfunc ) )
  54. {
  55. }
  56. void EnsureCapacity( int num ) { m_Tree.EnsureCapacity( num ); }
  57. // gets particular elements
  58. ElemType_t & Element( IndexType_t i ) { return m_Tree.Element( i ).elem; }
  59. const ElemType_t & Element( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
  60. ElemType_t & operator[]( IndexType_t i ) { return m_Tree.Element( i ).elem; }
  61. const ElemType_t & operator[]( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
  62. KeyType_t & Key( IndexType_t i ) { return m_Tree.Element( i ).key; }
  63. const KeyType_t & Key( IndexType_t i ) const { return m_Tree.Element( i ).key; }
  64. // Num elements
  65. unsigned int Count() const { return m_Tree.Count(); }
  66. // Max "size" of the vector
  67. IndexType_t MaxElement() const { return m_Tree.MaxElement(); }
  68. // Checks if a node is valid and in the map
  69. bool IsValidIndex( IndexType_t i ) const { return m_Tree.IsValidIndex( i ); }
  70. // Checks if the map as a whole is valid
  71. bool IsValid() const { return m_Tree.IsValid(); }
  72. // Invalid index
  73. static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); }
  74. // Sets the less func
  75. void SetLessFunc( LessFunc_t func )
  76. {
  77. m_Tree.SetLessFunc( CKeyLess( func ) );
  78. }
  79. // Insert method (inserts in order)
  80. IndexType_t Insert( const KeyType_t &key, const ElemType_t &insert )
  81. {
  82. Node_t node;
  83. node.key = key;
  84. node.elem = insert;
  85. return m_Tree.Insert( node );
  86. }
  87. IndexType_t Insert( const KeyType_t &key )
  88. {
  89. Node_t node;
  90. node.key = key;
  91. return m_Tree.Insert( node );
  92. }
  93. // Find method
  94. IndexType_t Find( const KeyType_t &key ) const
  95. {
  96. Node_t dummyNode;
  97. dummyNode.key = key;
  98. return m_Tree.Find( dummyNode );
  99. }
  100. // Remove methods
  101. void RemoveAt( IndexType_t i ) { m_Tree.RemoveAt( i ); }
  102. bool Remove( const KeyType_t &key )
  103. {
  104. Node_t dummyNode;
  105. dummyNode.key = key;
  106. return m_Tree.Remove( dummyNode );
  107. }
  108. void RemoveAll( ) { m_Tree.RemoveAll(); }
  109. void Purge( ) { m_Tree.Purge(); }
  110. // Purges the list and calls delete on each element in it.
  111. void PurgeAndDeleteElements();
  112. // Iteration
  113. IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); }
  114. IndexType_t NextInorder( IndexType_t i ) const { return m_Tree.NextInorder( i ); }
  115. IndexType_t PrevInorder( IndexType_t i ) const { return m_Tree.PrevInorder( i ); }
  116. IndexType_t LastInorder() const { return m_Tree.LastInorder(); }
  117. // If you change the search key, this can be used to reinsert the
  118. // element into the map.
  119. void Reinsert( const KeyType_t &key, IndexType_t i )
  120. {
  121. m_Tree[i].key = key;
  122. m_Tree.Reinsert(i);
  123. }
  124. IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert )
  125. {
  126. IndexType_t i = Find( key );
  127. if ( i != InvalidIndex() )
  128. {
  129. Element( i ) = insert;
  130. return i;
  131. }
  132. return Insert( key, insert );
  133. }
  134. void Swap( CUtlMap< K, T, I > &that )
  135. {
  136. m_Tree.Swap( that.m_Tree );
  137. }
  138. struct Node_t
  139. {
  140. Node_t()
  141. {
  142. }
  143. Node_t( const Node_t &from )
  144. : key( from.key ),
  145. elem( from.elem )
  146. {
  147. }
  148. KeyType_t key;
  149. ElemType_t elem;
  150. };
  151. class CKeyLess
  152. {
  153. public:
  154. CKeyLess( LessFunc_t lessFunc ) : m_LessFunc(lessFunc) {}
  155. bool operator!() const
  156. {
  157. return !m_LessFunc;
  158. }
  159. bool operator()( const Node_t &left, const Node_t &right ) const
  160. {
  161. return m_LessFunc( left.key, right.key );
  162. }
  163. LessFunc_t m_LessFunc;
  164. };
  165. typedef CUtlRBTree<Node_t, I, CKeyLess> CTree;
  166. CTree *AccessTree() { return &m_Tree; }
  167. protected:
  168. CTree m_Tree;
  169. };
  170. //-----------------------------------------------------------------------------
  171. // Purges the list and calls delete on each element in it.
  172. template< typename K, typename T, typename I >
  173. inline void CUtlMap<K, T, I>::PurgeAndDeleteElements()
  174. {
  175. for ( I i = 0; i < MaxElement(); ++i )
  176. {
  177. if ( !IsValidIndex( i ) )
  178. continue;
  179. delete Element( i );
  180. }
  181. Purge();
  182. }
  183. //-----------------------------------------------------------------------------
  184. // This is horrible and slow and meant to be used only when you're dealing with really
  185. // non-time/memory-critical code and desperately want to copy a whole map element-by-element
  186. // for whatever reason.
  187. template < typename K, typename T, typename I >
  188. void DeepCopyMap( const CUtlMap<K,T,I>& pmapIn, CUtlMap<K,T,I> *out_pmapOut )
  189. {
  190. Assert( out_pmapOut );
  191. out_pmapOut->Purge();
  192. FOR_EACH_MAP_FAST( pmapIn, i )
  193. {
  194. out_pmapOut->Insert( i, pmapIn[i] );
  195. }
  196. }
  197. #endif // UTLMAP_H