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
856 lines
27 KiB
//========= 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
|
|
|