Counter Strike : Global Offensive Source Code
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.

277 lines
7.4 KiB

  1. //====== Copyright � 1996-2007, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "mdllib_utils.h"
  7. //////////////////////////////////////////////////////////////////////////
  8. //
  9. // CInsertionTracker implementation
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. void CInsertionTracker::InsertBytes( void *pos, int length )
  13. {
  14. if ( length <= 0 )
  15. return;
  16. Assert( m_map.InvalidIndex() == m_map.Find( ( byte * ) pos ) );
  17. m_map.InsertOrReplace( ( byte * ) pos, length );
  18. }
  19. int CInsertionTracker::GetNumBytesInserted() const
  20. {
  21. int iInserted = 0;
  22. for ( Map::IndexType_t idx = m_map.FirstInorder();
  23. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  24. {
  25. int numBytes = m_map.Element( idx );
  26. iInserted += numBytes;
  27. }
  28. return iInserted;
  29. }
  30. void CInsertionTracker::Finalize()
  31. {
  32. // Iterate the map and find all the adjacent removal data blocks
  33. // TODO:
  34. }
  35. void CInsertionTracker::MemMove( void *ptrBase, int &length ) const
  36. {
  37. int numBytesInsertReq = GetNumBytesInserted();
  38. byte *pbBlockEnd = BYTE_OFF_PTR( ptrBase, length );
  39. length += numBytesInsertReq;
  40. for ( Map::IndexType_t idx = m_map.LastInorder();
  41. idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
  42. {
  43. byte *ptr = m_map.Key( idx );
  44. int numBytes = m_map.Element( idx );
  45. // Move [ptr, pbBlockEnd) ->> + numBytesInsertReq
  46. memmove( BYTE_OFF_PTR( ptr, numBytesInsertReq ), ptr, BYTE_DIFF_PTR( ptr, pbBlockEnd ) );
  47. // Inserted data
  48. memset( BYTE_OFF_PTR( ptr, numBytesInsertReq - numBytes ), 0, numBytes );
  49. numBytesInsertReq -= numBytes;
  50. pbBlockEnd = ptr;
  51. }
  52. }
  53. int CInsertionTracker::ComputeOffset( void *ptrBase, int off ) const
  54. {
  55. void *ptrNewBase = ComputePointer( ptrBase );
  56. void *ptrNewData = ComputePointer( BYTE_OFF_PTR( ptrBase, off ) );
  57. return BYTE_DIFF_PTR( ptrNewBase, ptrNewData );
  58. }
  59. void * CInsertionTracker::ComputePointer( void *ptrNothingInserted ) const
  60. {
  61. int iInserted = 0;
  62. // Iterate the map and find all the data that would be inserted before the given pointer
  63. for ( Map::IndexType_t idx = m_map.FirstInorder();
  64. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  65. {
  66. if ( m_map.Key( idx ) < ptrNothingInserted )
  67. iInserted += m_map.Element( idx );
  68. else
  69. break;
  70. }
  71. return BYTE_OFF_PTR( ptrNothingInserted, iInserted );
  72. }
  73. //////////////////////////////////////////////////////////////////////////
  74. //
  75. // CMemoryMovingTracker implementation
  76. //
  77. //////////////////////////////////////////////////////////////////////////
  78. void CMemoryMovingTracker::RegisterBytes( void *pos, int length )
  79. {
  80. if ( length <= 0 && m_ePolicy != MEMORY_MODIFY )
  81. return;
  82. // -- hint
  83. if ( m_map.Count() && m_ePolicy == MEMORY_REMOVE )
  84. {
  85. if ( m_hint.ptr < pos )
  86. {
  87. if ( BYTE_OFF_PTR( m_hint.ptr, m_hint.len ) == pos )
  88. {
  89. m_hint.len += length;
  90. m_map.Element( m_hint.idx ) = m_hint.len;
  91. return;
  92. }
  93. }
  94. else if ( m_hint.ptr > pos )
  95. {
  96. if ( BYTE_OFF_PTR( pos, length ) == m_hint.ptr )
  97. {
  98. m_hint.len += length;
  99. m_hint.ptr = BYTE_OFF_PTR( m_hint.ptr, - length );
  100. m_map.Key( m_hint.idx ) = m_hint.ptr;
  101. m_map.Element( m_hint.idx ) = m_hint.len;
  102. return;
  103. }
  104. }
  105. }
  106. // -- end hint
  107. // Insert new
  108. Assert( m_map.InvalidIndex() == m_map.Find( ( byte * ) pos ) );
  109. Map::IndexType_t idx = m_map.InsertOrReplace( ( byte * ) pos, length );
  110. // New hint
  111. m_hint.idx = idx;
  112. m_hint.ptr = ( byte * ) pos;
  113. m_hint.len = length;
  114. }
  115. int CMemoryMovingTracker::GetNumBytesRegistered() const
  116. {
  117. int iRegistered = 0;
  118. for ( Map::IndexType_t idx = m_map.FirstInorder();
  119. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  120. {
  121. int numBytes = m_map.Element( idx );
  122. if ( m_ePolicy == MEMORY_MODIFY && numBytes <= 0 )
  123. continue;
  124. iRegistered += numBytes;
  125. }
  126. return iRegistered;
  127. }
  128. void CMemoryMovingTracker::RegisterBaseDelta( void *pOldBase, void *pNewBase )
  129. {
  130. for ( Map::IndexType_t idx = m_map.FirstInorder();
  131. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  132. {
  133. m_map.Key( idx ) = BYTE_OFF_PTR( m_map.Key( idx ), BYTE_DIFF_PTR( pOldBase, pNewBase ) );
  134. }
  135. m_hint.ptr = BYTE_OFF_PTR( m_hint.ptr, BYTE_DIFF_PTR( pOldBase, pNewBase ) );
  136. }
  137. void CMemoryMovingTracker::Finalize()
  138. {
  139. // Iterate the map and find all the adjacent removal data blocks
  140. // TODO:
  141. }
  142. void CMemoryMovingTracker::MemMove( void *ptrBase, int &length ) const
  143. {
  144. if ( m_ePolicy == MEMORY_REMOVE )
  145. {
  146. int iRemoved = 0;
  147. for ( Map::IndexType_t idx = m_map.FirstInorder();
  148. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  149. {
  150. byte *ptr = m_map.Key( idx );
  151. int numBytes = m_map.Element( idx );
  152. byte *ptrDest = BYTE_OFF_PTR( ptr, - iRemoved );
  153. memmove( ptrDest, BYTE_OFF_PTR( ptrDest, numBytes ), BYTE_DIFF_PTR( BYTE_OFF_PTR( ptr, numBytes ), BYTE_OFF_PTR( ptrBase, length ) ) );
  154. iRemoved += numBytes;
  155. }
  156. length -= iRemoved;
  157. }
  158. if ( m_ePolicy == MEMORY_INSERT )
  159. {
  160. for ( Map::IndexType_t idx = m_map.LastInorder();
  161. idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
  162. {
  163. byte *ptr = m_map.Key( idx );
  164. int numBytes = m_map.Element( idx );
  165. byte *ptrDest = BYTE_OFF_PTR( ptr, numBytes );
  166. memmove( ptrDest, ptr, BYTE_DIFF_PTR( ptr, BYTE_OFF_PTR( ptrBase, length ) ) );
  167. length += numBytes;
  168. }
  169. }
  170. if ( m_ePolicy == MEMORY_MODIFY )
  171. {
  172. // Perform insertions first:
  173. for ( Map::IndexType_t idx = m_map.LastInorder();
  174. idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
  175. {
  176. byte *ptr = m_map.Key( idx );
  177. int numBytes = m_map.Element( idx );
  178. if ( numBytes <= 0 )
  179. continue; // this is removal
  180. byte *ptrDest = BYTE_OFF_PTR( ptr, numBytes );
  181. memmove( ptrDest, ptr, BYTE_DIFF_PTR( ptr, BYTE_OFF_PTR( ptrBase, length ) ) );
  182. length += numBytes;
  183. }
  184. // Now perform removals accounting for all insertions
  185. // that has happened up to the moment
  186. int numInsertedToPoint = 0;
  187. int iRemoved = 0;
  188. for ( Map::IndexType_t idx = m_map.FirstInorder();
  189. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  190. {
  191. byte *ptr = m_map.Key( idx );
  192. int numBytes = m_map.Element( idx );
  193. if ( numBytes >= 0 )
  194. {
  195. numInsertedToPoint += numBytes;
  196. continue; // this is insertion that already happened
  197. }
  198. numBytes = -numBytes;
  199. ptr = BYTE_OFF_PTR( ptr, numInsertedToPoint );
  200. byte *ptrDest = BYTE_OFF_PTR( ptr, - iRemoved );
  201. memmove( ptrDest, BYTE_OFF_PTR( ptrDest, numBytes ), BYTE_DIFF_PTR( BYTE_OFF_PTR( ptr, numBytes ), BYTE_OFF_PTR( ptrBase, length ) ) );
  202. iRemoved += numBytes;
  203. }
  204. length -= iRemoved;
  205. }
  206. }
  207. int CMemoryMovingTracker::ComputeOffset( void *ptrBase, int off ) const
  208. {
  209. void *ptrNewBase = ComputePointer( ptrBase );
  210. void *ptrNewData = ComputePointer( BYTE_OFF_PTR( ptrBase, off ) );
  211. return BYTE_DIFF_PTR( ptrNewBase, ptrNewData );
  212. }
  213. void * CMemoryMovingTracker::ComputePointer( void *ptrNothingRemoved ) const
  214. {
  215. int iAffected = 0;
  216. // Iterate the map and find all the data that would be removed/inserted before the given pointer
  217. for ( Map::IndexType_t idx = m_map.FirstInorder();
  218. idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
  219. {
  220. if ( m_map.Key( idx ) < ptrNothingRemoved )
  221. iAffected += m_map.Element( idx );
  222. else
  223. break;
  224. }
  225. if ( m_ePolicy == MEMORY_REMOVE )
  226. return BYTE_OFF_PTR( ptrNothingRemoved, - iAffected );
  227. if ( m_ePolicy == MEMORY_INSERT || m_ePolicy == MEMORY_MODIFY )
  228. return BYTE_OFF_PTR( ptrNothingRemoved, iAffected );
  229. return ptrNothingRemoved;
  230. }