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.

666 lines
23 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dmxloader/dmxattribute.h"
  7. #include "tier1/utlbufferutil.h"
  8. #include "tier1/uniqueid.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. //-----------------------------------------------------------------------------
  12. // globals
  13. //-----------------------------------------------------------------------------
  14. CUtlSymbolTableLargeMT CDmxAttribute::s_AttributeNameSymbols;
  15. //-----------------------------------------------------------------------------
  16. // Attribute size
  17. //-----------------------------------------------------------------------------
  18. static size_t s_pAttributeSize[AT_TYPE_COUNT] =
  19. {
  20. 0, // AT_UNKNOWN,
  21. sizeof(CDmxElement*), // AT_ELEMENT,
  22. sizeof(int), // AT_INT,
  23. sizeof(float), // AT_FLOAT,
  24. sizeof(bool), // AT_BOOL,
  25. sizeof(CUtlString), // AT_STRING,
  26. sizeof(CUtlBinaryBlock), // AT_VOID,
  27. sizeof(DmeTime_t), // AT_TIME,
  28. sizeof(Color), // AT_COLOR,
  29. sizeof(Vector2D), // AT_VECTOR2,
  30. sizeof(Vector), // AT_VECTOR3,
  31. sizeof(Vector4D), // AT_VECTOR4,
  32. sizeof(QAngle), // AT_QANGLE,
  33. sizeof(Quaternion), // AT_QUATERNION,
  34. sizeof(VMatrix), // AT_VMATRIX,
  35. sizeof(CUtlVector<CDmxElement*>), // AT_ELEMENT_ARRAY,
  36. sizeof(CUtlVector<int>), // AT_INT_ARRAY,
  37. sizeof(CUtlVector<float>), // AT_FLOAT_ARRAY,
  38. sizeof(CUtlVector<bool>), // AT_BOOL_ARRAY,
  39. sizeof(CUtlVector<CUtlString>), // AT_STRING_ARRAY,
  40. sizeof(CUtlVector<CUtlBinaryBlock>), // AT_VOID_ARRAY,
  41. sizeof(CUtlVector<DmeTime_t>), // AT_TIME_ARRAY,
  42. sizeof(CUtlVector<Color>), // AT_COLOR_ARRAY,
  43. sizeof(CUtlVector<Vector2D>), // AT_VECTOR2_ARRAY,
  44. sizeof(CUtlVector<Vector>), // AT_VECTOR3_ARRAY,
  45. sizeof(CUtlVector<Vector4D>), // AT_VECTOR4_ARRAY,
  46. sizeof(CUtlVector<QAngle>), // AT_QANGLE_ARRAY,
  47. sizeof(CUtlVector<Quaternion>), // AT_QUATERNION_ARRAY,
  48. sizeof(CUtlVector<VMatrix>), // AT_VMATRIX_ARRAY,
  49. };
  50. //-----------------------------------------------------------------------------
  51. // make sure that the attribute data type sizes are what we think they are to choose the right allocator
  52. //-----------------------------------------------------------------------------
  53. struct CSizeTest
  54. {
  55. CSizeTest()
  56. {
  57. // test internal value attribute sizes
  58. COMPILE_TIME_ASSERT( sizeof( int ) == 4 );
  59. COMPILE_TIME_ASSERT( sizeof( float ) == 4 );
  60. COMPILE_TIME_ASSERT( sizeof( bool ) <= 4 );
  61. COMPILE_TIME_ASSERT( sizeof( Color ) == 4 );
  62. COMPILE_TIME_ASSERT( sizeof( DmeTime_t ) == 4 );
  63. COMPILE_TIME_ASSERT( sizeof( Vector2D ) == 8 );
  64. COMPILE_TIME_ASSERT( sizeof( Vector ) == 12 );
  65. COMPILE_TIME_ASSERT( sizeof( Vector4D ) == 16 );
  66. COMPILE_TIME_ASSERT( sizeof( QAngle ) == 12 );
  67. COMPILE_TIME_ASSERT( sizeof( Quaternion ) == 16 );
  68. COMPILE_TIME_ASSERT( sizeof( VMatrix ) == 64 );
  69. #if !defined( PLATFORM_64BITS )
  70. COMPILE_TIME_ASSERT( sizeof( CUtlString ) == 16 );
  71. COMPILE_TIME_ASSERT( sizeof( CUtlBinaryBlock ) == 16 );
  72. #endif
  73. };
  74. };
  75. static CSizeTest g_sizeTest;
  76. //-----------------------------------------------------------------------------
  77. // Returns attribute name for type
  78. //-----------------------------------------------------------------------------
  79. const char *CDmxAttribute::s_pAttributeTypeName[AT_TYPE_COUNT] =
  80. {
  81. "unknown", // AT_UNKNOWN
  82. CDmAttributeInfo<DmElementHandle_t>::AttributeTypeName(), // AT_ELEMENT,
  83. CDmAttributeInfo<int>::AttributeTypeName(), // AT_INT,
  84. CDmAttributeInfo<float>::AttributeTypeName(), // AT_FLOAT,
  85. CDmAttributeInfo<bool>::AttributeTypeName(), // AT_BOOL,
  86. CDmAttributeInfo<CUtlString>::AttributeTypeName(), // AT_STRING,
  87. CDmAttributeInfo<CUtlBinaryBlock>::AttributeTypeName(), // AT_VOID,
  88. CDmAttributeInfo<DmeTime_t>::AttributeTypeName(), // AT_TIME,
  89. CDmAttributeInfo<Color>::AttributeTypeName(), // AT_COLOR,
  90. CDmAttributeInfo<Vector2D>::AttributeTypeName(), // AT_VECTOR2,
  91. CDmAttributeInfo<Vector>::AttributeTypeName(), // AT_VECTOR3,
  92. CDmAttributeInfo<Vector4D>::AttributeTypeName(), // AT_VECTOR4,
  93. CDmAttributeInfo<QAngle>::AttributeTypeName(), // AT_QANGLE,
  94. CDmAttributeInfo<Quaternion>::AttributeTypeName(), // AT_QUATERNION,
  95. CDmAttributeInfo<VMatrix>::AttributeTypeName(), // AT_VMATRIX,
  96. CDmAttributeInfo< CUtlVector< DmElementHandle_t > >::AttributeTypeName(), // AT_ELEMENT_ARRAY,
  97. CDmAttributeInfo< CUtlVector< int > >::AttributeTypeName(), // AT_INT_ARRAY,
  98. CDmAttributeInfo< CUtlVector< float > >::AttributeTypeName(), // AT_FLOAT_ARRAY,
  99. CDmAttributeInfo< CUtlVector< bool > >::AttributeTypeName(), // AT_BOOL_ARRAY,
  100. CDmAttributeInfo< CUtlVector< CUtlString > >::AttributeTypeName(), // AT_STRING_ARRAY,
  101. CDmAttributeInfo< CUtlVector< CUtlBinaryBlock > >::AttributeTypeName(), // AT_VOID_ARRAY,
  102. CDmAttributeInfo< CUtlVector< DmeTime_t > >::AttributeTypeName(), // AT_TIME_ARRAY,
  103. CDmAttributeInfo< CUtlVector< Color > >::AttributeTypeName(), // AT_COLOR_ARRAY,
  104. CDmAttributeInfo< CUtlVector< Vector2D > >::AttributeTypeName(), // AT_VECTOR2_ARRAY,
  105. CDmAttributeInfo< CUtlVector< Vector > >::AttributeTypeName(), // AT_VECTOR3_ARRAY,
  106. CDmAttributeInfo< CUtlVector< Vector4D > >::AttributeTypeName(), // AT_VECTOR4_ARRAY,
  107. CDmAttributeInfo< CUtlVector< QAngle > >::AttributeTypeName(), // AT_QANGLE_ARRAY,
  108. CDmAttributeInfo< CUtlVector< Quaternion > >::AttributeTypeName(), // AT_QUATERNION_ARRAY,
  109. CDmAttributeInfo< CUtlVector< VMatrix > >::AttributeTypeName(), // AT_VMATRIX_ARRAY,
  110. };
  111. //-----------------------------------------------------------------------------
  112. // Constructor, destructor
  113. //-----------------------------------------------------------------------------
  114. CDmxAttribute::CDmxAttribute( const char *pAttributeName )
  115. {
  116. m_Name = s_AttributeNameSymbols.AddString( pAttributeName );
  117. m_Type = AT_UNKNOWN;
  118. m_pData = NULL;
  119. }
  120. CDmxAttribute::CDmxAttribute( CUtlSymbolLarge attributeName )
  121. {
  122. m_Name = attributeName;
  123. m_Type = AT_UNKNOWN;
  124. m_pData = NULL;
  125. }
  126. CDmxAttribute::~CDmxAttribute()
  127. {
  128. FreeDataMemory();
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Returns the size of the variables storing the various attribute types
  132. //-----------------------------------------------------------------------------
  133. int CDmxAttribute::AttributeDataSize( DmAttributeType_t type )
  134. {
  135. return s_pAttributeSize[type];
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Gets the basic type for a given array attribute type
  139. //-----------------------------------------------------------------------------
  140. DmAttributeType_t CDmxAttribute::ArrayAttributeBasicType( DmAttributeType_t type )
  141. {
  142. COMPILE_TIME_ASSERT( ( AT_FIRST_ARRAY_TYPE - AT_FIRST_VALUE_TYPE ) == ( AT_TYPE_COUNT - AT_FIRST_ARRAY_TYPE ) );
  143. if ( IsArrayType( type ) )
  144. type = (DmAttributeType_t)( type - ( AT_FIRST_ARRAY_TYPE - AT_FIRST_VALUE_TYPE ) ); // Array -> array element
  145. return type;
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Macros to tersify operations on attribute data of any type
  149. //-----------------------------------------------------------------------------
  150. #define NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  151. case AT_INT: _func_< int , int >_params_; break; \
  152. case AT_FLOAT: _func_< float , float >_params_; break; \
  153. case AT_BOOL: _func_< bool , bool >_params_; break; \
  154. case AT_STRING: _func_< CUtlString , CUtlString >_params_; break; \
  155. case AT_VOID: _func_< CUtlBinaryBlock , CUtlBinaryBlock >_params_; break; \
  156. case AT_TIME: _func_< DmeTime_t , DmeTime_t >_params_; break; \
  157. case AT_COLOR: _func_< Color , Color >_params_; break; \
  158. case AT_VECTOR2: _func_< Vector2D , Vector2D >_params_; break; \
  159. case AT_VECTOR3: _func_< Vector , Vector >_params_; break; \
  160. case AT_VECTOR4: _func_< Vector4D , Vector4D >_params_; break; \
  161. case AT_QANGLE: _func_< QAngle , QAngle >_params_; break; \
  162. case AT_QUATERNION: _func_< Quaternion , Quaternion >_params_; break; \
  163. case AT_VMATRIX: _func_< VMatrix , VMatrix >_params_; break;
  164. #define ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  165. case AT_INT_ARRAY: _func_< CUtlVector<int >, int >_params_; break; \
  166. case AT_FLOAT_ARRAY: _func_< CUtlVector<float >, float >_params_; break; \
  167. case AT_BOOL_ARRAY: _func_< CUtlVector<bool >, bool >_params_; break; \
  168. case AT_STRING_ARRAY: _func_< CUtlVector<CUtlString >, CUtlString >_params_; break; \
  169. case AT_VOID_ARRAY: _func_< CUtlVector<CUtlBinaryBlock >, CUtlBinaryBlock >_params_; break; \
  170. case AT_TIME_ARRAY: _func_< CUtlVector<DmeTime_t >, DmeTime_t >_params_; break; \
  171. case AT_COLOR_ARRAY: _func_< CUtlVector<Color >, Color >_params_; break; \
  172. case AT_VECTOR2_ARRAY: _func_< CUtlVector<Vector2D >, Vector2D >_params_; break; \
  173. case AT_VECTOR3_ARRAY: _func_< CUtlVector<Vector >, Vector >_params_; break; \
  174. case AT_VECTOR4_ARRAY: _func_< CUtlVector<Vector4D >, Vector4D >_params_; break; \
  175. case AT_QANGLE_ARRAY: _func_< CUtlVector<QAngle >, QAngle >_params_; break; \
  176. case AT_QUATERNION_ARRAY: _func_< CUtlVector<Quaternion >, Quaternion >_params_; break; \
  177. case AT_VMATRIX_ARRAY: _func_< CUtlVector<VMatrix >, VMatrix >_params_; break;
  178. #define NON_ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
  179. case AT_ELEMENT: _func_< CDmxElement* , CDmxElement* >_params_; break;
  180. #define ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
  181. case AT_ELEMENT_ARRAY: _func_< CUtlVector<CDmxElement* >, CDmxElement* >_params_; break;
  182. #define CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( _func_, _params_, _errCase_ ) \
  183. switch( m_Type ) \
  184. { \
  185. ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  186. default: _errCase_; \
  187. }
  188. #define CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( _func_, _params_, _errCase_ ) \
  189. switch( m_Type ) \
  190. { \
  191. ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  192. ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
  193. default: _errCase_; \
  194. }
  195. #define CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( _func_, _params_, _errCase_ ) \
  196. switch( m_Type ) \
  197. { \
  198. NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  199. ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  200. default: _errCase_; \
  201. }
  202. #define CALL_TYPE_TEMPLATIZED_FUNCTION( _func_, _params_, _errCase_ ) \
  203. switch( m_Type ) \
  204. { \
  205. NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  206. NON_ARRAY_ELEMENT_CASE(_func_, _params_, _errCase_ ) \
  207. ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
  208. ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
  209. default: _errCase_; \
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Allocate, free memory for data
  213. //-----------------------------------------------------------------------------
  214. void CDmxAttribute::AllocateDataMemory( DmAttributeType_t type )
  215. {
  216. FreeDataMemory();
  217. m_Type = type;
  218. m_pData = DMXAlloc( s_pAttributeSize[m_Type] );
  219. }
  220. template < class VT, class T >
  221. void CDmxAttribute::ConstructDataMemory( void )
  222. {
  223. Construct( (VT *)m_pData );
  224. }
  225. void CDmxAttribute::AllocateDataMemory_AndConstruct( DmAttributeType_t type )
  226. {
  227. AllocateDataMemory( type );
  228. Assert( m_pData != NULL );
  229. // Process array and non-array types, including elements
  230. CALL_TYPE_TEMPLATIZED_FUNCTION( ConstructDataMemory, (), );
  231. }
  232. template < class VT, class T >
  233. void CDmxAttribute::DestructDataMemory( void )
  234. {
  235. Destruct( (VT *)m_pData );
  236. }
  237. void CDmxAttribute::FreeDataMemory()
  238. {
  239. if ( m_Type != AT_UNKNOWN )
  240. {
  241. Assert( m_pData != NULL );
  242. // Process array and non-array types, including elements
  243. CALL_TYPE_TEMPLATIZED_FUNCTION( DestructDataMemory, (), );
  244. m_Type = AT_UNKNOWN;
  245. }
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Returns attribute type string
  249. //-----------------------------------------------------------------------------
  250. inline const char* CDmxAttribute::GetTypeString() const
  251. {
  252. return s_pAttributeTypeName[ m_Type ];
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Returns attribute name
  256. //-----------------------------------------------------------------------------
  257. const char *CDmxAttribute::GetName() const
  258. {
  259. return m_Name.String();
  260. }
  261. //-----------------------------------------------------------------------------
  262. // Gets the size of an array, returns 0 if it's not an array type
  263. //-----------------------------------------------------------------------------
  264. template < class VT, class T >
  265. void CDmxAttribute::GetArrayCount( int &nCount ) const
  266. {
  267. nCount = ((VT *)m_pData)->Count();
  268. }
  269. int CDmxAttribute::GetArrayCount() const
  270. {
  271. int nCount = 0;
  272. // Process array types only, including elements
  273. if ( IsArrayType( m_Type ) && m_pData )
  274. CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( GetArrayCount, (nCount), );
  275. return nCount;
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Sets the size of an array, non-destructively
  279. //-----------------------------------------------------------------------------
  280. template < class VT, class T >
  281. void CDmxAttribute::SetArrayCount( int nArrayCount )
  282. {
  283. ((VT *)m_pData)->SetCountNonDestructively( nArrayCount );
  284. }
  285. void CDmxAttribute::SetArrayCount( int nArrayCount )
  286. {
  287. // Process array types only, including elements
  288. CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( SetArrayCount, (nArrayCount), Assert(0) );
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Gets the base data pointer of an array
  292. //-----------------------------------------------------------------------------
  293. template < class VT, class T >
  294. void CDmxAttribute::GetArrayBase( const void * &pBasePtr ) const
  295. {
  296. pBasePtr = ((VT *)m_pData)->Base();
  297. }
  298. const void *CDmxAttribute::GetArrayBase( void ) const
  299. {
  300. const void *pBasePtr = NULL;
  301. // Process array types only, including elements
  302. CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( GetArrayBase, (pBasePtr), Assert(0) );
  303. return pBasePtr;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // Gets whether a given data type serializes to multiple lines
  307. //-----------------------------------------------------------------------------
  308. template < class VT, class T >
  309. void CDmxAttribute::SerializesOnMultipleLines( bool &bResult ) const
  310. {
  311. bResult = ::SerializesOnMultipleLines<VT>();
  312. }
  313. bool CDmxAttribute::SerializesOnMultipleLines() const
  314. {
  315. bool bResult = false;
  316. // Process array and non-array types, including elements
  317. CALL_TYPE_TEMPLATIZED_FUNCTION( SerializesOnMultipleLines, (bResult), );
  318. return bResult;
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Write to file
  322. //-----------------------------------------------------------------------------
  323. template < class VT, class T >
  324. void CDmxAttribute::SerializeType( bool &bSuccess, CUtlBuffer &buf ) const
  325. {
  326. if ( m_pData )
  327. {
  328. bSuccess = ::Serialize( buf, *(VT *)m_pData );
  329. }
  330. else
  331. {
  332. VT temp;
  333. CDmAttributeInfo< VT >::SetDefaultValue( temp );
  334. bSuccess = ::Serialize( buf, temp );
  335. }
  336. }
  337. bool CDmxAttribute::Serialize( CUtlBuffer &buf ) const
  338. {
  339. bool bSuccess = false;
  340. // Process array and non-array types, excluding elements
  341. CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( SerializeType, (bSuccess, buf), AssertMsg( 0, "Cannot serialize elements or element arrays!\n" ) );
  342. return bSuccess;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Serialize a single element in an array attribute
  346. //-----------------------------------------------------------------------------
  347. template < class VT, class T >
  348. void CDmxAttribute::SerializeTypedElement( bool &bSuccess, int nIndex, CUtlBuffer &buf ) const
  349. {
  350. if ( m_pData )
  351. {
  352. const VT &array = *(VT *)m_pData;
  353. bSuccess = ::Serialize( buf, array[nIndex] );
  354. }
  355. else
  356. {
  357. T temp;
  358. CDmAttributeInfo<T>::SetDefaultValue( temp );
  359. bSuccess = ::Serialize( buf, temp );
  360. }
  361. }
  362. bool CDmxAttribute::SerializeElement( int nIndex, CUtlBuffer &buf ) const
  363. {
  364. if ( !IsArrayType( m_Type ) )
  365. return false;
  366. bool bSuccess = false;
  367. // Process array types only, excluding elements
  368. CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( SerializeTypedElement, (bSuccess, nIndex, buf), AssertMsg( 0, "Cannot serialize elements!\n" ); );
  369. return bSuccess;
  370. }
  371. //-----------------------------------------------------------------------------
  372. // Read from file
  373. //-----------------------------------------------------------------------------
  374. template < class VT, class T >
  375. void CDmxAttribute::UnserializeType( bool &bSuccess, CUtlBuffer &buf )
  376. {
  377. bSuccess = ::Unserialize( buf, *(VT *)m_pData );
  378. }
  379. bool CDmxAttribute::Unserialize( DmAttributeType_t type, CUtlBuffer &buf )
  380. {
  381. AllocateDataMemory_AndConstruct( type );
  382. bool bSuccess = false;
  383. // Process array and non-array types, excluding elements
  384. CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( UnserializeType, (bSuccess, buf), AssertMsg( 0, "Cannot unserialize elements or element arrays!\n" ); );
  385. return bSuccess;
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Read element from file
  389. //-----------------------------------------------------------------------------
  390. template < class VT, class T >
  391. void CDmxAttribute::UnserializeTypedElement( bool &bSuccess, CUtlBuffer &buf )
  392. {
  393. T temp;
  394. bSuccess = ::Unserialize( buf, temp );
  395. if ( bSuccess )
  396. ((VT *)m_pData)->AddToTail( temp );
  397. }
  398. bool CDmxAttribute::UnserializeElement( DmAttributeType_t type, CUtlBuffer &buf )
  399. {
  400. if ( !IsArrayType( type ) )
  401. return false;
  402. if ( m_Type != type )
  403. AllocateDataMemory_AndConstruct( type );
  404. bool bSuccess = false;
  405. // Process array types only, excluding elements
  406. CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( UnserializeTypedElement, (bSuccess, buf), AssertMsg( 0, "Cannot unserialize elements!\n" ) );
  407. return bSuccess;
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Sets name
  411. //-----------------------------------------------------------------------------
  412. void CDmxAttribute::SetName( const char *pAttributeName )
  413. {
  414. m_Name = s_AttributeNameSymbols.Find( pAttributeName );
  415. }
  416. //-----------------------------------------------------------------------------
  417. // Sets values
  418. //-----------------------------------------------------------------------------
  419. void CDmxAttribute::SetValue( const char *pString )
  420. {
  421. AllocateDataMemory( AT_STRING );
  422. CUtlString* pUtlString = (CUtlString*)m_pData;
  423. Construct( pUtlString );
  424. pUtlString->Set( pString );
  425. }
  426. void CDmxAttribute::SetValue( char *pString )
  427. {
  428. SetValue( (const char*)pString );
  429. }
  430. void CDmxAttribute::SetValue( const void *pBuffer, size_t nLen )
  431. {
  432. AllocateDataMemory( AT_VOID );
  433. CUtlBinaryBlock* pBlob = (CUtlBinaryBlock*)m_pData;
  434. Construct( pBlob );
  435. pBlob->Set( pBuffer, nLen );
  436. }
  437. // Untyped method for setting used by unpack
  438. void CDmxAttribute::SetValue( DmAttributeType_t type, const void *pSrc, int nLen )
  439. {
  440. if ( m_Type != type )
  441. {
  442. AllocateDataMemory( type );
  443. }
  444. if ( nLen > CDmxAttribute::AttributeDataSize( type ) )
  445. {
  446. nLen = CDmxAttribute::AttributeDataSize( type );
  447. }
  448. memcpy( m_pData, pSrc, nLen );
  449. }
  450. // Untyped method for setting arrays, used by unpack
  451. void CDmxAttribute::SetArrayValue( DmAttributeType_t type, const void *pSrc, int nDataTypeSize, int nArrayLength, int nSrcStride )
  452. {
  453. if ( !IsArrayType( type ) )
  454. return;
  455. if ( m_Type != type )
  456. {
  457. AllocateDataMemory( type );
  458. }
  459. // NOTE: nDestStride will be 4 for char/short/int values, and the below code is designed to work in all those cases
  460. DmAttributeType_t basicType = ArrayAttributeBasicType( type );
  461. int nDestStride = CDmxAttribute::AttributeDataSize( basicType );
  462. Assert( nDataTypeSize <= nDestStride );
  463. nDataTypeSize = MIN( nDataTypeSize, nDestStride );
  464. SetArrayCount( nArrayLength );
  465. void *pDest = (void *)GetArrayBase();
  466. if ( !pDest )
  467. return;
  468. if ( nDataTypeSize != nDestStride )
  469. {
  470. // Avoid writing junk, keep the data clean in case we inspect the memory or a serialized file:
  471. Q_memset( pDest, 0, nDestStride*nArrayLength );
  472. }
  473. if ( ( nSrcStride == nDestStride ) && ( nDataTypeSize == nSrcStride ) )
  474. {
  475. memcpy( pDest, pSrc, nDestStride*nArrayLength );
  476. }
  477. else
  478. {
  479. byte *pByteDest = (byte *)pDest;
  480. const byte *pByteSrc = (const byte *)pSrc;
  481. for ( int i = 0; i < nArrayLength; i++ )
  482. {
  483. memcpy( pByteDest, pByteSrc, nDataTypeSize );
  484. pByteDest += nDestStride;
  485. pByteSrc += nSrcStride;
  486. }
  487. }
  488. }
  489. void CDmxAttribute::GetArrayValue( DmAttributeType_t type, void *pDest, int nDataTypeSize, int nDestArrayLength, const char *pDefaultString ) const
  490. {
  491. if ( !IsArrayType( type ) || ( m_Type != type ) )
  492. return;
  493. // NOTE: nDestStride will be 4 for char/short/int values, and the below code is designed to work in all those cases
  494. DmAttributeType_t basicType = ArrayAttributeBasicType( type );
  495. int nSrcStride = CDmxAttribute::AttributeDataSize( basicType );
  496. Assert( nDataTypeSize <= nSrcStride );
  497. nDataTypeSize = MIN( nDataTypeSize, nSrcStride );
  498. int nSrcArrayLength = GetArrayCount();
  499. const void *pSrc = GetArrayBase();
  500. if ( nSrcArrayLength && pSrc )
  501. {
  502. if ( nSrcStride == nDataTypeSize )
  503. {
  504. memcpy( pDest, pSrc, nSrcArrayLength*nDataTypeSize );
  505. }
  506. else
  507. {
  508. byte *pByteDst = (byte *)pDest;
  509. const byte *pByteSrc = (const byte *)pSrc;
  510. for ( int i = 0; i < nSrcArrayLength; i++ )
  511. {
  512. memcpy( pByteDst, pByteSrc, nDataTypeSize );
  513. pByteDst += nDataTypeSize;
  514. pByteSrc += nSrcStride;
  515. }
  516. }
  517. }
  518. if ( ( nSrcArrayLength < nDestArrayLength ) && pDefaultString )
  519. {
  520. CDmxAttribute temp( NULL );
  521. temp.AllocateDataMemory_AndConstruct( basicType );
  522. temp.SetValueFromString( pDefaultString );
  523. byte *pByteDst = ( (byte *)pDest ) + nSrcArrayLength*nDataTypeSize;
  524. for ( int i = nSrcArrayLength; i < nDestArrayLength; i++ )
  525. {
  526. memcpy( pByteDst, temp.m_pData, nDataTypeSize );
  527. pByteDst += nDataTypeSize;
  528. }
  529. }
  530. }
  531. void CDmxAttribute::SetValue( const CDmxAttribute *pAttribute )
  532. {
  533. DmAttributeType_t type = pAttribute->GetType();
  534. if ( !IsArrayType( type ) )
  535. {
  536. SetValue( type, pAttribute->m_pData, CDmxAttribute::AttributeDataSize( type ) );
  537. }
  538. else
  539. {
  540. // Copying array attributes not done yet..
  541. Assert( 0 );
  542. }
  543. }
  544. // Sets the attribute to its default value based on its type
  545. template < class VT, class T >
  546. void CDmxAttribute::SetDefaultValue( void )
  547. {
  548. CDmAttributeInfo< VT >::SetDefaultValue( *(VT *)( m_pData ) );
  549. }
  550. void CDmxAttribute::SetToDefaultValue()
  551. {
  552. // Process array and non-array types, including elements
  553. CALL_TYPE_TEMPLATIZED_FUNCTION( SetDefaultValue, (), );
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Convert to and from string
  557. //-----------------------------------------------------------------------------
  558. void CDmxAttribute::SetValueFromString( const char *pValue )
  559. {
  560. switch ( GetType() )
  561. {
  562. case AT_UNKNOWN:
  563. break;
  564. case AT_STRING:
  565. SetValue( pValue );
  566. break;
  567. default:
  568. {
  569. int nLen = pValue ? Q_strlen( pValue ) : 0;
  570. if ( nLen == 0 )
  571. {
  572. SetToDefaultValue();
  573. break;
  574. }
  575. CUtlBuffer buf( pValue, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
  576. if ( !Unserialize( GetType(), buf ) )
  577. {
  578. SetToDefaultValue();
  579. }
  580. }
  581. break;
  582. }
  583. }
  584. const char *CDmxAttribute::GetValueAsString( char *pBuffer, size_t nBufLen ) const
  585. {
  586. Assert( pBuffer );
  587. CUtlBuffer buf( pBuffer, nBufLen, CUtlBuffer::TEXT_BUFFER );
  588. Serialize( buf );
  589. return pBuffer;
  590. }