diff options
Diffstat (limited to 'gcsdk/sqlaccess/record.cpp')
| -rw-r--r-- | gcsdk/sqlaccess/record.cpp | 856 |
1 files changed, 856 insertions, 0 deletions
diff --git a/gcsdk/sqlaccess/record.cpp b/gcsdk/sqlaccess/record.cpp new file mode 100644 index 0000000..6812b50 --- /dev/null +++ b/gcsdk/sqlaccess/record.cpp @@ -0,0 +1,856 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "stdafx.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +namespace GCSDK +{ + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CRecordBase::~CRecordBase() +{ + Cleanup(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Copy constructor +// Input: that - CRecord to copy from +//----------------------------------------------------------------------------- +CRecordBase::CRecordBase( const CRecordBase &that ) +{ + *this = that; +} + + +//----------------------------------------------------------------------------- +// Purpose: Assignment operator - COPIES the record data +// Input: that - CRecord to copy from +//----------------------------------------------------------------------------- +CRecordBase& CRecordBase::operator = ( const CRecordBase & that ) +{ + Assert( GetITable() == that.GetITable() ); + + // COPY that record + Copy( that ); + + return *this; +} + + +//----------------------------------------------------------------------------- +// Purpose: Copies the data in the record. This is overridden by CRecordVar and +// CRecordExternal +// Input: that - CRecord to copy from +//----------------------------------------------------------------------------- +void CRecordBase::Copy( const CRecordBase & that ) +{ + Cleanup(); + Q_memcpy( PubRecordFixed(), that.PubRecordFixed(), GetPSchema()->CubRecordFixed() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Return the record info for this record's schema +//----------------------------------------------------------------------------- +const CRecordInfo *CRecordBase::GetPRecordInfo() const +{ + return GetPSchema()->GetRecordInfo(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Copies the data in the var record. +// Input: that - CRecord to copy from +//----------------------------------------------------------------------------- +void CRecordVar::Copy( const CRecordBase & baseThat ) +{ + const CRecordVar & that = (const CRecordVar &)baseThat; + + // COPY that record + Cleanup(); + m_pSchema = that.m_pSchema; + Q_memcpy( PubRecordFixed(), that.PubRecordFixed(), GetPSchema()->CubRecordFixed() ); + + SetFlag( k_EAllocatedVarBlock, false ); + if ( VarFieldBlockInfo_t *pVarBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) ) + { + if ( pVarBlockInfo->m_cubBlock ) + { + void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock ); + Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock ); + pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock; + SetFlag( k_EAllocatedVarBlock, true ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Copies the data in the var record. +// Input: that - CRecord to copy from +//----------------------------------------------------------------------------- +void CRecordExternal::Copy( const CRecordBase & baseThat ) +{ + const CRecordExternal & that = (const CRecordExternal &)baseThat; + + Cleanup(); + m_pSchema = that.m_pSchema; + + m_pubRecordFixedExternal = ( uint8 * )malloc( m_pSchema->CubRecordFixed() ); + Q_memcpy( m_pubRecordFixedExternal, that.PubRecordFixed(), m_pSchema->CubRecordFixed() ); + SetFlag( k_EAllocatedFixed, true ); + + SetFlag( k_EAllocatedVarBlock, false ); + if ( VarFieldBlockInfo_t *pVarBlockInfo = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) ) + { + if ( pVarBlockInfo->m_cubBlock ) + { + void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock ); + Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock ); + pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock; + SetFlag( k_EAllocatedVarBlock, true ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Initialize to an empty record +// Input: pSchema - Schema for the record this will hold +//----------------------------------------------------------------------------- +void CRecordExternal::Init( CSchema *pSchema ) +{ + Cleanup(); + m_pSchema = pSchema; + m_pubRecordFixedExternal = ( uint8 * )malloc( m_pSchema->CubRecordFixed() ); + Q_memset( m_pubRecordFixedExternal, 0, m_pSchema->CubRecordFixed() ); + SetFlag( k_EAllocatedFixed, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Initialize pointing to a record expanded in memory +// Input: pSchema - Schema for the record this will hold +// pubRecord - Pointer to fixed record data +// bTakeOwnership - Should we delete the record when destroyed +// Output: Size of the record's data +//----------------------------------------------------------------------------- +int CRecordBase::InitFromBytes( uint8 *pubRecord ) +{ + Cleanup(); + + Q_memcpy( PubRecordFixed(), pubRecord, GetPSchema()->CubRecordFixed() ); + int cubRead = GetPSchema()->CubRecordFixed(); + return cubRead; +} + +int CRecordVar::InitFromBytes( uint8 *pubRecord ) +{ + Cleanup(); + + Q_memcpy( PubRecordFixed(), pubRecord, GetPSchema()->CubRecordFixed() ); + int cubRead = GetPSchema()->CubRecordFixed(); + if ( VarFieldBlockInfo_t *pVarBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ) ) + { + if ( pVarBlockInfo->m_cubBlock ) + { + void *pvNewBlock = malloc( pVarBlockInfo->m_cubBlock ); + Q_memcpy( pvNewBlock, pVarBlockInfo->m_pubBlock, pVarBlockInfo->m_cubBlock ); + pVarBlockInfo->m_pubBlock = ( uint8 * )pvNewBlock; + SetFlag( k_EAllocatedVarBlock, true ); + cubRead += pVarBlockInfo->m_cubBlock; + } + } + + return cubRead; +} + + +int CRecordExternal::Init( CSchema *pSchema, uint8 *pubRecord, bool bTakeOwnership ) +{ + m_pSchema = pSchema; + m_pubRecordFixedExternal = pubRecord; + SetFlag( k_EAllocatedFixed, bTakeOwnership ); + SetFlag( k_EAllocatedVarBlock, bTakeOwnership ); + int cubRead = m_pSchema->CubRecordFixed() + CubRecordVarBlock(); + + return cubRead; +} + +CSchema *CRecordBase::GetPSchema() +{ + return GetPSchemaImpl(); +} + +CSchema *CRecordBase::GetPSchemaImpl() +{ + CSchema *pSchema = NULL; + int i = GetITable(); + if ( i != -1 ) + pSchema = &GSchemaFull().GetSchema( i ); + return pSchema; +} + +//----------------------------------------------------------------------------- +// Purpose: Render a field to a buffer +// Input: unColumn - field to render +// cchBuffer - size of render buffer +// pchBuffer - buffer to render into +//----------------------------------------------------------------------------- +void CRecordBase::RenderField( uint32 unColumn, int cchBuffer, char *pchBuffer ) const +{ + Q_strncpy( pchBuffer, "", cchBuffer ); + + uint8 *pubData; + uint32 cubData; + if ( !BGetField( unColumn, &pubData, &cubData ) ) + return; + + // Get the column info and figure out how to interpret the data + ConvertFieldToText( GetPRecordInfo()->GetColumnInfo( unColumn ).GetType(), pubData, cubData, pchBuffer, cchBuffer, false ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Reset to base state, freeing any memory we are responsible for +//----------------------------------------------------------------------------- +void CRecordBase::Cleanup() +{ +} + +void CRecordVar::Cleanup() +{ + // Must do this before freeing memory that encloses it + // (eg releasing the net packet) + if ( BFlagSet( k_EAllocatedVarBlock ) ) + { + void *pvVarBlock = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock; + free( pvVarBlock ); + m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock = NULL; + SetFlag( k_EAllocatedVarBlock, false ); + } +} + +void CRecordExternal::Cleanup() +{ + // clean up the variable-length memory we might have allocated + if ( BFlagSet( k_EAllocatedVarBlock ) ) + { + void *pvVarBlock = m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock; + free( pvVarBlock ); + m_pSchema->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock = NULL; + SetFlag( k_EAllocatedVarBlock, false ); + } + + // clean up the external memory we might have allocated + if ( BFlagSet( k_EAllocatedFixed ) ) + free( m_pubRecordFixedExternal ); + SetFlag( k_EAllocatedFixed, false ); + m_pubRecordFixedExternal = NULL; + + // clean up the lowest layer, not calling CRecordVar + CRecordBase::Cleanup(); +} + +//----------------------------------------------------------------------------- +// Purpose: Deserializes a block of memory into this record +// Input: pubData - Memory block to deserialize from +//----------------------------------------------------------------------------- +void CRecordExternal::DeSerialize( uint8 *pubData ) +{ + InitFromBytes( pubData ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Calculates the size of this record when serialized +// Output: Size of serialized message +//----------------------------------------------------------------------------- +uint32 CRecordBase::CubSerialized() +{ + return CubRecordFixed() + CubRecordVarBlock(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get pointer to fixed part of record +// Output: pubRecordFixed +//----------------------------------------------------------------------------- +uint8* CRecordBase::PubRecordFixed() +{ + return ( uint8 * )( this + 1 ); +} + +uint8* CRecordExternal::PubRecordFixed() +{ + Assert( m_pubRecordFixedExternal ); + return m_pubRecordFixedExternal; +} + +uint8* CRecordVar::PubRecordFixed() +{ + return ( uint8 * )( this + 1 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get pointer to fixed part of record +// Output: pubRecordFixed +//----------------------------------------------------------------------------- +const uint8* CRecordBase::PubRecordFixed() const +{ + return const_cast<CRecordBase *>( this )->PubRecordFixed(); +} + +const uint8* CRecordVar::PubRecordFixed() const +{ + return const_cast<CRecordVar *>( this )->PubRecordFixed(); +} + +const uint8* CRecordExternal::PubRecordFixed() const +{ + return const_cast<CRecordExternal *>( this )->PubRecordFixed(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get size of fixed part of record +// Output: size in bytes of fixed part +//----------------------------------------------------------------------------- +uint32 CRecordBase::CubRecordFixed() const +{ + return GetPSchema()->CubRecordFixed(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get pointer to variable part of record +// Output: Pointer to variable-length block -- may be NULL if this record +// has no var-length fields or they are all empty +//----------------------------------------------------------------------------- +uint8* CRecordBase::PubRecordVarBlock() +{ + VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ); + if ( pVarFieldBlockInfo ) + { + return pVarFieldBlockInfo->m_pubBlock; + } + else + { + return NULL; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Get pointer to variable part of record +// Output: Pointer to variable-length block -- may be NULL if this record +// has no var-length fields or they are all empty +//----------------------------------------------------------------------------- +const uint8* CRecordBase::PubRecordVarBlock() const +{ + return const_cast<CRecordBase *>( this )->PubRecordVarBlock(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get size of variable part of record +// Output: Size in bytes of var-length block - may be zero if this record +// has no var-length fields or they are all empty +//----------------------------------------------------------------------------- +uint32 CRecordBase::CubRecordVarBlock() const +{ + VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ); + if ( pVarFieldBlockInfo ) + { + return pVarFieldBlockInfo->m_cubBlock; + } + else + { + return 0; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Get size of variable part of record +// Output: Size in bytes of var-length block - may be zero if this record +// has no var-length fields or they are all empty +//----------------------------------------------------------------------------- +bool CRecordBase::BAssureRecordVarStorage( uint32 cVariableBytes ) +{ + // get the variable field block + VarFieldBlockInfo_t *pVarFieldBlockInfo = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ); + if ( pVarFieldBlockInfo ) + { + // if we have it, see if it's got enough storage + if ( pVarFieldBlockInfo->m_cubBlock >= cVariableBytes ) + { + // already there + return true; + } + + // allocate it + uint8* pubData = (uint8*) malloc( cVariableBytes ); + if ( pubData == NULL ) + return false; + + // do we have something right now? + if ( pVarFieldBlockInfo->m_cubBlock != 0 ) + { + // sure do. copy it over. + Q_memcpy( pubData, pVarFieldBlockInfo->m_pubBlock, pVarFieldBlockInfo->m_cubBlock ); + + // free what was there + free( pVarFieldBlockInfo->m_pubBlock ); + } + + // hook up our buffer + pVarFieldBlockInfo->m_cubBlockFree = cVariableBytes - pVarFieldBlockInfo->m_cubBlock; + pVarFieldBlockInfo->m_cubBlock = cVariableBytes; + pVarFieldBlockInfo->m_pubBlock = pubData; + + return true; + } + else + { + // we don't have one; + // we've got no variable length fields, and so can't preallocate for them! + return false; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize this whole record to random data +// Input: unPrimaryIndex - Primary index to set +//----------------------------------------------------------------------------- +void CRecordExternal::InitRecordRandom( uint32 unPrimaryIndex ) +{ + bool bRealloced = false; + GetPSchema()->InitRecordRandom( PubRecordFixed(), unPrimaryIndex, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) ); + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Set a field in this record to random bits +// Input: iField - Field to set +//----------------------------------------------------------------------------- +void CRecordExternal::SetFieldRandom( int iField ) +{ + bool bRealloced = false; + GetPSchema()->SetFieldRandom( PubRecordFixed(), iField, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) ); + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get a field (var or fixed) from this record +// Input: iField - Field to set +// ppubData - Receives pointer to fields data +// pcubField - Receives count of bytes of data (will count the null for strings) +// Output: true if succeeds +//----------------------------------------------------------------------------- +bool CRecordBase::BGetField( int iField, uint8 **ppubData, uint32 *pcubField ) const +{ + return GetPSchema()->BGetFieldData( PubRecordFixed(), iField, ppubData, pcubField ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the data for a field, whether fixed or variable length +// Input: iField - index of field to set +// pubData - pointer to field data to copy from +// cubData - size in bytes of that data +// Output: true if successful +//----------------------------------------------------------------------------- +bool CRecordBase::BSetField( int iField, void *pvData, uint32 cubData ) +{ + bool bRealloced = false; + bool bResult = BSetField( iField, pvData, cubData, &bRealloced ); + Assert( !bRealloced ); + + return bResult; +} + +bool CRecordBase::BSetField( int iField, void *pvData, uint32 cubData, bool *pbRealloced ) +{ + uint8 *pubData = reinterpret_cast<uint8 *>( pvData ); + + if ( !GetPSchema()->BSetFieldData( PubRecordFixed(), iField, pubData, cubData, pbRealloced ) ) + return false; + + return true; +} + +bool CRecordVar::BSetField( int iField, void *pvData, uint32 cubData ) +{ + bool bRealloced = false; + bool bResult = CRecordBase::BSetField( iField, pvData, cubData, &bRealloced ); + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); + return bResult; +} + + +//----------------------------------------------------------------------------- +// Purpose: Erases a field, setting it to 0 length (if possible) and filling with nulls +// Input: iField - index of field to wipe +// NOTE: This relies on CSchema::BSetFieldData nulling out the rest of a field when it is set to 0 length! +//----------------------------------------------------------------------------- +void CRecordBase::WipeField( int iField ) +{ + bool bRealloced = false; + + // Empty Data + uint32 un = 0; + + // Length should be 0, except for non-variable length strings where length should be 1 (for an empty string "") + int cub = 0; + Field_t &field = GetPSchema()->GetField( iField ); + Assert( !field.BIsVariableLength() ); + if ( field.BIsStringType() ) + cub = 1; + + GetPSchema()->BSetFieldData( PubRecordFixed(), iField, ( uint8 * ) &un, cub, &bRealloced ); + + Assert( !bRealloced ); +} + +void CRecordVar::WipeField( int iField ) +{ + bool bRealloced = false; + + // Empty Data + uint32 un = 0; + + // Length should be 0, except for non-variable length strings where length should be 1 (for an empty string "") + int cub = 0; + Field_t &field = GetPSchema()->GetField( iField ); + if ( field.BIsStringType() && !field.BIsVariableLength() ) + cub = 1; + + GetPSchema()->BSetFieldData( PubRecordFixed(), iField, ( uint8 * ) &un, cub, &bRealloced ); + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get a string field - will return empty string instead of NULL if field has no datas +// Input: iField - Field to get +// pcubField - Receives count of bytes of data (will count the null for strings) +// Output: const pointer to string data (to an empty string if no data) +//----------------------------------------------------------------------------- +const char * CRecordBase::GetStringField( int iField, uint32 *pcubField ) +{ + uint8 * pubData = NULL; + *pcubField = 0; + + if ( BGetField( iField, &pubData, pcubField ) && *pcubField > 0 ) + return ( const char * ) pubData; + else + return ""; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get an int field +// Input: iField - Field to get +// Output: Int (0 if no data) +//----------------------------------------------------------------------------- +int CRecordBase::GetInt( int iField ) +{ + return ( int ) GetUint32( iField ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get a uint16 field +// Input: iField - Field to get +// Output: uint16 (0 if no data) +//----------------------------------------------------------------------------- +uint16 CRecordBase::GetUint16( int iField ) +{ + uint8 * pubData = NULL; + uint32 cubField = 0; + + DbgVerify( BGetField( iField, &pubData, &cubField ) ); + Assert( 0 < cubField ); + + if ( NULL != pubData ) + return *( uint16 * ) pubData; + else + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get a uint32 field +// Input: iField - Field to get +// Output: uint32 (0 if no data) +//----------------------------------------------------------------------------- +uint32 CRecordBase::GetUint32( int iField ) +{ + uint8 * pubData = NULL; + uint32 cubField = 0; + + DbgVerify( BGetField( iField, &pubData, &cubField ) ); + Assert( 0 < cubField ); + + if ( NULL != pubData ) + return *( uint32 * ) pubData; + else + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get a uint64 field +// Input: iField - Field to get +// Output: uint64 (0 if no data) +//----------------------------------------------------------------------------- +uint64 CRecordBase::GetUint64( int iField ) +{ + uint8 * pubData = NULL; + uint32 cubField = 0; + + DbgVerify( BGetField( iField, &pubData, &cubField ) ); + Assert( 0 < cubField ); + + if ( NULL != pubData ) + return *( uint64 * ) pubData; + else + return 0; +} + + + +const char * CRecordBase::ReadVarCharField( const CVarCharField &field ) const +{ + Assert( false ); + return NULL; +} + +const uint8 * CRecordBase::ReadVarDataField( const CVarField &field, uint32 *pcubField ) const +{ + Assert( false ); + return NULL; +} + +// These may cause a realloc +bool CRecordBase::SetVarCharField( CVarCharField &field, const char *pchString, bool bTruncate, int32 iField ) +{ + Assert( false ); + return false ; +} + +void CRecordBase::SetVarDataField( CVarField &field, const void *pvData, uint32 cubData ) +{ + Assert( false ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Read data from a varchar field +// Input: field - opaque field object to read from +// Output: pointer to data - may be NULL if that field is empty. +//----------------------------------------------------------------------------- +const char * CRecordVar::ReadVarCharField( const CVarCharField &field ) const +{ + Assert ( GetPSchema()->BHasVariableFields() ); + + uint8 *pubData; + uint32 cubData; + if ( GetPSchema()->BGetVarField( PubRecordFixed(), &field, &pubData, &cubData ) ) + return (const char *)pubData; + else + return ""; +} + + +//----------------------------------------------------------------------------- +// Purpose: Read data from a vardata field +// Input: field - opaque field object to read from +// Output: pointer to data - may be NULL if that field is empty. +//----------------------------------------------------------------------------- +const uint8 *CRecordVar::ReadVarDataField( const CVarField &field, uint32 *pcubField ) const +{ + Assert ( GetPSchema()->BHasVariableFields() ); + + uint8 *pubData; + *pcubField = 0; + if ( GetPSchema()->BGetVarField( PubRecordFixed(), &field, &pubData, pcubField ) ) + return pubData; + else + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Update (in memory) a varchar field +// Input: field - opaque field object to update +// pchString - string data to set +//----------------------------------------------------------------------------- +bool CRecordVar::SetVarCharField( CVarCharField &field, const char *pchString, bool bTruncate, int32 iField ) +{ + Assert ( GetPSchema()->BHasVariableFields() ); + if( iField < 0 ) + { + AssertMsg1( false, "Encountered a bad call to SetVarCharField with an invalid field specified: %d", iField ); + return false; + } + + bool bTruncated = false; + int cchLen = Q_strlen( pchString ) + 1; + + // since we're a VARCHAR field, cbMaxLength is the length in characters + const int cchMaxLength = m_pSchema->GetField( iField ).m_cchMaxLength; + if ( ( cchMaxLength > 0 ) && ( cchLen > cchMaxLength ) ) + { + if( bTruncate ) + { + bTruncated = true; + cchLen = cchMaxLength; + } + else + { + // caller should check his data and not pass stuff that wont fit + AssertMsg4( false, "Overflow in SetVarCharField (%u > %u) for column %s in table %s", cchLen, cchMaxLength, m_pSchema->GetField( iField ).m_rgchName, m_pSchema->GetPchName() ); + return false; + } + } + + bool bRealloced = false; + bool fSuccess = GetPSchema()->BSetVarField( PubRecordFixed(), &field, pchString, cchLen, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) ); + if( fSuccess && bTruncated ) + { + //make sure the last character is NULL if we truncated + VarFieldBlockInfo_t *pBlock = GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() ); + uint8 *pubVarBlock = pBlock->m_pubBlock; + char* pField = ( char* )( pubVarBlock + field.m_dubOffset ); + pField[ cchLen - 1 ] = '\0'; + } + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); + return fSuccess; +} + + +//----------------------------------------------------------------------------- +// Purpose: Update (in memory) a vardata field +// Input: field - opaque field object to update +// pvData - pointer to data to put there +// cubData - size in bytes of the data +//----------------------------------------------------------------------------- +void CRecordVar::SetVarDataField( CVarField &field, const void *pvData, uint32 cubData ) +{ + Assert ( GetPSchema()->BHasVariableFields() ); + + bool bRealloced = false; + GetPSchema()->BSetVarField( PubRecordFixed(), &field, pvData, cubData, &bRealloced, BFlagSet( k_EAllocatedVarBlock ) ); + + if ( bRealloced ) + SetFlag( k_EAllocatedVarBlock, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Set or clear the specified flag in m_nFlags +// Input: eFlag - flag (single bit) to change +// bSet - Set it, else clear it +//----------------------------------------------------------------------------- +void CRecordVar::SetFlag( int eFlag, bool bSet ) +{ + if ( bSet ) + m_nFlags |= eFlag; + else + m_nFlags &= ~eFlag; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the state of the specified flag +// Input: eFlag - flag (single bit) to check +//----------------------------------------------------------------------------- +bool CRecordVar::BFlagSet( int eFlag ) const +{ + return 0 != ( m_nFlags & eFlag ); +} + + +#ifdef DBGFLAG_VALIDATE +//----------------------------------------------------------------------------- +// Purpose: Run a global validation pass on all of our data structures and memory +// allocations. +// Input: validator - Our global validator object +// pchName - Our name (typically a member var in our container) +//----------------------------------------------------------------------------- +void CRecordBase::Validate( CValidator &validator, const char *pchName ) +{ + VALIDATE_SCOPE(); +} + +void CRecordVar::Validate( CValidator &validator, const char *pchName ) +{ + VALIDATE_SCOPE(); + + if ( BFlagSet( k_EAllocatedVarBlock ) ) + { + validator.ClaimMemory( GetPSchema()->PVarFieldBlockInfoFromRecord( PubRecordFixed() )->m_pubBlock ); + } + +} + +void CRecordExternal::Validate( CValidator &validator, const char *pchName ) +{ + if ( BFlagSet( k_EAllocatedFixed ) ) + { + validator.ClaimMemory( m_pubRecordFixedExternal ); + } + + CRecordBase::Validate( validator, pchName ); +} + +void CRecordBase::ValidateStatics( CValidator &validator, const char *pchName ) +{ + VALIDATE_SCOPE_STATIC( "CRecordBase class statics" ); +} + +#endif // DBGFLAG_VALIDATE + + +//----------------------------------------------------------------------------- +// Purpose: Return the schema for this record type +//----------------------------------------------------------------------------- +CSchema *CRecordType::GetSchema() const +{ + return &GSchemaFull().GetSchema( GetITable() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Return the CRecordInfo for this record type +//----------------------------------------------------------------------------- +CRecordInfo *CRecordType::GetRecordInfo() const +{ + return GetSchema()->GetRecordInfo(); +} + +} // namespace GCSDK |