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.

856 lines
27 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "stdafx.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. namespace GCSDK
  11. {
  12. //-----------------------------------------------------------------------------
  13. // Purpose: Destructor
  14. //-----------------------------------------------------------------------------
  15. CRecordBase::~CRecordBase()
  16. {
  17. Cleanup();
  18. }
  19. //-----------------------------------------------------------------------------
  20. // Purpose: Copy constructor
  21. // Input: that - CRecord to copy from
  22. //-----------------------------------------------------------------------------
  23. CRecordBase::CRecordBase( const CRecordBase &that )
  24. {
  25. *this = that;
  26. }
  27. //-----------------------------------------------------------------------------
  28. // Purpose: Assignment operator - COPIES the record data
  29. // Input: that - CRecord to copy from
  30. //-----------------------------------------------------------------------------
  31. CRecordBase& CRecordBase::operator = ( const CRecordBase & that )
  32. {
  33. Assert( GetITable() == that.GetITable() );
  34. // COPY that record
  35. Copy( that );
  36. return *this;
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Purpose: Copies the data in the record. This is overridden by CRecordVar and
  40. // CRecordExternal
  41. // Input: that - CRecord to copy from
  42. //-----------------------------------------------------------------------------
  43. void CRecordBase::Copy( const CRecordBase & that )
  44. {
  45. Cleanup();
  46. Q_memcpy( PubRecordFixed(), that.PubRecordFixed(), GetPSchema()->CubRecordFixed() );
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose: Return the record info for this record's schema
  50. //-----------------------------------------------------------------------------
  51. const CRecordInfo *CRecordBase::GetPRecordInfo() const
  52. {
  53. return GetPSchema()->GetRecordInfo();
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Copies the data in the var record.
  57. // Input: that - CRecord to copy from
  58. //-----------------------------------------------------------------------------
  59. void CRecordVar::Copy( const CRecordBase & baseThat )
  60. {
  61. const CRecordVar & that = (const CRecordVar &)baseThat;
  62. // COPY that record
  63. Cleanup();
  64. m_pSchema = that.m_pSchema;
  65. Q_memcpy( PubRecordFixed(), that.PubRecordFixed(), GetPSchema()->CubRecordFixed() );
  66. SetFlag( k_EAllocatedVarBlock, false );
  67. if ( VarFieldBlockInfo_t *pVarBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) )
  68. {
  69. if ( pVarBlockInfo->m_cubBlock )
  70. {
  71. void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock );
  72. Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock );
  73. pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock;
  74. SetFlag( k_EAllocatedVarBlock, true );
  75. }
  76. }
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Copies the data in the var record.
  80. // Input: that - CRecord to copy from
  81. //-----------------------------------------------------------------------------
  82. void CRecordExternal::Copy( const CRecordBase & baseThat )
  83. {
  84. const CRecordExternal & that = (const CRecordExternal &)baseThat;
  85. Cleanup();
  86. m_pSchema = that.m_pSchema;
  87. m_pubRecordFixedExternal = ( uint8 * )malloc( m_pSchema->CubRecordFixed() );
  88. Q_memcpy( m_pubRecordFixedExternal, that.PubRecordFixed(), m_pSchema->CubRecordFixed() );
  89. SetFlag( k_EAllocatedFixed, true );
  90. SetFlag( k_EAllocatedVarBlock, false );
  91. if ( VarFieldBlockInfo_t *pVarBlockInfo = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) )
  92. {
  93. if ( pVarBlockInfo->m_cubBlock )
  94. {
  95. void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock );
  96. Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock );
  97. pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock;
  98. SetFlag( k_EAllocatedVarBlock, true );
  99. }
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: Initialize to an empty record
  104. // Input: pSchema - Schema for the record this will hold
  105. //-----------------------------------------------------------------------------
  106. void CRecordExternal::Init( CSchema *pSchema )
  107. {
  108. Cleanup();
  109. m_pSchema = pSchema;
  110. m_pubRecordFixedExternal = ( uint8 * )malloc( m_pSchema->CubRecordFixed() );
  111. Q_memset( m_pubRecordFixedExternal, 0, m_pSchema->CubRecordFixed() );
  112. SetFlag( k_EAllocatedFixed, true );
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Purpose: Initialize pointing to a record expanded in memory
  116. // Input: pSchema - Schema for the record this will hold
  117. // pubRecord - Pointer to fixed record data
  118. // bTakeOwnership - Should we delete the record when destroyed
  119. // Output: Size of the record's data
  120. //-----------------------------------------------------------------------------
  121. int CRecordBase::InitFromBytes( uint8 *pubRecord )
  122. {
  123. Cleanup();
  124. Q_memcpy( PubRecordFixed(), pubRecord, GetPSchema()->CubRecordFixed() );
  125. int cubRead = GetPSchema()->CubRecordFixed();
  126. return cubRead;
  127. }
  128. int CRecordVar::InitFromBytes( uint8 *pubRecord )
  129. {
  130. Cleanup();
  131. Q_memcpy( PubRecordFixed(), pubRecord, GetPSchema()->CubRecordFixed() );
  132. int cubRead = GetPSchema()->CubRecordFixed();
  133. if ( VarFieldBlockInfo_t *pVarBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) )
  134. {
  135. if ( pVarBlockInfo->m_cubBlock )
  136. {
  137. void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock );
  138. Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock );
  139. pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock;
  140. SetFlag( k_EAllocatedVarBlock, true );
  141. cubRead += pVarBlockInfo->m_cubBlock;
  142. }
  143. }
  144. return cubRead;
  145. }
  146. int CRecordExternal::Init( CSchema *pSchema, uint8 *pubRecord, bool bTakeOwnership )
  147. {
  148. m_pSchema = pSchema;
  149. m_pubRecordFixedExternal = pubRecord;
  150. SetFlag( k_EAllocatedFixed, bTakeOwnership );
  151. SetFlag( k_EAllocatedVarBlock, bTakeOwnership );
  152. int cubRead = m_pSchema->CubRecordFixed() + CubRecordVarBlock();
  153. return cubRead;
  154. }
  155. CSchema *CRecordBase::GetPSchema()
  156. {
  157. return GetPSchemaImpl();
  158. }
  159. CSchema *CRecordBase::GetPSchemaImpl()
  160. {
  161. CSchema *pSchema = NULL;
  162. int i = GetITable();
  163. if ( i != -1 )
  164. pSchema = &GSchemaFull().GetSchema( i );
  165. return pSchema;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Purpose: Render a field to a buffer
  169. // Input: unColumn - field to render
  170. // cchBuffer - size of render buffer
  171. // pchBuffer - buffer to render into
  172. //-----------------------------------------------------------------------------
  173. void CRecordBase::RenderField( uint32 unColumn, int cchBuffer, char *pchBuffer ) const
  174. {
  175. Q_strncpy( pchBuffer, "", cchBuffer );
  176. uint8 *pubData;
  177. uint32 cubData;
  178. if ( !BGetField( unColumn, &pubData, &cubData ) )
  179. return;
  180. // Get the column info and figure out how to interpret the data
  181. ConvertFieldToText( GetPRecordInfo()->GetColumnInfo( unColumn ).GetType(), pubData, cubData, pchBuffer, cchBuffer, false );
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose: Reset to base state, freeing any memory we are responsible for
  185. //-----------------------------------------------------------------------------
  186. void CRecordBase::Cleanup()
  187. {
  188. }
  189. void CRecordVar::Cleanup()
  190. {
  191. // Must do this before freeing memory that encloses it
  192. // (eg releasing the net packet)
  193. if ( BFlagSet( k_EAllocatedVarBlock ) )
  194. {
  195. void *pvVarBlock = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock;
  196. free( pvVarBlock );
  197. m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock = NULL;
  198. SetFlag( k_EAllocatedVarBlock, false );
  199. }
  200. }
  201. void CRecordExternal::Cleanup()
  202. {
  203. // clean up the variable-length memory we might have allocated
  204. if ( BFlagSet( k_EAllocatedVarBlock ) )
  205. {
  206. void *pvVarBlock = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock;
  207. free( pvVarBlock );
  208. m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock = NULL;
  209. SetFlag( k_EAllocatedVarBlock, false );
  210. }
  211. // clean up the external memory we might have allocated
  212. if ( BFlagSet( k_EAllocatedFixed ) )
  213. free( m_pubRecordFixedExternal );
  214. SetFlag( k_EAllocatedFixed, false );
  215. m_pubRecordFixedExternal = NULL;
  216. // clean up the lowest layer, not calling CRecordVar
  217. CRecordBase::Cleanup();
  218. }
  219. //-----------------------------------------------------------------------------
  220. // Purpose: Deserializes a block of memory into this record
  221. // Input: pubData - Memory block to deserialize from
  222. //-----------------------------------------------------------------------------
  223. void CRecordExternal::DeSerialize( uint8 *pubData )
  224. {
  225. InitFromBytes( pubData );
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose: Calculates the size of this record when serialized
  229. // Output: Size of serialized message
  230. //-----------------------------------------------------------------------------
  231. uint32 CRecordBase::CubSerialized()
  232. {
  233. return CubRecordFixed() + CubRecordVarBlock();
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose: Get pointer to fixed part of record
  237. // Output: pubRecordFixed
  238. //-----------------------------------------------------------------------------
  239. uint8* CRecordBase::PubRecordFixed()
  240. {
  241. return ( uint8 * )( this + 1 );
  242. }
  243. uint8* CRecordExternal::PubRecordFixed()
  244. {
  245. Assert( m_pubRecordFixedExternal );
  246. return m_pubRecordFixedExternal;
  247. }
  248. uint8* CRecordVar::PubRecordFixed()
  249. {
  250. return ( uint8 * )( this + 1 );
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose: Get pointer to fixed part of record
  254. // Output: pubRecordFixed
  255. //-----------------------------------------------------------------------------
  256. const uint8* CRecordBase::PubRecordFixed() const
  257. {
  258. return const_cast<CRecordBase *>( this )->PubRecordFixed();
  259. }
  260. const uint8* CRecordVar::PubRecordFixed() const
  261. {
  262. return const_cast<CRecordVar *>( this )->PubRecordFixed();
  263. }
  264. const uint8* CRecordExternal::PubRecordFixed() const
  265. {
  266. return const_cast<CRecordExternal *>( this )->PubRecordFixed();
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Purpose: Get size of fixed part of record
  270. // Output: size in bytes of fixed part
  271. //-----------------------------------------------------------------------------
  272. uint32 CRecordBase::CubRecordFixed() const
  273. {
  274. return GetPSchema()->CubRecordFixed();
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Purpose: Get pointer to variable part of record
  278. // Output: Pointer to variable-length block -- may be NULL if this record
  279. // has no var-length fields or they are all empty
  280. //-----------------------------------------------------------------------------
  281. uint8* CRecordBase::PubRecordVarBlock()
  282. {
  283. VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() );
  284. if ( pVarFieldBlockInfo )
  285. {
  286. return pVarFieldBlockInfo->m_pubBlock;
  287. }
  288. else
  289. {
  290. return NULL;
  291. }
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Purpose: Get pointer to variable part of record
  295. // Output: Pointer to variable-length block -- may be NULL if this record
  296. // has no var-length fields or they are all empty
  297. //-----------------------------------------------------------------------------
  298. const uint8* CRecordBase::PubRecordVarBlock() const
  299. {
  300. return const_cast<CRecordBase *>( this )->PubRecordVarBlock();
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Get size of variable part of record
  304. // Output: Size in bytes of var-length block - may be zero if this record
  305. // has no var-length fields or they are all empty
  306. //-----------------------------------------------------------------------------
  307. uint32 CRecordBase::CubRecordVarBlock() const
  308. {
  309. VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() );
  310. if ( pVarFieldBlockInfo )
  311. {
  312. return pVarFieldBlockInfo->m_cubBlock;
  313. }
  314. else
  315. {
  316. return 0;
  317. }
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Purpose: Get size of variable part of record
  321. // Output: Size in bytes of var-length block - may be zero if this record
  322. // has no var-length fields or they are all empty
  323. //-----------------------------------------------------------------------------
  324. bool CRecordBase::BAssureRecordVarStorage( uint32 cVariableBytes )
  325. {
  326. // get the variable field block
  327. VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() );
  328. if ( pVarFieldBlockInfo )
  329. {
  330. // if we have it, see if it's got enough storage
  331. if ( pVarFieldBlockInfo->m_cubBlock >= cVariableBytes )
  332. {
  333. // already there
  334. return true;
  335. }
  336. // allocate it
  337. uint8* pubData = (uint8*) malloc( cVariableBytes );
  338. if ( pubData == NULL )
  339. return false;
  340. // do we have something right now?
  341. if ( pVarFieldBlockInfo->m_cubBlock != 0 )
  342. {
  343. // sure do. copy it over.
  344. Q_memcpy( pubData, pVarFieldBlockInfo->m_pubBlock, pVarFieldBlockInfo->m_cubBlock );
  345. // free what was there
  346. free( pVarFieldBlockInfo->m_pubBlock );
  347. }
  348. // hook up our buffer
  349. pVarFieldBlockInfo->m_cubBlockFree = cVariableBytes - pVarFieldBlockInfo->m_cubBlock;
  350. pVarFieldBlockInfo->m_cubBlock = cVariableBytes;
  351. pVarFieldBlockInfo->m_pubBlock = pubData;
  352. return true;
  353. }
  354. else
  355. {
  356. // we don't have one;
  357. // we've got no variable length fields, and so can't preallocate for them!
  358. return false;
  359. }
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Purpose: Initialize this whole record to random data
  363. // Input: unPrimaryIndex - Primary index to set
  364. //-----------------------------------------------------------------------------
  365. void CRecordExternal::InitRecordRandom( uint32 unPrimaryIndex )
  366. {
  367. bool bRealloced = false;
  368. GetPSchema()->InitRecordRandom( PubRecordFixed(), unPrimaryIndex, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) );
  369. if ( bRealloced )
  370. SetFlag( k_EAllocatedVarBlock, true );
  371. }
  372. //-----------------------------------------------------------------------------
  373. // Purpose: Set a field in this record to random bits
  374. // Input: iField - Field to set
  375. //-----------------------------------------------------------------------------
  376. void CRecordExternal::SetFieldRandom( int iField )
  377. {
  378. bool bRealloced = false;
  379. GetPSchema()->SetFieldRandom( PubRecordFixed(), iField, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) );
  380. if ( bRealloced )
  381. SetFlag( k_EAllocatedVarBlock, true );
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose: Get a field (var or fixed) from this record
  385. // Input: iField - Field to set
  386. // ppubData - Receives pointer to fields data
  387. // pcubField - Receives count of bytes of data (will count the null for strings)
  388. // Output: true if succeeds
  389. //-----------------------------------------------------------------------------
  390. bool CRecordBase::BGetField( int iField, uint8 **ppubData, uint32 *pcubField ) const
  391. {
  392. return GetPSchema()->BGetFieldData( PubRecordFixed(), iField, ppubData, pcubField );
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Purpose: Sets the data for a field, whether fixed or variable length
  396. // Input: iField - index of field to set
  397. // pubData - pointer to field data to copy from
  398. // cubData - size in bytes of that data
  399. // Output: true if successful
  400. //-----------------------------------------------------------------------------
  401. bool CRecordBase::BSetField( int iField, void *pvData, uint32 cubData )
  402. {
  403. bool bRealloced = false;
  404. bool bResult = BSetField( iField, pvData, cubData, &bRealloced );
  405. Assert( !bRealloced );
  406. return bResult;
  407. }
  408. bool CRecordBase::BSetField( int iField, void *pvData, uint32 cubData, bool *pbRealloced )
  409. {
  410. uint8 *pubData = reinterpret_cast<uint8 *>( pvData );
  411. if ( !GetPSchema()->BSetFieldData( PubRecordFixed(), iField, pubData, cubData, pbRealloced ) )
  412. return false;
  413. return true;
  414. }
  415. bool CRecordVar::BSetField( int iField, void *pvData, uint32 cubData )
  416. {
  417. bool bRealloced = false;
  418. bool bResult = CRecordBase::BSetField( iField, pvData, cubData, &bRealloced );
  419. if ( bRealloced )
  420. SetFlag( k_EAllocatedVarBlock, true );
  421. return bResult;
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Purpose: Erases a field, setting it to 0 length (if possible) and filling with nulls
  425. // Input: iField - index of field to wipe
  426. // NOTE: This relies on CSchema::BSetFieldData nulling out the rest of a field when it is set to 0 length!
  427. //-----------------------------------------------------------------------------
  428. void CRecordBase::WipeField( int iField )
  429. {
  430. bool bRealloced = false;
  431. // Empty Data
  432. uint32 un = 0;
  433. // Length should be 0, except for non-variable length strings where length should be 1 (for an empty string "")
  434. int cub = 0;
  435. Field_t &field = GetPSchema()->GetField( iField );
  436. Assert( !field.BIsVariableLength() );
  437. if ( field.BIsStringType() )
  438. cub = 1;
  439. GetPSchema()->BSetFieldData( PubRecordFixed(), iField, ( uint8 * ) &un, cub, &bRealloced );
  440. Assert( !bRealloced );
  441. }
  442. void CRecordVar::WipeField( int iField )
  443. {
  444. bool bRealloced = false;
  445. // Empty Data
  446. uint32 un = 0;
  447. // Length should be 0, except for non-variable length strings where length should be 1 (for an empty string "")
  448. int cub = 0;
  449. Field_t &field = GetPSchema()->GetField( iField );
  450. if ( field.BIsStringType() && !field.BIsVariableLength() )
  451. cub = 1;
  452. GetPSchema()->BSetFieldData( PubRecordFixed(), iField, ( uint8 * ) &un, cub, &bRealloced );
  453. if ( bRealloced )
  454. SetFlag( k_EAllocatedVarBlock, true );
  455. }
  456. //-----------------------------------------------------------------------------
  457. // Purpose: Get a string field - will return empty string instead of NULL if field has no datas
  458. // Input: iField - Field to get
  459. // pcubField - Receives count of bytes of data (will count the null for strings)
  460. // Output: const pointer to string data (to an empty string if no data)
  461. //-----------------------------------------------------------------------------
  462. const char * CRecordBase::GetStringField( int iField, uint32 *pcubField )
  463. {
  464. uint8 * pubData = NULL;
  465. *pcubField = 0;
  466. if ( BGetField( iField, &pubData, pcubField ) && *pcubField > 0 )
  467. return ( const char * ) pubData;
  468. else
  469. return "";
  470. }
  471. //-----------------------------------------------------------------------------
  472. // Purpose: Get an int field
  473. // Input: iField - Field to get
  474. // Output: Int (0 if no data)
  475. //-----------------------------------------------------------------------------
  476. int CRecordBase::GetInt( int iField )
  477. {
  478. return ( int ) GetUint32( iField );
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: Get a uint16 field
  482. // Input: iField - Field to get
  483. // Output: uint16 (0 if no data)
  484. //-----------------------------------------------------------------------------
  485. uint16 CRecordBase::GetUint16( int iField )
  486. {
  487. uint8 * pubData = NULL;
  488. uint32 cubField = 0;
  489. DbgVerify( BGetField( iField, &pubData, &cubField ) );
  490. Assert( 0 < cubField );
  491. if ( NULL != pubData )
  492. return *( uint16 * ) pubData;
  493. else
  494. return 0;
  495. }
  496. //-----------------------------------------------------------------------------
  497. // Purpose: Get a uint32 field
  498. // Input: iField - Field to get
  499. // Output: uint32 (0 if no data)
  500. //-----------------------------------------------------------------------------
  501. uint32 CRecordBase::GetUint32( int iField )
  502. {
  503. uint8 * pubData = NULL;
  504. uint32 cubField = 0;
  505. DbgVerify( BGetField( iField, &pubData, &cubField ) );
  506. Assert( 0 < cubField );
  507. if ( NULL != pubData )
  508. return *( uint32 * ) pubData;
  509. else
  510. return 0;
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose: Get a uint64 field
  514. // Input: iField - Field to get
  515. // Output: uint64 (0 if no data)
  516. //-----------------------------------------------------------------------------
  517. uint64 CRecordBase::GetUint64( int iField )
  518. {
  519. uint8 * pubData = NULL;
  520. uint32 cubField = 0;
  521. DbgVerify( BGetField( iField, &pubData, &cubField ) );
  522. Assert( 0 < cubField );
  523. if ( NULL != pubData )
  524. return *( uint64 * ) pubData;
  525. else
  526. return 0;
  527. }
  528. const char * CRecordBase::ReadVarCharField( const CVarCharField &field ) const
  529. {
  530. Assert( false );
  531. return NULL;
  532. }
  533. const uint8 * CRecordBase::ReadVarDataField( const CVarField &field, uint32 *pcubField ) const
  534. {
  535. Assert( false );
  536. return NULL;
  537. }
  538. // These may cause a realloc
  539. bool CRecordBase::SetVarCharField( CVarCharField &field, const char *pchString, bool bTruncate, int32 iField )
  540. {
  541. Assert( false );
  542. return false ;
  543. }
  544. void CRecordBase::SetVarDataField( CVarField &field, const void *pvData, uint32 cubData )
  545. {
  546. Assert( false );
  547. }
  548. //-----------------------------------------------------------------------------
  549. // Purpose: Read data from a varchar field
  550. // Input: field - opaque field object to read from
  551. // Output: pointer to data - may be NULL if that field is empty.
  552. //-----------------------------------------------------------------------------
  553. const char * CRecordVar::ReadVarCharField( const CVarCharField &field ) const
  554. {
  555. Assert ( GetPSchema()->BHasVariableFields() );
  556. uint8 *pubData;
  557. uint32 cubData;
  558. if ( GetPSchema()->BGetVarField( PubRecordFixed(), &field, &pubData, &cubData ) )
  559. return (const char *)pubData;
  560. else
  561. return "";
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Purpose: Read data from a vardata field
  565. // Input: field - opaque field object to read from
  566. // Output: pointer to data - may be NULL if that field is empty.
  567. //-----------------------------------------------------------------------------
  568. const uint8 *CRecordVar::ReadVarDataField( const CVarField &field, uint32 *pcubField ) const
  569. {
  570. Assert ( GetPSchema()->BHasVariableFields() );
  571. uint8 *pubData;
  572. *pcubField = 0;
  573. if ( GetPSchema()->BGetVarField( PubRecordFixed(), &field, &pubData, pcubField ) )
  574. return pubData;
  575. else
  576. return NULL;
  577. }
  578. //-----------------------------------------------------------------------------
  579. // Purpose: Update (in memory) a varchar field
  580. // Input: field - opaque field object to update
  581. // pchString - string data to set
  582. //-----------------------------------------------------------------------------
  583. bool CRecordVar::SetVarCharField( CVarCharField &field, const char *pchString, bool bTruncate, int32 iField )
  584. {
  585. Assert ( GetPSchema()->BHasVariableFields() );
  586. if( iField < 0 )
  587. {
  588. AssertMsg1( false, "Encountered a bad call to SetVarCharField with an invalid field specified: %d", iField );
  589. return false;
  590. }
  591. bool bTruncated = false;
  592. int cchLen = Q_strlen( pchString ) + 1;
  593. // since we're a VARCHAR field, cbMaxLength is the length in characters
  594. const int cchMaxLength = m_pSchema->GetField( iField ).m_cchMaxLength;
  595. if ( ( cchMaxLength > 0 ) && ( cchLen > cchMaxLength ) )
  596. {
  597. if( bTruncate )
  598. {
  599. bTruncated = true;
  600. cchLen = cchMaxLength;
  601. }
  602. else
  603. {
  604. // caller should check his data and not pass stuff that wont fit
  605. AssertMsg4( false, "Overflow in SetVarCharField (%u > %u) for column %s in table %s", cchLen, cchMaxLength, m_pSchema->GetField( iField ).m_rgchName, m_pSchema->GetPchName() );
  606. return false;
  607. }
  608. }
  609. bool bRealloced = false;
  610. bool fSuccess = GetPSchema()->BSetVarField( PubRecordFixed(), &field, pchString, cchLen, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) );
  611. if( fSuccess && bTruncated )
  612. {
  613. //make sure the last character is NULL if we truncated
  614. VarFieldBlockInfo_t *pBlock = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() );
  615. uint8 *pubVarBlock = pBlock->m_pubBlock;
  616. char* pField = ( char* )( pubVarBlock + field.m_dubOffset );
  617. pField[ cchLen - 1 ] = '\0';
  618. }
  619. if ( bRealloced )
  620. SetFlag( k_EAllocatedVarBlock, true );
  621. return fSuccess;
  622. }
  623. //-----------------------------------------------------------------------------
  624. // Purpose: Update (in memory) a vardata field
  625. // Input: field - opaque field object to update
  626. // pvData - pointer to data to put there
  627. // cubData - size in bytes of the data
  628. //-----------------------------------------------------------------------------
  629. void CRecordVar::SetVarDataField( CVarField &field, const void *pvData, uint32 cubData )
  630. {
  631. Assert ( GetPSchema()->BHasVariableFields() );
  632. bool bRealloced = false;
  633. GetPSchema()->BSetVarField( PubRecordFixed(), &field, pvData, cubData, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) );
  634. if ( bRealloced )
  635. SetFlag( k_EAllocatedVarBlock, true );
  636. }
  637. //-----------------------------------------------------------------------------
  638. // Purpose: Set or clear the specified flag in m_nFlags
  639. // Input: eFlag - flag (single bit) to change
  640. // bSet - Set it, else clear it
  641. //-----------------------------------------------------------------------------
  642. void CRecordVar::SetFlag( int eFlag, bool bSet )
  643. {
  644. if ( bSet )
  645. m_nFlags |= eFlag;
  646. else
  647. m_nFlags &= ~eFlag;
  648. }
  649. //-----------------------------------------------------------------------------
  650. // Purpose: Get the state of the specified flag
  651. // Input: eFlag - flag (single bit) to check
  652. //-----------------------------------------------------------------------------
  653. bool CRecordVar::BFlagSet( int eFlag ) const
  654. {
  655. return 0 != ( m_nFlags & eFlag );
  656. }
  657. #ifdef DBGFLAG_VALIDATE
  658. //-----------------------------------------------------------------------------
  659. // Purpose: Run a global validation pass on all of our data structures and memory
  660. // allocations.
  661. // Input: validator - Our global validator object
  662. // pchName - Our name (typically a member var in our container)
  663. //-----------------------------------------------------------------------------
  664. void CRecordBase::Validate( CValidator &validator, const char *pchName )
  665. {
  666. VALIDATE_SCOPE();
  667. }
  668. void CRecordVar::Validate( CValidator &validator, const char *pchName )
  669. {
  670. VALIDATE_SCOPE();
  671. if ( BFlagSet( k_EAllocatedVarBlock ) )
  672. {
  673. validator.ClaimMemory( GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock );
  674. }
  675. }
  676. void CRecordExternal::Validate( CValidator &validator, const char *pchName )
  677. {
  678. if ( BFlagSet( k_EAllocatedFixed ) )
  679. {
  680. validator.ClaimMemory( m_pubRecordFixedExternal );
  681. }
  682. CRecordBase::Validate( validator, pchName );
  683. }
  684. void CRecordBase::ValidateStatics( CValidator &validator, const char *pchName )
  685. {
  686. VALIDATE_SCOPE_STATIC( "CRecordBase class statics" );
  687. }
  688. #endif // DBGFLAG_VALIDATE
  689. //-----------------------------------------------------------------------------
  690. // Purpose: Return the schema for this record type
  691. //-----------------------------------------------------------------------------
  692. CSchema *CRecordType::GetSchema() const
  693. {
  694. return &GSchemaFull().GetSchema( GetITable() );
  695. }
  696. //-----------------------------------------------------------------------------
  697. // Purpose: Return the CRecordInfo for this record type
  698. //-----------------------------------------------------------------------------
  699. CRecordInfo *CRecordType::GetRecordInfo() const
  700. {
  701. return GetSchema()->GetRecordInfo();
  702. }
  703. } // namespace GCSDK