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.

521 lines
22 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef DATAMAP_H
  8. #define DATAMAP_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #ifndef VECTOR_H
  13. #include "mathlib/vector.h"
  14. #endif
  15. #include "tier1/utlvector.h"
  16. #include "tier0/memdbgon.h"
  17. // SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes
  18. class SINGLE_INHERITANCE CBaseEntity;
  19. struct inputdata_t;
  20. #define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load
  21. typedef enum _fieldtypes
  22. {
  23. FIELD_VOID = 0, // No type or value
  24. FIELD_FLOAT, // Any floating point value
  25. FIELD_STRING, // A string ID (return from ALLOC_STRING)
  26. FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse
  27. FIELD_QUATERNION, // A quaternion
  28. FIELD_INTEGER, // Any integer or enum
  29. FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
  30. FIELD_SHORT, // 2 byte integer
  31. FIELD_CHARACTER, // a byte
  32. FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color)
  33. FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription
  34. FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions
  35. FIELD_CLASSPTR, // CBaseEntity *
  36. FIELD_EHANDLE, // Entity handle
  37. FIELD_EDICT, // edict_t *
  38. FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically)
  39. FIELD_TIME, // a floating point time (these are fixed up automatically too!)
  40. FIELD_TICK, // an integer tick count( fixed up similarly to time)
  41. FIELD_MODELNAME, // Engine string that is a model name (needs precache)
  42. FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache)
  43. FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar)
  44. FIELD_FUNCTION, // A class function pointer (Think, Use, etc)
  45. FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace)
  46. // NOTE: Use float arrays for local transformations that don't need to be fixed up.
  47. FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions)
  48. FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions)
  49. FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 )
  50. FIELD_MODELINDEX, // a model index
  51. FIELD_MATERIALINDEX, // a material index (using the material precache string table)
  52. FIELD_VECTOR2D, // 2 floats
  53. FIELD_INTEGER64, // 64bit integer
  54. FIELD_VECTOR4D, // 4 floats
  55. FIELD_TYPECOUNT, // MUST BE LAST
  56. } fieldtype_t;
  57. //-----------------------------------------------------------------------------
  58. // Field sizes...
  59. //-----------------------------------------------------------------------------
  60. template <int FIELD_TYPE>
  61. class CDatamapFieldSizeDeducer
  62. {
  63. public:
  64. enum
  65. {
  66. SIZE = 0
  67. };
  68. static int FieldSize( )
  69. {
  70. return 0;
  71. }
  72. };
  73. #define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \
  74. template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } };
  75. #define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE
  76. #define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8)
  77. DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) )
  78. DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) )
  79. DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) )
  80. DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) )
  81. DECLARE_FIELD_SIZE( FIELD_VECTOR4D, 4 * sizeof( float ) )
  82. DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float))
  83. DECLARE_FIELD_SIZE( FIELD_INTEGER, sizeof(int))
  84. DECLARE_FIELD_SIZE( FIELD_INTEGER64, sizeof(int64))
  85. DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char))
  86. DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short))
  87. DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char))
  88. DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int))
  89. DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int))
  90. DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int))
  91. DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int))
  92. DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float))
  93. DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float))
  94. DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int))
  95. DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int))
  96. DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int))
  97. DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int))
  98. #if defined(_WIN32)
  99. DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(void *))
  100. #elif defined(POSIX)
  101. // pointer to members under gnuc are 8bytes if you have a virtual func
  102. DECLARE_FIELD_SIZE( FIELD_FUNCTION, 2 * sizeof(void *))
  103. #else
  104. #error
  105. #endif
  106. DECLARE_FIELD_SIZE( FIELD_VMATRIX, 16 * sizeof(float))
  107. DECLARE_FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float))
  108. DECLARE_FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float))
  109. DECLARE_FIELD_SIZE( FIELD_INTERVAL, 2 * sizeof( float) ) // NOTE: Must match interval.h definition
  110. DECLARE_FIELD_SIZE( FIELD_MODELINDEX, sizeof(int) )
  111. DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX, sizeof(int) )
  112. #define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0]))
  113. #define SIZE_OF_ARRAY(p) _ARRAYSIZE(p)
  114. #define _FIELD(name,fieldtype,count,flags,mapname,tolerance) { fieldtype, #name, offsetof(classNameTypedef, name), count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance }
  115. #define DEFINE_FIELD_NULL { FIELD_VOID,0,0,0,0,0,0,0,0}
  116. #define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 )
  117. #define DEFINE_FIELD_NOT_SAVED(name,fieldtype) _FIELD(name, fieldtype, 1, 0, NULL, 0 )
  118. #define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
  119. #define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 )
  120. #define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
  121. #define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 )
  122. #define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 )
  123. #define DEFINE_ARRAY_NOT_SAVED(name,fieldtype, count) _FIELD(name, fieldtype, count, 0, NULL, 0 )
  124. #define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 )
  125. #define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 )
  126. #define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 )
  127. #define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
  128. #define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL }
  129. #define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL }
  130. #define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
  131. // Used by byteswap datadescs
  132. #define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) )
  133. #define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 )
  134. #define DEFINE_EMBEDDED( name ) \
  135. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
  136. #define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \
  137. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
  138. #define DEFINE_EMBEDDEDBYREF( name ) \
  139. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f }
  140. #define DEFINE_EMBEDDED_ARRAY( name, count ) \
  141. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
  142. #define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \
  143. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
  144. #ifndef NO_ENTITY_PREDICTION
  145. // FTYPEDESC_KEY tells the prediction copy system to report the full nameof the field when reporting errors
  146. #define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \
  147. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, NULL, NULL, NULL, &fieldtype::m_PredMap }
  148. #define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \
  149. { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_PTR | FTYPEDESC_KEY, NULL, NULL, NULL, &fieldtype::m_PredMap }
  150. #else
  151. #define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL
  152. #define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL
  153. #endif
  154. // Extensions to datamap.h macros for predicted entities only
  155. #define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f )
  156. #define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f )
  157. #define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f )
  158. // Predictable macros, which include a tolerance for floating point values...
  159. #define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance )
  160. #define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance)
  161. #define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance )
  162. //#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname )
  163. // INPUTS
  164. #define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) }
  165. #define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, 0, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast <inputfunc_t> (&classNameTypedef::inputfunc) }
  166. // OUTPUTS
  167. // the variable 'name' MUST BE derived from CBaseOutput
  168. // we know the output type from the variable itself, so it doesn't need to be specified here
  169. class ISaveRestoreOps;
  170. extern ISaveRestoreOps *eventFuncs;
  171. #define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs }
  172. // replaces EXPORT table for portability and non-DLL based systems (xbox)
  173. #define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), 0, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) }
  174. #define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t )
  175. #define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore
  176. #define FTYPEDESC_SAVE 0x0002 // This field is saved to disk
  177. #define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time
  178. #define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called
  179. #define FTYPEDESC_OUTPUT 0x0010 // This field propogates it's value to all targets whenever it changes
  180. #define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer
  181. #define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object
  182. #define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now)
  183. // Flags used by other systems (e.g., prediction system)
  184. #define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable
  185. #define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking)
  186. #define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors
  187. #define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output)
  188. #define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping.
  189. // These flags apply to C_BasePlayer derived objects only
  190. #define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself),
  191. // but if this is set, then we allow you to see fields on other players
  192. #define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player
  193. #define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual)
  194. #define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info
  195. struct typedescription_t;
  196. class ISaveRestoreOps;
  197. //
  198. // Function prototype for all input handlers.
  199. //
  200. typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data);
  201. struct datamap_t;
  202. struct typedescription_t;
  203. enum
  204. {
  205. PC_NON_NETWORKED_ONLY = 0,
  206. PC_NETWORKED_ONLY,
  207. PC_COPYTYPE_COUNT,
  208. PC_EVERYTHING = PC_COPYTYPE_COUNT,
  209. };
  210. enum
  211. {
  212. TD_OFFSET_NORMAL = 0,
  213. TD_OFFSET_PACKED = 1,
  214. // Must be last
  215. TD_OFFSET_COUNT,
  216. };
  217. struct typedescription_t
  218. {
  219. fieldtype_t fieldType;
  220. const char *fieldName;
  221. int fieldOffset; // Local offset value
  222. unsigned short fieldSize;
  223. short flags;
  224. // the name of the variable in the map/fgd data, or the name of the action
  225. const char *externalName;
  226. // pointer to the function set for save/restoring of custom data types
  227. ISaveRestoreOps *pSaveRestoreOps;
  228. // for associating function with string names
  229. inputfunc_t inputFunc;
  230. // For embedding additional datatables inside this one
  231. datamap_t *td;
  232. // Stores the actual member variable size in bytes
  233. int fieldSizeInBytes;
  234. // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred
  235. struct typedescription_t *override_field;
  236. // Used to track exclusion of baseclass fields
  237. int override_count;
  238. // Tolerance for field errors for float fields
  239. float fieldTolerance;
  240. // For raw fields (including children of embedded stuff) this is the flattened offset
  241. int flatOffset[ TD_OFFSET_COUNT ];
  242. unsigned short flatGroup;
  243. };
  244. // See predictioncopy.h for implementation and notes
  245. struct optimized_datamap_t;
  246. //-----------------------------------------------------------------------------
  247. // Purpose: stores the list of objects in the hierarchy
  248. // used to iterate through an object's data descriptions
  249. //-----------------------------------------------------------------------------
  250. struct datamap_t
  251. {
  252. typedescription_t *dataDesc;
  253. int dataNumFields;
  254. char const *dataClassName;
  255. datamap_t *baseMap;
  256. int m_nPackedSize;
  257. optimized_datamap_t *m_pOptimizedDataMap;
  258. #if defined( _DEBUG )
  259. bool bValidityChecked;
  260. #endif // _DEBUG
  261. };
  262. //-----------------------------------------------------------------------------
  263. //
  264. // Macros used to implement datadescs
  265. //
  266. #define DECLARE_FRIEND_DATADESC_ACCESS() \
  267. template <typename T> friend void DataMapAccess(T *, datamap_t **p); \
  268. template <typename T> friend datamap_t *DataMapInit(T *);
  269. #define DECLARE_SIMPLE_DATADESC() \
  270. static datamap_t m_DataMap; \
  271. static datamap_t *GetBaseMap(); \
  272. template <typename T> friend void DataMapAccess(T *, datamap_t **p); \
  273. template <typename T> friend datamap_t *DataMapInit(T *);
  274. #if defined(POSIX) && !defined(_PS3)
  275. #define DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() \
  276. static datamap_t m_DataMap; \
  277. static datamap_t *GetBaseMap(); \
  278. template <typename T> friend void ::DataMapAccess(T *, datamap_t **p);
  279. #else
  280. #define DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() \
  281. static datamap_t m_DataMap; \
  282. static datamap_t *GetBaseMap(); \
  283. template <typename T> friend void ::DataMapAccess(T *, datamap_t **p); \
  284. template <typename T> friend datamap_t *::DataMapInit(T *);
  285. #endif
  286. #define DECLARE_DATADESC() \
  287. DECLARE_SIMPLE_DATADESC() \
  288. virtual datamap_t *GetDataDescMap( void );
  289. #define BEGIN_DATADESC( className ) \
  290. datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
  291. datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
  292. datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
  293. BEGIN_DATADESC_GUTS( className )
  294. #define BEGIN_DATADESC_NO_BASE( className ) \
  295. datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
  296. datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
  297. datamap_t *className::GetBaseMap() { return NULL; } \
  298. BEGIN_DATADESC_GUTS( className )
  299. #define BEGIN_SIMPLE_DATADESC( className ) \
  300. datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
  301. datamap_t *className::GetBaseMap() { return NULL; } \
  302. BEGIN_DATADESC_GUTS( className )
  303. #define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \
  304. datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
  305. datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
  306. BEGIN_DATADESC_GUTS( className )
  307. #define BEGIN_DATADESC_GUTS( className ) \
  308. template <typename T> datamap_t *DataMapInit(T *); \
  309. template <> datamap_t *DataMapInit<className>( className * ); \
  310. namespace className##_DataDescInit \
  311. { \
  312. datamap_t *g_DataMapHolder = DataMapInit<className>( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
  313. } \
  314. \
  315. template <> datamap_t *DataMapInit<className>( className * ) \
  316. { \
  317. typedef className classNameTypedef; \
  318. static CDatadescGeneratedNameHolder nameHolder(#className); \
  319. className::m_DataMap.baseMap = className::GetBaseMap(); \
  320. static typedescription_t dataDesc[] = \
  321. { \
  322. { FIELD_VOID,0,0,0,0,0,0,0,0}, /* so you can define "empty" tables */
  323. #define BEGIN_DATADESC_GUTS_NAMESPACE( className, nameSpace ) \
  324. template <typename T> datamap_t *nameSpace::DataMapInit(T *); \
  325. template <> datamap_t *nameSpace::DataMapInit<className>( className * ); \
  326. namespace className##_DataDescInit \
  327. { \
  328. datamap_t *g_DataMapHolder = nameSpace::DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
  329. } \
  330. \
  331. template <> datamap_t *nameSpace::DataMapInit<className>( className * ) \
  332. { \
  333. typedef className classNameTypedef; \
  334. static CDatadescGeneratedNameHolder nameHolder(#className); \
  335. className::m_DataMap.baseMap = className::GetBaseMap(); \
  336. static typedescription_t dataDesc[] = \
  337. { \
  338. { FIELD_VOID,0,0,0,0,0,0,0,0}, /* so you can define "empty" tables */
  339. #define END_DATADESC() \
  340. }; \
  341. \
  342. if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \
  343. { \
  344. classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \
  345. classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \
  346. } \
  347. else \
  348. { \
  349. classNameTypedef::m_DataMap.dataNumFields = 1; \
  350. classNameTypedef::m_DataMap.dataDesc = dataDesc; \
  351. } \
  352. return &classNameTypedef::m_DataMap; \
  353. }
  354. // used for when there is no data description
  355. #define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \
  356. BEGIN_SIMPLE_DATADESC( derivedClass ) \
  357. END_DATADESC()
  358. #define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \
  359. BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \
  360. END_DATADESC()
  361. #define IMPLEMENT_NULL_DATADESC( derivedClass ) \
  362. BEGIN_DATADESC( derivedClass ) \
  363. END_DATADESC()
  364. // helps get the offset of a bitfield
  365. #define BEGIN_BITFIELD( name ) \
  366. union \
  367. { \
  368. char name; \
  369. struct \
  370. {
  371. #define END_BITFIELD() \
  372. }; \
  373. };
  374. //-----------------------------------------------------------------------------
  375. // Forward compatability with potential seperate byteswap datadescs
  376. #define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC()
  377. #define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name)
  378. #define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base)
  379. #define END_BYTESWAP_DATADESC() END_DATADESC()
  380. //-----------------------------------------------------------------------------
  381. template <typename T>
  382. inline void DataMapAccess(T *ignored, datamap_t **p)
  383. {
  384. *p = &T::m_DataMap;
  385. }
  386. //-----------------------------------------------------------------------------
  387. class CDatadescGeneratedNameHolder
  388. {
  389. public:
  390. explicit CDatadescGeneratedNameHolder( const char *pszBase )
  391. : m_pszBase(pszBase)
  392. {
  393. m_nLenBase = strlen( m_pszBase );
  394. }
  395. ~CDatadescGeneratedNameHolder()
  396. {
  397. for ( int i = 0; i < m_Names.Count(); i++ )
  398. {
  399. delete m_Names[i];
  400. }
  401. }
  402. const char *GenerateName( const char *pszIdentifier )
  403. {
  404. char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1];
  405. strcpy( pBuf, m_pszBase );
  406. strcat( pBuf, pszIdentifier );
  407. m_Names.AddToTail( pBuf );
  408. return pBuf;
  409. }
  410. private:
  411. const char *m_pszBase;
  412. size_t m_nLenBase;
  413. CUtlVector<char *> m_Names;
  414. };
  415. //-----------------------------------------------------------------------------
  416. // Compiler can require the global-namespace template friend to be declared
  417. // before DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() can be used
  418. template <typename T> datamap_t *DataMapInit(T *);
  419. #include "tier0/memdbgoff.h"
  420. #endif // DATAMAP_H