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.

245 lines
5.6 KiB

  1. //====== Copyright (c) Valve Corporation, All rights reserved. =======//
  2. #ifndef TIER1_UTL_BUFFER_STRIDER_HDR
  3. #define TIER1_UTL_BUFFER_STRIDER_HDR
  4. #include "tier1/strtools.h"
  5. //#include "tier0/memdbg_for_headers.h"
  6. template< class T, class A >
  7. class CUtlVector;
  8. class CBufferStrider
  9. {
  10. public:
  11. CBufferStrider( void *pBuffer );
  12. template <typename T> T *Stride( int nCount = 1 );
  13. template <typename T> T StrideUnaligned( );
  14. template <typename T> void StrideUnaligned( T* pOut, int nCount = 1 );
  15. char* StrideString( );
  16. char* StrideString( const void *pEnd );
  17. template <typename T> T Peek( ){ return *(T*)Get(); }
  18. uint8 *Get(){ return m_pBuffer; }
  19. void Set( void *p ){ m_pBuffer = ( uint8 *)p; }
  20. void Align( uint nAlignment ){ m_pBuffer = ( uint8* )( ( uintp( m_pBuffer ) + nAlignment - 1 ) & ~uintp( nAlignment - 1 ) ); }
  21. protected:
  22. uint8 *m_pBuffer;
  23. };
  24. template <typename T>
  25. inline T *CBufferStrider::Stride( int nCount )
  26. {
  27. uint nAlignMask = VALIGNOF( T ) - 1; NOTE_UNUSED( nAlignMask );
  28. AssertDbg( !( uintp( m_pBuffer ) & nAlignMask ) );
  29. T* p = ( T* ) m_pBuffer;
  30. m_pBuffer += sizeof( T ) * nCount;
  31. return p;
  32. }
  33. template <typename T>
  34. inline T CBufferStrider::StrideUnaligned( )
  35. {
  36. T out;
  37. memcpy( &out, m_pBuffer, sizeof( T ) );
  38. m_pBuffer += sizeof( T );
  39. return out;
  40. }
  41. template <typename T>
  42. inline void CBufferStrider::StrideUnaligned( T* pOut, int nCount )
  43. {
  44. memcpy( pOut, m_pBuffer, sizeof( T ) * nCount );
  45. m_pBuffer += sizeof( T ) * nCount;
  46. }
  47. inline char* CBufferStrider::StrideString( const void *pEnd )
  48. {
  49. uint8 *pNextItem = m_pBuffer;
  50. do
  51. {
  52. if ( pNextItem >= ( uint8* ) pEnd )
  53. {
  54. return NULL; // we steppend past end of buffer
  55. }
  56. }
  57. while ( *( pNextItem++ ) );
  58. // found end of string
  59. char *pString = ( char* ) m_pBuffer;
  60. m_pBuffer = pNextItem;
  61. return pString;
  62. }
  63. inline char* CBufferStrider::StrideString( )
  64. {
  65. uint8 *pNextItem = m_pBuffer;
  66. while ( *( pNextItem++ ) ) // this will crash in case of malformed (no terminating NULL) buffer
  67. {
  68. continue;
  69. }
  70. // found end of string
  71. char *pString = ( char* ) m_pBuffer;
  72. m_pBuffer = pNextItem;
  73. return pString;
  74. }
  75. inline
  76. CBufferStrider::CBufferStrider( void *pBuffer )
  77. : m_pBuffer( ( uint8* ) pBuffer )
  78. {
  79. }
  80. #define MULTIBUFFER_ASSERTS
  81. class CMultiBufferCounter
  82. {
  83. public:
  84. CMultiBufferCounter( )
  85. :m_nByteCount( 0 )
  86. #ifdef MULTIBUFFER_ASSERTS
  87. , m_nMaxAlignment( 0 )
  88. , m_nRunAlignment( 0xFFFFFFFF )
  89. #endif
  90. {}
  91. template <typename T>
  92. T* operator()( T *& pDummy, uint nCount )
  93. {
  94. #ifdef MULTIBUFFER_ASSERTS
  95. const uint nAlignMask = VALIGNOF( T ) - 1;
  96. Assert( m_nRunAlignment >= nAlignMask );
  97. m_nRunAlignment &= nAlignMask;
  98. m_nMaxAlignment |= nAlignMask;
  99. #endif
  100. m_nByteCount += sizeof( T ) * nCount;
  101. return NULL; // we didn't allocate anything yet!
  102. }
  103. template< typename T, typename A >
  104. T* operator()( T*& pDummy, const CUtlVector< T, A > &arr )
  105. {
  106. ( *this )( pDummy, arr.Count( ) );
  107. return NULL; // we didn't allocate anything yet
  108. }
  109. char *String( const char *& pDummy, const char *pSourceString )
  110. {
  111. if ( pSourceString )
  112. {
  113. ( *this )( pDummy, uint( V_strlen( pSourceString ) + 1 ) );
  114. }
  115. return NULL; // we didn't allocate anything yet
  116. }
  117. uint GetByteCount( )const { return m_nByteCount; }
  118. protected:
  119. uint m_nByteCount;
  120. #ifdef MULTIBUFFER_ASSERTS
  121. uint m_nMaxAlignment;
  122. uint m_nRunAlignment;
  123. #endif
  124. };
  125. class CMultiBufferStrider: public CBufferStrider
  126. {
  127. public:
  128. CMultiBufferStrider( void *pBuffer ): CBufferStrider( pBuffer ){}
  129. template <typename T>
  130. T* operator() ( T*& refPtr, uint nCount )
  131. {
  132. refPtr = nCount ? Stride< T >( nCount ) : NULL;
  133. return refPtr;
  134. }
  135. template < typename T, typename A >
  136. T* operator()( T *&refPtr, const CUtlVector< T, A > &arr )
  137. {
  138. if ( arr.IsEmpty( ) )
  139. {
  140. refPtr = NULL;
  141. }
  142. else
  143. {
  144. refPtr = Stride< T >( arr.Count( ) );
  145. V_memcpy( refPtr, arr.Base( ), sizeof( T ) * arr.Count( ) );
  146. }
  147. return refPtr;
  148. }
  149. char *String( const char *& refPtr, const char *pSourceString )
  150. {
  151. if ( pSourceString )
  152. {
  153. uint nBufLen = V_strlen( pSourceString ) + 1;
  154. char *pOut = const_cast< char* >( ( *this )( refPtr, nBufLen ) );
  155. V_memcpy( pOut, pSourceString, nBufLen );
  156. AssertDbg( refPtr == pOut );
  157. return pOut;
  158. }
  159. else
  160. {
  161. return NULL; // we didn't allocate anything
  162. }
  163. }
  164. };
  165. //////////////////////////////////////////////////////////////////////////
  166. // Derive from this buffer and override function Enum( T& ) that should
  167. // enumerate all the pointers and sizes of buffers to be allocated
  168. //
  169. template <typename Derived>
  170. class CMultiBufferHelper
  171. {
  172. public:
  173. CMultiBufferHelper( )
  174. {
  175. m_pMultiBuffer = NULL;
  176. m_nMultiBufferSize = 0;
  177. }
  178. ~CMultiBufferHelper( )
  179. {
  180. if ( m_pMultiBuffer )
  181. {
  182. MemAlloc_FreeAligned( m_pMultiBuffer );
  183. m_pMultiBuffer = NULL;
  184. m_nMultiBufferSize = 0;
  185. }
  186. }
  187. uint8 *GetBuffer( ) { return m_pMultiBuffer; }
  188. uint GetBufferSize( ) { return m_nMultiBufferSize; }
  189. uint8 *TakeBuffer( )
  190. {
  191. // forget the buffer
  192. uint8 *pBuffer = m_pMultiBuffer;
  193. m_pMultiBuffer = NULL;
  194. m_nMultiBufferSize = 0;
  195. return pBuffer;
  196. }
  197. protected:
  198. template <typename Ctx >
  199. void ReallocateMultiBuffer( Ctx &context )
  200. {
  201. if ( m_pMultiBuffer )
  202. {
  203. MemAlloc_FreeAligned( m_pMultiBuffer );
  204. }
  205. CMultiBufferCounter byteCounter;
  206. static_cast< Derived* >( this )->OnAllocateMultiBuffer( byteCounter, context );
  207. m_nMultiBufferSize = byteCounter.GetByteCount( );
  208. m_pMultiBuffer = ( uint8* )MemAlloc_AllocAligned( m_nMultiBufferSize, 16 );
  209. CMultiBufferStrider bufferStrider( m_pMultiBuffer );
  210. static_cast< Derived* >( this )->OnAllocateMultiBuffer( bufferStrider, context );
  211. Assert( m_pMultiBuffer + m_nMultiBufferSize == bufferStrider.Get( ) );
  212. }
  213. protected:
  214. uint8 *m_pMultiBuffer;
  215. uint m_nMultiBufferSize;
  216. };
  217. #endif