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.

157 lines
6.0 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "dt_utlvector_recv.h"
  9. #include "tier0/memdbgon.h"
  10. extern char *s_ClientElementNames[MAX_ARRAY_ELEMENTS];
  11. class CRecvPropExtra_UtlVector
  12. {
  13. public:
  14. DataTableRecvVarProxyFn m_DataTableProxyFn; // If it's a datatable, then this is the proxy they specified.
  15. RecvVarProxyFn m_ProxyFn; // If it's a non-datatable, then this is the proxy they specified.
  16. ResizeUtlVectorFn m_ResizeFn; // The function used to resize the CUtlVector.
  17. EnsureCapacityFn m_EnsureCapacityFn;
  18. int m_ElementStride; // Distance between each element in the array.
  19. int m_Offset; // Offset of the CUtlVector from its parent structure.
  20. int m_nMaxElements; // For debugging...
  21. };
  22. void RecvProxy_UtlVectorLength( const CRecvProxyData *pData, void *pStruct, void *pOut )
  23. {
  24. CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pData->m_pRecvProp->GetExtraData();
  25. pExtra->m_ResizeFn( pStruct, pExtra->m_Offset, pData->m_Value.m_Int );
  26. }
  27. void RecvProxy_UtlVectorElement( const CRecvProxyData *pData, void *pStruct, void *pOut )
  28. {
  29. CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pData->m_pRecvProp->GetExtraData();
  30. // Kind of lame overloading element stride to hold the element index,
  31. // but we can easily move it into its SetExtraData stuff if we need to.
  32. int iElement = pData->m_pRecvProp->GetElementStride();
  33. // NOTE: this is cheesy, but it does the trick.
  34. CUtlVector<int> *pUtlVec = (CUtlVector<int>*)((char*)pStruct + pExtra->m_Offset);
  35. // Call through to the proxy they passed in, making pStruct=the CUtlVector.
  36. // Note: there should be space here as long as the element is < the max # elements
  37. // that we ensured capacity for in DataTableRecvProxy_LengthProxy.
  38. pExtra->m_ProxyFn( pData, pOut, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride );
  39. }
  40. void RecvProxy_UtlVectorElement_DataTable( const RecvProp *pProp, void **pOut, void *pData, int objectID )
  41. {
  42. CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pProp->GetExtraData();
  43. int iElement = pProp->GetElementStride();
  44. Assert( iElement < pExtra->m_nMaxElements );
  45. // NOTE: this is cheesy, but it does the trick.
  46. CUtlVector<int> *pUtlVec = (CUtlVector<int>*)((char*)pData + pExtra->m_Offset);
  47. // Call through to the proxy they passed in, making pStruct=the CUtlVector and forcing iElement to 0.
  48. pExtra->m_DataTableProxyFn( pProp, pOut, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride, objectID );
  49. }
  50. void DataTableRecvProxy_LengthProxy( const RecvProp *pProp, void **pOut, void *pData, int objectID )
  51. {
  52. // This is VERY important - since it calls all the datatable proxies in the tree first,
  53. // particularly BEFORE it calls our array length proxy, we need to make sure we return
  54. // valid pointers that aren't going to change when it starts to copy the data into
  55. // the datatable elements.
  56. CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pProp->GetExtraData();
  57. pExtra->m_EnsureCapacityFn( pData, pExtra->m_Offset, pExtra->m_nMaxElements );
  58. *pOut = pData;
  59. }
  60. RecvProp RecvPropUtlVector(
  61. char *pVarName, // Use RECVINFO_UTLVECTOR to generate these 4.
  62. int offset, // Used to generate pData in the function specified in varProxy.
  63. int sizeofVar, // The size of each element in the utlvector.
  64. ResizeUtlVectorFn fn,
  65. EnsureCapacityFn ensureFn,
  66. int nMaxElements, // Max # of elements in the array. Keep this as low as possible.
  67. RecvProp pArrayProp
  68. )
  69. {
  70. RecvProp ret;
  71. Assert( nMaxElements <= MAX_ARRAY_ELEMENTS );
  72. ret.m_RecvType = DPT_DataTable;
  73. ret.m_pVarName = pVarName;
  74. ret.SetOffset( 0 );
  75. ret.SetDataTableProxyFn( DataTableRecvProxy_StaticDataTable );
  76. RecvProp *pProps = new RecvProp[nMaxElements+1]; // TODO free that again
  77. // Extra data bound to each of the properties.
  78. CRecvPropExtra_UtlVector *pExtraData = new CRecvPropExtra_UtlVector;
  79. pExtraData->m_nMaxElements = nMaxElements;
  80. pExtraData->m_ElementStride = sizeofVar;
  81. pExtraData->m_ResizeFn = fn;
  82. pExtraData->m_EnsureCapacityFn = ensureFn;
  83. pExtraData->m_Offset = offset;
  84. if ( pArrayProp.m_RecvType == DPT_DataTable )
  85. pExtraData->m_DataTableProxyFn = pArrayProp.GetDataTableProxyFn();
  86. else
  87. pExtraData->m_ProxyFn = pArrayProp.GetProxyFn();
  88. // The first property is datatable with an int that tells the length of the array.
  89. // It has to go in a datatable, otherwise if this array holds datatable properties, it will be received last.
  90. RecvProp *pLengthProp = new RecvProp;
  91. *pLengthProp = RecvPropInt( AllocateStringHelper( "lengthprop%d", nMaxElements ), 0, 0, 0, RecvProxy_UtlVectorLength );
  92. pLengthProp->SetExtraData( pExtraData );
  93. char *pLengthProxyTableName = AllocateUniqueDataTableName( false, "_LPT_%s_%d", pVarName, nMaxElements );
  94. RecvTable *pLengthTable = new RecvTable( pLengthProp, 1, pLengthProxyTableName );
  95. pProps[0] = RecvPropDataTable( "lengthproxy", 0, 0, pLengthTable, DataTableRecvProxy_LengthProxy );
  96. pProps[0].SetExtraData( pExtraData );
  97. // The first element is a sub-datatable.
  98. for ( int i = 1; i < nMaxElements+1; i++ )
  99. {
  100. pProps[i] = pArrayProp; // copy array element property setting
  101. pProps[i].SetOffset( 0 ); // leave offset at 0 so pStructBase is always a pointer to the CUtlVector
  102. pProps[i].m_pVarName = s_ClientElementNames[i-1]; // give unique name
  103. pProps[i].SetExtraData( pExtraData );
  104. pProps[i].SetElementStride( i-1 ); // Kind of lame overloading element stride to hold the element index,
  105. // but we can easily move it into its SetExtraData stuff if we need to.
  106. // We provide our own proxy here.
  107. if ( pArrayProp.m_RecvType == DPT_DataTable )
  108. {
  109. pProps[i].SetDataTableProxyFn( RecvProxy_UtlVectorElement_DataTable );
  110. }
  111. else
  112. {
  113. pProps[i].SetProxyFn( RecvProxy_UtlVectorElement );
  114. }
  115. }
  116. RecvTable *pTable = new RecvTable(
  117. pProps,
  118. nMaxElements+1,
  119. AllocateUniqueDataTableName( false, "_ST_%s_%d", pVarName, nMaxElements )
  120. ); // TODO free that again
  121. ret.SetDataTable( pTable );
  122. return ret;
  123. }