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.

452 lines
13 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #ifndef GCRECORD_H
  8. #define GCRECORD_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "schema.h"
  13. #include "tier0/memdbgon.h"
  14. namespace GCSDK
  15. {
  16. #pragma pack( push, 1 )
  17. class CRecordInfo;
  18. //-----------------------------------------------------------------------------
  19. // VarFieldBlockInfo_t
  20. // Tracks a block of memory used to hold all the variable-length
  21. // fields for a record.
  22. //-----------------------------------------------------------------------------
  23. struct VarFieldBlockInfo_t
  24. {
  25. union
  26. {
  27. // Take up 64-bits of space now even though
  28. // pointers are still 32 bits
  29. uint8* m_pubBlock;
  30. uint64 _unused;
  31. };
  32. uint32 m_cubBlock; // how much is in this block?
  33. uint32 m_cubBlockFree; // how much in this block is free?
  34. };
  35. //-----------------------------------------------------------------------------
  36. // VarField_t
  37. // Data format for a variable field entry in a DS record
  38. // For leaf code, is hidden inside a CVarField or CVarCharField
  39. //-----------------------------------------------------------------------------
  40. struct VarField_t
  41. {
  42. uint32 m_cubField; // Size of the field
  43. uint32 m_dubOffset; // Offset of the field within the block
  44. };
  45. //-----------------------------------------------------------------------------
  46. // CVarField
  47. // Defines a class to encompass a variable-length field - opaque
  48. //-----------------------------------------------------------------------------
  49. class CVarField : private VarField_t
  50. {
  51. public:
  52. friend class CRecordVar;
  53. private:
  54. };
  55. //-----------------------------------------------------------------------------
  56. // CVarCharField
  57. // Defines a class to encompass a variable-length string field - opaque
  58. //-----------------------------------------------------------------------------
  59. class CVarCharField : public CVarField
  60. {
  61. public:
  62. friend class CRecordVar;
  63. };
  64. //-----------------------------------------------------------------------------
  65. // CVarCharField
  66. // Defines a class to encompass a variable-length string field - opaque
  67. //-----------------------------------------------------------------------------
  68. class CVarBinaryField : public CVarField
  69. {
  70. public:
  71. friend class CRecordVar;
  72. };
  73. #pragma pack( pop )
  74. // fix the size of this just to be safe
  75. #pragma pack( push, 4 )
  76. class CSchema;
  77. //-----------------------------------------------------------------------------
  78. // CRecordBase
  79. // Defines a class which arbitrates access to a fixed-length record
  80. //
  81. // This is used as a base class for the CSchTable wrapper classes emitted
  82. // by the schema compiler when the involved table has no variable length data.
  83. //-----------------------------------------------------------------------------
  84. class CRecordBase
  85. {
  86. public:
  87. // These both allocate new space and COPY the record data into it
  88. CRecordBase( const CRecordBase &that );
  89. CRecordBase &operator=(const CRecordBase &that);
  90. // Init from general memory
  91. int InitFromBytes( uint8 *pubRecord );
  92. virtual ~CRecordBase();
  93. // Use these when sending records over the wire
  94. uint32 CubSerialized();
  95. virtual uint8 *PubRecordFixed();
  96. const uint8 *PubRecordFixed() const;
  97. uint32 CubRecordFixed() const;
  98. virtual uint8 *PubRecordVarBlock();
  99. virtual const uint8 *PubRecordVarBlock() const;
  100. uint32 CubRecordVarBlock() const;
  101. bool BAssureRecordVarStorage( uint32 cVariableBytes );
  102. // generic data accessors
  103. bool BGetField( int iField, uint8 **ppubData, uint32 *pcubField ) const;
  104. virtual bool BSetField( int iField, void * pvData, uint32 cubData );
  105. virtual void WipeField( int iField );
  106. // data accessors
  107. const char * GetStringField( int iField, uint32 *pcubField );
  108. int GetInt( int iField );
  109. uint32 GetUint32( int iField );
  110. uint64 GetUint64( int iField );
  111. // variable length data accessors
  112. // (not implemented by this class)
  113. virtual const char *ReadVarCharField( const CVarCharField &field ) const;
  114. virtual const uint8 *ReadVarDataField( const CVarField &field, uint32 *pcubField ) const;
  115. virtual bool SetVarCharField( CVarCharField &field, const char *pchString );
  116. virtual void SetVarDataField( CVarField &field, const void *pvData, uint32 cubData );
  117. virtual const CSchema *GetPSchema() const
  118. {
  119. return const_cast<CRecordBase*>(this)->GetPSchema();
  120. }
  121. virtual CSchema *GetPSchema();
  122. const CRecordInfo *GetPRecordInfo() const;
  123. // implemented by CSch-something derivatives
  124. virtual int GetITable() const = 0;
  125. void RenderField( uint32 unColumn, int cchBuffer, char *pchBuffer ) const;
  126. #ifdef DBGFLAG_VALIDATE
  127. void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  128. static void ValidateStatics( CValidator &validator, const char *pchName );
  129. #endif // DBGFLAG_VALIDATE
  130. protected:
  131. // copies the contents of the record. The assignement operator uses this internally
  132. virtual void Copy( const CRecordBase & that );
  133. CSchema *GetPSchemaImpl();
  134. void Cleanup();
  135. bool BSetField( int iField, void *pvData, uint32 cubData, bool *pbRealloced );
  136. // ctor for derived classes, CSch*
  137. CRecordBase( ) { }
  138. };
  139. //-----------------------------------------------------------------------------
  140. // CRecordVar
  141. // Defines a class which arbitrates access to a variable-length record
  142. //
  143. // This is used as a base class for the CSchTable wrapper classes emitted
  144. // by the schema compiler when the involved table *does* have variable-length data
  145. //-----------------------------------------------------------------------------
  146. class CRecordVar : public CRecordBase
  147. {
  148. public:
  149. CRecordVar( )
  150. {
  151. m_pSchema = NULL;
  152. m_nFlags = 0;
  153. }
  154. virtual ~CRecordVar()
  155. {
  156. Cleanup();
  157. }
  158. virtual uint8* PubRecordFixed();
  159. const uint8 *PubRecordFixed() const;
  160. virtual CSchema *GetPSchema()
  161. {
  162. return m_pSchema;
  163. }
  164. virtual const CSchema *GetPSchema() const
  165. {
  166. return m_pSchema;
  167. }
  168. // Init from general memory
  169. int InitFromBytes( uint8 *pubRecord );
  170. // generic data accessors
  171. virtual bool BSetField( int iField, void * pvData, uint32 cubData );
  172. virtual void WipeField( int iField );
  173. // variable-length data accessors
  174. virtual const char *ReadVarCharField( const CVarCharField &field ) const;
  175. virtual const uint8 *ReadVarDataField( const CVarField &field, uint32 *pcubField ) const;
  176. virtual bool SetVarCharField( CVarCharField &field, const char *pchString );
  177. virtual void SetVarDataField( CVarField &field, const void *pvData, uint32 cubData );
  178. // allocated fixed means we've got our own memory for the fixed record
  179. // allocated var block means we've allocated a block for the variable part of this record
  180. enum EFlags { k_EAllocatedFixed = 0x1, k_EAllocatedVarBlock = 0x2 };
  181. bool BFlagSet( int eFlag ) const;
  182. #ifdef DBGFLAG_VALIDATE
  183. void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  184. #endif // DBGFLAG_VALIDATE
  185. protected:
  186. // copies the contents of the record. The assignement operator uses this internally
  187. virtual void Copy( const CRecordBase & that );
  188. // initialization helper
  189. void DoInit()
  190. {
  191. m_pSchema = CRecordBase::GetPSchema();
  192. }
  193. void SetFlag( int eFlag, bool bSet );
  194. void Cleanup();
  195. CSchema *m_pSchema; // Corresponding Schema
  196. int m_nFlags; // Flags about the record memory allocations / location
  197. };
  198. //-----------------------------------------------------------------------------
  199. // CRecordExternal
  200. // Defines a class which arbitrates access to a variable-length record
  201. //
  202. // This is used as an accessor for a polymorphic record. It can be used to
  203. // read CSchTable records when the type is unknown, manipulate stats records,
  204. // or touch data that isn't preallocated. Its use is relatively rare.
  205. //-----------------------------------------------------------------------------
  206. class CRecordExternal : public CRecordVar
  207. {
  208. public:
  209. CRecordExternal()
  210. {
  211. m_pubRecordFixedExternal = NULL;
  212. m_nFlags = 0;
  213. }
  214. virtual ~CRecordExternal()
  215. {
  216. Cleanup();
  217. }
  218. virtual uint8* PubRecordFixed();
  219. const uint8 *PubRecordFixed() const;
  220. void DeSerialize( uint8 *pubData );
  221. int GetITable() const
  222. {
  223. return -1;
  224. }
  225. void Init( CSchema *pSchema );
  226. int Init( CSchema *pSchema, uint8 *pubRecord, bool bTakeOwnership );
  227. // test helpers
  228. void InitRecordRandom( uint32 unPrimaryIndex );
  229. void SetFieldRandom( int iField );
  230. #ifdef DBGFLAG_VALIDATE
  231. void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  232. #endif // DBGFLAG_VALIDATE
  233. protected:
  234. // copies the contents of the record. The assignement operator uses this internally
  235. virtual void Copy( const CRecordBase & that );
  236. void Cleanup();
  237. void DoInit()
  238. {
  239. m_pSchema = CRecordBase::GetPSchema();
  240. }
  241. uint8 *m_pubRecordFixedExternal; // If the fixed record is not a part of this object,
  242. // this points to where it is
  243. CSchema *GetPSchemaImpl();
  244. };
  245. //-----------------------------------------------------------------------------
  246. // Accessors for variable length character data.
  247. // These goofy little macros implement some syntax sugar
  248. //-----------------------------------------------------------------------------
  249. #define READ_VAR_CHAR_FIELD( record, field )\
  250. (record).ReadVarCharField( (record).field )
  251. #define WRITE_VAR_CHAR_FIELD( record, field, text )\
  252. (record).SetVarCharField( (record).field, text )
  253. #pragma pack( pop )
  254. //-----------------------------------------------------------------------------
  255. // Template classes that get a LessFunc that sorts CRecordBases by a field
  256. // within them
  257. //-----------------------------------------------------------------------------
  258. template <class T, int I, typename F>
  259. class CDefSchOps
  260. {
  261. public:
  262. static bool LessFunc( const T &lhs, const T &rhs )
  263. {
  264. // Check that the field number is valid
  265. COMPILE_TIME_ASSERT( I >= 0 && I < T::k_iFieldMax );
  266. // Check to make sure this is a fixed field
  267. const Field_t &fieldInfo = lhs.GetPSchema()->GetField( I );
  268. Assert( !fieldInfo.BIsStringType() && !fieldInfo.BIsVariableLength() );
  269. if ( fieldInfo.BIsStringType() || fieldInfo.BIsVariableLength() )
  270. return false;
  271. // Read the data and make sure the sizes are correct for the field type we expect
  272. uint8 *pubLhs;
  273. uint8 *pubRhs;
  274. bool bRet;
  275. uint32 cubRead;
  276. bRet = lhs.BGetField( I, &pubLhs, &cubRead );
  277. Assert( bRet && cubRead == sizeof( F ) );
  278. if ( !bRet || cubRead != sizeof( F ) )
  279. return false;
  280. bRet = rhs.BGetField( I, &pubRhs, &cubRead );
  281. Assert( bRet && cubRead == sizeof( F ) );
  282. if ( !bRet || cubRead != sizeof( F ) )
  283. return false;
  284. // Finally do the comparison
  285. return ( *( (F *)pubLhs ) ) < ( *( (F *)pubRhs ) );
  286. }
  287. static bool LessFuncCtx( const T &lhs, const T &rhs, void *pCtx )
  288. {
  289. return LessFunc( lhs, rhs );
  290. }
  291. };
  292. #define DefSchLessFunc( RecordType, FieldIndex, FieldType ) CDefSchOps<RecordType, FieldIndex, FieldType>::LessFunc
  293. #define DefSchLessFuncCtx( RecordType, FieldIndex, FieldType ) CDefSchOps<RecordType, FieldIndex, FieldType>::LessFuncCtx
  294. //-----------------------------------------------------------------------------
  295. // Specializations for string fields
  296. //-----------------------------------------------------------------------------
  297. template <class T, int I>
  298. class CDefSchOps<T, I, char *>
  299. {
  300. public:
  301. static bool LessFunc( const T &lhs, const T &rhs )
  302. {
  303. // Check that the field number is valid
  304. COMPILE_TIME_ASSERT( I >= 0 && I < T::k_iFieldMax );
  305. // Check to make sure this is indeed a string field
  306. Field_t &fieldInfo = lhs.GetPSchema()->GetField( I );
  307. Assert( fieldInfo.BIsStringType() );
  308. if ( !fieldInfo.BIsStringType() )
  309. return false;
  310. // Read the data
  311. uint32 cubRead;
  312. const char *pchLhs = lhs.GetStringField( I, &cubRead );
  313. const char *pchRhs = rhs.GetStringField( I, &cubRead );
  314. // Finally do the comparison
  315. return CDefOps<const char *>::LessFunc( lhs, rhs );
  316. }
  317. static bool LessFuncCtx( const T &lhs, const T &rhs, void *pCtx )
  318. {
  319. return LessFunc( lhs, rhs );
  320. }
  321. };
  322. template <class T, int I>
  323. class CDefSchOps<T, I, const char *>
  324. {
  325. public:
  326. static bool LessFunc( const T &lhs, const T &rhs )
  327. {
  328. return CDefSchOps<T, I, char *>::LessFunc( lhs, rhs );
  329. }
  330. static bool LessFuncCtx( const T &lhs, const T &rhs, void *pCtx )
  331. {
  332. return LessFunc( lhs, rhs );
  333. }
  334. };
  335. //-----------------------------------------------------------------------------
  336. // Purpose: Provide a convenient object to pass around to represent a type
  337. // of record
  338. //-----------------------------------------------------------------------------
  339. class CRecordType
  340. {
  341. public:
  342. virtual int GetITable() const = 0;
  343. virtual CRecordBase *Create() const = 0;
  344. CSchema *GetSchema() const;
  345. CRecordInfo *GetRecordInfo() const;
  346. protected:
  347. private:
  348. };
  349. template <typename TRecord>
  350. class CRecordTypeConcrete: public CRecordType
  351. {
  352. public:
  353. virtual int GetITable() const { return TRecord::k_iTable; }
  354. virtual CRecordBase *Create() const { return new TRecord(); }
  355. };
  356. #define RTYPE( recordClass ) CRecordTypeConcrete<recordClass>()
  357. } // namespace GCSDK
  358. #include "tier0/memdbgoff.h"
  359. #endif // GCRECORD_H