Team Fortress 2 Source Code as on 22/4/2020
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.

467 lines
13 KiB

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