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.

203 lines
7.1 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. //
  3. // Purpose: see utlsoacontainer_serialization.h
  4. //
  5. //===========================================================================//
  6. #include "tier0/platform.h"
  7. #include "tier1/utlsoacontainer.h"
  8. #include "dmxloader/dmxloader.h"
  9. #include "dmxloader/dmxelement.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. // Simple wrapper class to provide access to the CSOAContainer innards
  13. class CSOAContainer_Serializable : public CSOAContainer
  14. {
  15. DECLARE_DMXELEMENT_UNPACK();
  16. public:
  17. bool Serialize( CDmxElement *pRootElement );
  18. bool Unserialize( const CDmxElement *pRootElement );
  19. private:
  20. bool ContainsValidAttributes( void );
  21. enum SoaContainerDmxVersion_t { SOA_CONTAINER_DMX_VERSION = 1 };
  22. };
  23. BEGIN_DMXELEMENT_UNPACK( CSOAContainer_Serializable )
  24. // NOTE: All other member variables are recomputed from the below values, after unpack, by 'AllocateData' (the stored data is copyied in after that)
  25. DMXELEMENT_UNPACK_FIELD( "num_columns", "0", int, m_nColumns )
  26. DMXELEMENT_UNPACK_FIELD( "num_rows", "0", int, m_nRows )
  27. DMXELEMENT_UNPACK_FIELD( "num_slices", "0", int, m_nSlices )
  28. DMXELEMENT_UNPACK_FIELD_ARRAY( "attribute_types", "-1", int, m_nDataType )
  29. DMXELEMENT_UNPACK_FIELD( "field_present_mask", "0", int, m_nFieldPresentMask )
  30. DMXELEMENT_UNPACK_FIELD( "thread_mode", "-1", int, m_eThreadMode )
  31. END_DMXELEMENT_UNPACK( CSOAContainer_Serializable, s_pSOAContainerUnpack )
  32. bool CSOAContainer_Serializable::Serialize( CDmxElement *pRootElement )
  33. {
  34. CDmxElementModifyScope modifyRoot( pRootElement );
  35. COMPILE_TIME_ASSERT( ATTRDATATYPE_NONE == -1 ); // If this changes, modify the line for m_nDataType in the BEGIN_DMXELEMENT_UNPACK block above
  36. COMPILE_TIME_ASSERT( SOATHREADMODE_AUTO == -1 ); // If this changes, modify the line for m_eThreadMode in the BEGIN_DMXELEMENT_UNPACK block above
  37. if ( !ContainsValidAttributes() || ( !m_pDataMemory && !m_pConstantDataMemory ) )
  38. {
  39. Warning( "ERROR: CSOAContainer_Serializable::Unserialize - no data to serialize!\n" );
  40. return false;
  41. }
  42. // Write the version number first
  43. const int nDmxVersion = SOA_CONTAINER_DMX_VERSION;
  44. pRootElement->SetValue( "version", nDmxVersion );
  45. // Write some member variables (enough to recompute the rest)
  46. pRootElement->AddAttributesFromStructure( this, s_pSOAContainerUnpack );
  47. // Now write out the data, as floats (NOTE: we have to at least init the attribute as a zero-element vector or it won't serialize!)
  48. CDmxAttribute *pDataMemoryAttribute = pRootElement->AddAttribute( "memory_data" );
  49. CUtlVector< float >& dataVector = pDataMemoryAttribute->GetArrayForEdit< float >();
  50. size_t nDataMemorySize = DataMemorySize();
  51. dataVector.SetCount( nDataMemorySize / sizeof( float ) );
  52. // NOTE: Constant data is always zero for now, but we write it out in case that changes (non-zero constant values seem potentially useful)
  53. CDmxAttribute *pConstantMemoryAttribute = pRootElement->AddAttribute( "constant_data" );
  54. CUtlVector< float >& constantVector = pConstantMemoryAttribute->GetArrayForEdit< float >();
  55. size_t nConstantMemorySize = ConstantMemorySize();
  56. constantVector.SetCount( nConstantMemorySize / sizeof( float ) );
  57. // To account for 'separate' memory allocations, we need to copy each attribute one at a time
  58. byte *pBaseDataPtr = (byte *)dataVector.Base();
  59. byte *pBaseConstantPtr = (byte *)constantVector.Base();
  60. for( int i = 0; i < MAX_SOA_FIELDS; i++ )
  61. {
  62. if ( m_nDataType[i] == ATTRDATATYPE_NONE )
  63. continue;
  64. if ( m_nFieldPresentMask & ( 1 << i ) )
  65. {
  66. memcpy( pBaseDataPtr, m_pAttributePtrs[ i ], AttributeMemorySize( i ) );
  67. pBaseDataPtr += AttributeMemorySize( i );
  68. }
  69. else
  70. {
  71. memcpy( pBaseConstantPtr, m_pAttributePtrs[ i ], AttributeMemorySize( i ) );
  72. pBaseConstantPtr += AttributeMemorySize( i );
  73. }
  74. }
  75. return true;
  76. }
  77. bool CSOAContainer_Serializable::Unserialize( const CDmxElement *pRootElement )
  78. {
  79. // Read the version number
  80. int nVersion = pRootElement->GetValue( "version", -1 );
  81. if ( nVersion == -1 )
  82. {
  83. Warning( "ERROR: CSOAContainer_Serializable::Unserialize - missing version field!\n" );
  84. return false;
  85. }
  86. // Clear, then unpack the stored members
  87. Purge();
  88. pRootElement->UnpackIntoStructure( this, s_pSOAContainerUnpack );
  89. // Check that we have enough data to create a valid container!
  90. int nError = 0;
  91. const CDmxAttribute *pDataMemoryAttribute = pRootElement->GetAttribute( "memory_data" );
  92. const CDmxAttribute *pConstantMemoryAttribute = pRootElement->GetAttribute( "constant_data" );
  93. if ( !pDataMemoryAttribute || !pConstantMemoryAttribute )
  94. nError = 1;
  95. if ( !ContainsValidAttributes() )
  96. nError = 1;
  97. if ( !nError )
  98. {
  99. // Update files saved in old versions
  100. switch( nVersion )
  101. {
  102. case SOA_CONTAINER_DMX_VERSION:
  103. break; // Up to date - nothing to do.
  104. default:
  105. // The DMX unpack structure will set reasonable defaults or flag stuff that needs fixing up
  106. nError = 1; // TODO: add code when versions are bumped and fixup needs to happen
  107. break;
  108. }
  109. }
  110. if ( !nError )
  111. {
  112. SOAThreadMode_t eSavedThreadMode = m_eThreadMode;
  113. // Allocate memory (fills in all the pointers and strides)
  114. AllocateData( NumCols(), NumRows(), NumSlices() );
  115. // Set thread mode from the unserialized value (AllocateData stomps on it)
  116. SetThreadMode( eSavedThreadMode );
  117. // Now copy in the data
  118. if ( m_pDataMemory )
  119. {
  120. const CUtlVector< float >& floatVector = pDataMemoryAttribute->GetArray< float >();
  121. size_t nDataMemorySize = DataMemorySize();
  122. int nFloats = nDataMemorySize / sizeof( float );
  123. if ( nFloats == floatVector.Count() )
  124. memcpy( m_pDataMemory, floatVector.Base(), nDataMemorySize );
  125. else
  126. nError = 2;
  127. }
  128. if ( m_pConstantDataMemory )
  129. {
  130. const CUtlVector< float >& floatVector = pConstantMemoryAttribute->GetArray< float >();
  131. size_t nConstantMemorySize = ConstantMemorySize();
  132. int nFloats = nConstantMemorySize / sizeof( float );
  133. if ( nFloats == floatVector.Count() )
  134. memcpy( m_pConstantDataMemory, floatVector.Base(), nConstantMemorySize );
  135. else
  136. nError = 3;
  137. }
  138. }
  139. if ( nError )
  140. {
  141. switch( nError )
  142. {
  143. case 1: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - DMX data does not represent a valid container!\n" ); break;
  144. case 2: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - found wrong amount of memory data!\n" ); break;
  145. case 3: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - found wrong amount of constant data!\n" ); break;
  146. }
  147. Assert( 0 );
  148. Purge();
  149. return false;
  150. }
  151. return true;
  152. }
  153. bool CSOAContainer_Serializable::ContainsValidAttributes( void )
  154. {
  155. if ( ( NumCols() <= 0 ) || ( NumRows() <= 0 ) || ( NumSlices() <= 0 ) )
  156. return false;
  157. for ( int i = 0; i < MAX_SOA_FIELDS; i++ )
  158. {
  159. if ( m_nDataType[ i ] != ATTRDATATYPE_NONE )
  160. return true;
  161. }
  162. return false;
  163. }
  164. bool SerializeCSOAContainer( const CSOAContainer *pContainer, CDmxElement *pRootElement )
  165. {
  166. return ((CSOAContainer_Serializable*)pContainer)->Serialize( pRootElement );
  167. }
  168. bool UnserializeCSOAContainer( const CSOAContainer *pContainer, const CDmxElement *pRootElement )
  169. {
  170. return ((CSOAContainer_Serializable*)pContainer)->Unserialize( pRootElement );
  171. }