This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

643
dmxloader/dmxattribute.cpp Normal file
View File

@ -0,0 +1,643 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "dmxloader/dmxattribute.h"
#include "tier1/utlbufferutil.h"
#include "tier1/uniqueid.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// globals
//-----------------------------------------------------------------------------
CUtlSymbolTableMT CDmxAttribute::s_AttributeNameSymbols;
//-----------------------------------------------------------------------------
// Attribute size
//-----------------------------------------------------------------------------
static size_t s_pAttributeSize[AT_TYPE_COUNT] =
{
0, // AT_UNKNOWN,
sizeof(CDmxElement*), // AT_ELEMENT,
sizeof(int), // AT_INT,
sizeof(float), // AT_FLOAT,
sizeof(bool), // AT_BOOL,
sizeof(CUtlString), // AT_STRING,
sizeof(CUtlBinaryBlock), // AT_VOID,
sizeof(DmObjectId_t), // AT_OBJECTID,
sizeof(Color), // AT_COLOR,
sizeof(Vector2D), // AT_VECTOR2,
sizeof(Vector), // AT_VECTOR3,
sizeof(Vector4D), // AT_VECTOR4,
sizeof(QAngle), // AT_QANGLE,
sizeof(Quaternion), // AT_QUATERNION,
sizeof(VMatrix), // AT_VMATRIX,
sizeof(CUtlVector<CDmxElement*>), // AT_ELEMENT_ARRAY,
sizeof(CUtlVector<int>), // AT_INT_ARRAY,
sizeof(CUtlVector<float>), // AT_FLOAT_ARRAY,
sizeof(CUtlVector<bool>), // AT_BOOL_ARRAY,
sizeof(CUtlVector<CUtlString>), // AT_STRING_ARRAY,
sizeof(CUtlVector<CUtlBinaryBlock>), // AT_VOID_ARRAY,
sizeof(CUtlVector<DmObjectId_t>), // AT_OBJECTID_ARRAY,
sizeof(CUtlVector<Color>), // AT_COLOR_ARRAY,
sizeof(CUtlVector<Vector2D>), // AT_VECTOR2_ARRAY,
sizeof(CUtlVector<Vector>), // AT_VECTOR3_ARRAY,
sizeof(CUtlVector<Vector4D>), // AT_VECTOR4_ARRAY,
sizeof(CUtlVector<QAngle>), // AT_QANGLE_ARRAY,
sizeof(CUtlVector<Quaternion>), // AT_QUATERNION_ARRAY,
sizeof(CUtlVector<VMatrix>), // AT_VMATRIX_ARRAY,
};
//-----------------------------------------------------------------------------
// make sure that the attribute data type sizes are what we think they are to choose the right allocator
//-----------------------------------------------------------------------------
struct CSizeTest
{
CSizeTest()
{
// test internal value attribute sizes
COMPILE_TIME_ASSERT( sizeof( int ) == 4 );
COMPILE_TIME_ASSERT( sizeof( float ) == 4 );
COMPILE_TIME_ASSERT( sizeof( bool ) <= 4 );
COMPILE_TIME_ASSERT( sizeof( Color ) == 4 );
COMPILE_TIME_ASSERT( sizeof( Vector2D ) == 8 );
COMPILE_TIME_ASSERT( sizeof( Vector ) == 12 );
COMPILE_TIME_ASSERT( sizeof( Vector4D ) == 16 );
COMPILE_TIME_ASSERT( sizeof( QAngle ) == 12 );
COMPILE_TIME_ASSERT( sizeof( Quaternion ) == 16 );
COMPILE_TIME_ASSERT( sizeof( VMatrix ) == 64 );
COMPILE_TIME_ASSERT( sizeof( CUtlString ) == 4 );
COMPILE_TIME_ASSERT( sizeof( CUtlBinaryBlock ) == 16 );
COMPILE_TIME_ASSERT( sizeof( DmObjectId_t ) == 16 );
};
};
static CSizeTest g_sizeTest;
//-----------------------------------------------------------------------------
// Returns attribute name for type
//-----------------------------------------------------------------------------
const char *g_pAttributeTypeName[AT_TYPE_COUNT] =
{
"unknown", // AT_UNKNOWN
CDmAttributeInfo<DmElementHandle_t>::AttributeTypeName(), // AT_ELEMENT,
CDmAttributeInfo<int>::AttributeTypeName(), // AT_INT,
CDmAttributeInfo<float>::AttributeTypeName(), // AT_FLOAT,
CDmAttributeInfo<bool>::AttributeTypeName(), // AT_BOOL,
CDmAttributeInfo<CUtlString>::AttributeTypeName(), // AT_STRING,
CDmAttributeInfo<CUtlBinaryBlock>::AttributeTypeName(), // AT_VOID,
CDmAttributeInfo<DmObjectId_t>::AttributeTypeName(), // AT_OBJECTID,
CDmAttributeInfo<Color>::AttributeTypeName(), // AT_COLOR,
CDmAttributeInfo<Vector2D>::AttributeTypeName(), // AT_VECTOR2,
CDmAttributeInfo<Vector>::AttributeTypeName(), // AT_VECTOR3,
CDmAttributeInfo<Vector4D>::AttributeTypeName(), // AT_VECTOR4,
CDmAttributeInfo<QAngle>::AttributeTypeName(), // AT_QANGLE,
CDmAttributeInfo<Quaternion>::AttributeTypeName(), // AT_QUATERNION,
CDmAttributeInfo<VMatrix>::AttributeTypeName(), // AT_VMATRIX,
CDmAttributeInfo< CUtlVector< DmElementHandle_t > >::AttributeTypeName(), // AT_ELEMENT_ARRAY,
CDmAttributeInfo< CUtlVector< int > >::AttributeTypeName(), // AT_INT_ARRAY,
CDmAttributeInfo< CUtlVector< float > >::AttributeTypeName(), // AT_FLOAT_ARRAY,
CDmAttributeInfo< CUtlVector< bool > >::AttributeTypeName(), // AT_BOOL_ARRAY,
CDmAttributeInfo< CUtlVector< CUtlString > >::AttributeTypeName(), // AT_STRING_ARRAY,
CDmAttributeInfo< CUtlVector< CUtlBinaryBlock > >::AttributeTypeName(), // AT_VOID_ARRAY,
CDmAttributeInfo< CUtlVector< DmObjectId_t > >::AttributeTypeName(), // AT_OBJECTID_ARRAY,
CDmAttributeInfo< CUtlVector< Color > >::AttributeTypeName(), // AT_COLOR_ARRAY,
CDmAttributeInfo< CUtlVector< Vector2D > >::AttributeTypeName(), // AT_VECTOR2_ARRAY,
CDmAttributeInfo< CUtlVector< Vector > >::AttributeTypeName(), // AT_VECTOR3_ARRAY,
CDmAttributeInfo< CUtlVector< Vector4D > >::AttributeTypeName(), // AT_VECTOR4_ARRAY,
CDmAttributeInfo< CUtlVector< QAngle > >::AttributeTypeName(), // AT_QANGLE_ARRAY,
CDmAttributeInfo< CUtlVector< Quaternion > >::AttributeTypeName(), // AT_QUATERNION_ARRAY,
CDmAttributeInfo< CUtlVector< VMatrix > >::AttributeTypeName(), // AT_VMATRIX_ARRAY,
};
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CDmxAttribute::CDmxAttribute( const char *pAttributeName )
{
m_Name = s_AttributeNameSymbols.AddString( pAttributeName );
m_Type = AT_UNKNOWN;
m_pData = NULL;
}
CDmxAttribute::CDmxAttribute( CUtlSymbol attributeName )
{
m_Name = attributeName;
m_Type = AT_UNKNOWN;
m_pData = NULL;
}
CDmxAttribute::~CDmxAttribute()
{
FreeDataMemory();
}
//-----------------------------------------------------------------------------
// Returns the size of the variables storing the various attribute types
//-----------------------------------------------------------------------------
int CDmxAttribute::AttributeDataSize( DmAttributeType_t type )
{
return s_pAttributeSize[type];
}
//-----------------------------------------------------------------------------
// Allocate, free memory for data
//-----------------------------------------------------------------------------
void CDmxAttribute::AllocateDataMemory( DmAttributeType_t type )
{
FreeDataMemory();
m_Type = type;
m_pData = DMXAlloc( s_pAttributeSize[m_Type] );
}
#define DESTRUCT_ARRAY( _dataType ) \
case CDmAttributeInfo< CUtlVector< _dataType > >::ATTRIBUTE_TYPE: \
Destruct( ( CUtlVector< _dataType >* )m_pData ); \
break;
void CDmxAttribute::FreeDataMemory()
{
if ( m_Type != AT_UNKNOWN )
{
Assert( m_pData != NULL );
if ( !IsArrayType( m_Type ) )
{
if ( m_Type == AT_STRING )
{
Destruct( (CUtlString*)m_pData );
}
else if ( m_Type == AT_VOID )
{
Destruct( (CUtlBinaryBlock*)m_pData );
}
}
else
{
switch ( m_Type )
{
DESTRUCT_ARRAY( int );
DESTRUCT_ARRAY( float );
DESTRUCT_ARRAY( bool );
DESTRUCT_ARRAY( CUtlString );
DESTRUCT_ARRAY( CUtlBinaryBlock );
DESTRUCT_ARRAY( DmObjectId_t );
DESTRUCT_ARRAY( Color );
DESTRUCT_ARRAY( Vector2D );
DESTRUCT_ARRAY( Vector );
DESTRUCT_ARRAY( Vector4D );
DESTRUCT_ARRAY( QAngle );
DESTRUCT_ARRAY( Quaternion );
DESTRUCT_ARRAY( VMatrix );
DESTRUCT_ARRAY( CDmxElement* );
}
}
m_Type = AT_UNKNOWN;
}
}
//-----------------------------------------------------------------------------
// Returns attribute type string
//-----------------------------------------------------------------------------
inline const char* CDmxAttribute::GetTypeString() const
{
return g_pAttributeTypeName[ m_Type ];
}
//-----------------------------------------------------------------------------
// Returns attribute name
//-----------------------------------------------------------------------------
const char *CDmxAttribute::GetName() const
{
return s_AttributeNameSymbols.String( m_Name );
}
//-----------------------------------------------------------------------------
// Gets the size of an array, returns 0 if it's not an array type
//-----------------------------------------------------------------------------
#define GET_ARRAY_COUNT( _dataType ) \
case CDmAttributeInfo< CUtlVector< _dataType > >::ATTRIBUTE_TYPE: \
{ \
const CUtlVector< _dataType > &array = *( CUtlVector< _dataType >* )m_pData; \
return array.Count(); \
}
int CDmxAttribute::GetArrayCount() const
{
if ( !IsArrayType( m_Type ) || !m_pData )
return 0;
switch( m_Type )
{
GET_ARRAY_COUNT( int );
GET_ARRAY_COUNT( float );
GET_ARRAY_COUNT( bool );
GET_ARRAY_COUNT( CUtlString );
GET_ARRAY_COUNT( CUtlBinaryBlock );
GET_ARRAY_COUNT( DmObjectId_t );
GET_ARRAY_COUNT( Color );
GET_ARRAY_COUNT( Vector2D );
GET_ARRAY_COUNT( Vector );
GET_ARRAY_COUNT( Vector4D );
GET_ARRAY_COUNT( QAngle );
GET_ARRAY_COUNT( Quaternion );
GET_ARRAY_COUNT( VMatrix );
GET_ARRAY_COUNT( CDmxElement* );
}
return 0;
}
//-----------------------------------------------------------------------------
// Gets the size of an array, returns 0 if it's not an array type
//-----------------------------------------------------------------------------
#define SERIALIZES_ON_MULTIPLE_LINES( _dataType ) \
case CDmAttributeInfo< _dataType >::ATTRIBUTE_TYPE: \
return ::SerializesOnMultipleLines< _dataType >(); \
case CDmAttributeInfo< CUtlVector< _dataType > >::ATTRIBUTE_TYPE: \
return ::SerializesOnMultipleLines< CUtlVector< _dataType > >()
bool CDmxAttribute::SerializesOnMultipleLines() const
{
switch( m_Type )
{
SERIALIZES_ON_MULTIPLE_LINES( CDmxElement* );
SERIALIZES_ON_MULTIPLE_LINES( int );
SERIALIZES_ON_MULTIPLE_LINES( float );
SERIALIZES_ON_MULTIPLE_LINES( bool );
SERIALIZES_ON_MULTIPLE_LINES( CUtlString );
SERIALIZES_ON_MULTIPLE_LINES( CUtlBinaryBlock );
SERIALIZES_ON_MULTIPLE_LINES( DmObjectId_t );
SERIALIZES_ON_MULTIPLE_LINES( Color );
SERIALIZES_ON_MULTIPLE_LINES( Vector2D );
SERIALIZES_ON_MULTIPLE_LINES( Vector );
SERIALIZES_ON_MULTIPLE_LINES( Vector4D );
SERIALIZES_ON_MULTIPLE_LINES( QAngle );
SERIALIZES_ON_MULTIPLE_LINES( Quaternion );
SERIALIZES_ON_MULTIPLE_LINES( VMatrix );
}
return false;
}
//-----------------------------------------------------------------------------
// Write to file
//-----------------------------------------------------------------------------
#define SERIALIZE_TYPE( _buf, _attributeType, _dataType ) \
case _attributeType: \
{ \
if ( m_pData ) \
return ::Serialize( _buf, *(_dataType*)m_pData ); \
_dataType temp; \
CDmAttributeInfo< _dataType >::SetDefaultValue( temp ); \
return ::Serialize( _buf, temp ); \
}
#define SERIALIZE_ARRAY_TYPE( _buf, _attributeType, _dataType ) \
case _attributeType: \
{ \
if ( m_pData ) \
return ::Serialize( _buf, *(CUtlVector< _dataType >*)m_pData ); \
CUtlVector< _dataType > temp; \
CDmAttributeInfo< CUtlVector< _dataType > >::SetDefaultValue( temp ); \
return ::Serialize( _buf, temp ); \
}
bool CDmxAttribute::Serialize( CUtlBuffer &buf ) const
{
switch( m_Type )
{
SERIALIZE_TYPE( buf, AT_INT, int );
SERIALIZE_TYPE( buf, AT_FLOAT, float );
SERIALIZE_TYPE( buf, AT_BOOL, bool );
SERIALIZE_TYPE( buf, AT_STRING, CUtlString );
SERIALIZE_TYPE( buf, AT_VOID, CUtlBinaryBlock );
SERIALIZE_TYPE( buf, AT_OBJECTID, DmObjectId_t );
SERIALIZE_TYPE( buf, AT_COLOR, Color );
SERIALIZE_TYPE( buf, AT_VECTOR2, Vector2D );
SERIALIZE_TYPE( buf, AT_VECTOR3, Vector );
SERIALIZE_TYPE( buf, AT_VECTOR4, Vector4D );
SERIALIZE_TYPE( buf, AT_QANGLE, QAngle );
SERIALIZE_TYPE( buf, AT_QUATERNION, Quaternion );
SERIALIZE_TYPE( buf, AT_VMATRIX, VMatrix );
SERIALIZE_ARRAY_TYPE( buf, AT_INT_ARRAY, int );
SERIALIZE_ARRAY_TYPE( buf, AT_FLOAT_ARRAY, float );
SERIALIZE_ARRAY_TYPE( buf, AT_BOOL_ARRAY, bool );
SERIALIZE_ARRAY_TYPE( buf, AT_STRING_ARRAY, CUtlString );
SERIALIZE_ARRAY_TYPE( buf, AT_VOID_ARRAY, CUtlBinaryBlock );
SERIALIZE_ARRAY_TYPE( buf, AT_OBJECTID_ARRAY, DmObjectId_t );
SERIALIZE_ARRAY_TYPE( buf, AT_COLOR_ARRAY, Color );
SERIALIZE_ARRAY_TYPE( buf, AT_VECTOR2_ARRAY, Vector2D );
SERIALIZE_ARRAY_TYPE( buf, AT_VECTOR3_ARRAY, Vector );
SERIALIZE_ARRAY_TYPE( buf, AT_VECTOR4_ARRAY, Vector4D );
SERIALIZE_ARRAY_TYPE( buf, AT_QANGLE_ARRAY, QAngle );
SERIALIZE_ARRAY_TYPE( buf, AT_QUATERNION_ARRAY, Quaternion );
SERIALIZE_ARRAY_TYPE( buf, AT_VMATRIX_ARRAY, VMatrix );
default:
AssertMsg( 0, "Cannot serialize elements or element arrays!\n" );
return false;
}
return false;
}
//-----------------------------------------------------------------------------
// Serialize a single element in an array attribute
//-----------------------------------------------------------------------------
#define SERIALIZE_TYPED_ELEMENT( _index, _buf, _attributeType, _dataType ) \
case _attributeType: \
{ \
if ( m_pData ) \
{ \
const CUtlVector< _dataType > &array = *( CUtlVector< _dataType >* )m_pData;\
return ::Serialize( buf, array[_index] ); \
} \
_dataType temp; \
CDmAttributeInfo< _dataType >::SetDefaultValue( temp ); \
return ::Serialize( _buf, temp ); \
}
bool CDmxAttribute::SerializeElement( int nIndex, CUtlBuffer &buf ) const
{
if ( !IsArrayType( m_Type ) )
return false;
switch( m_Type )
{
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_INT_ARRAY, int );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_FLOAT_ARRAY, float );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_BOOL_ARRAY, bool );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_STRING_ARRAY, CUtlString );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_VOID_ARRAY, CUtlBinaryBlock );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_OBJECTID_ARRAY, DmObjectId_t );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_COLOR_ARRAY, Color );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_VECTOR2_ARRAY, Vector2D );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_VECTOR3_ARRAY, Vector );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_VECTOR4_ARRAY, Vector4D );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_QANGLE_ARRAY, QAngle );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_QUATERNION_ARRAY, Quaternion );
SERIALIZE_TYPED_ELEMENT( nIndex, buf, AT_VMATRIX_ARRAY, VMatrix );
default:
AssertMsg( 0, "Cannot serialize elements!\n" );
return false;
}
return false;
}
//-----------------------------------------------------------------------------
// Read from file
//-----------------------------------------------------------------------------
#define UNSERIALIZE_TYPE( _buf, _attributeType, _dataType ) \
case _attributeType: \
Construct( (_dataType*)m_pData ); \
return ::Unserialize( _buf, *(_dataType*)m_pData )
#define UNSERIALIZE_ARRAY_TYPE( _buf, _attributeType, _dataType ) \
case _attributeType: \
Construct( (CUtlVector< _dataType > *)m_pData ); \
return ::Unserialize( _buf, *(CUtlVector< _dataType >*)m_pData )
bool CDmxAttribute::Unserialize( DmAttributeType_t type, CUtlBuffer &buf )
{
AllocateDataMemory( type );
switch( type )
{
UNSERIALIZE_TYPE( buf, AT_INT, int );
UNSERIALIZE_TYPE( buf, AT_FLOAT, float );
UNSERIALIZE_TYPE( buf, AT_BOOL, bool );
UNSERIALIZE_TYPE( buf, AT_STRING, CUtlString );
UNSERIALIZE_TYPE( buf, AT_VOID, CUtlBinaryBlock );
UNSERIALIZE_TYPE( buf, AT_OBJECTID, DmObjectId_t );
UNSERIALIZE_TYPE( buf, AT_COLOR, Color );
UNSERIALIZE_TYPE( buf, AT_VECTOR2, Vector2D );
UNSERIALIZE_TYPE( buf, AT_VECTOR3, Vector );
UNSERIALIZE_TYPE( buf, AT_VECTOR4, Vector4D );
UNSERIALIZE_TYPE( buf, AT_QANGLE, QAngle );
UNSERIALIZE_TYPE( buf, AT_QUATERNION, Quaternion );
UNSERIALIZE_TYPE( buf, AT_VMATRIX, VMatrix );
UNSERIALIZE_ARRAY_TYPE( buf, AT_INT_ARRAY, int );
UNSERIALIZE_ARRAY_TYPE( buf, AT_FLOAT_ARRAY, float );
UNSERIALIZE_ARRAY_TYPE( buf, AT_BOOL_ARRAY, bool );
UNSERIALIZE_ARRAY_TYPE( buf, AT_STRING_ARRAY, CUtlString );
UNSERIALIZE_ARRAY_TYPE( buf, AT_VOID_ARRAY, CUtlBinaryBlock );
UNSERIALIZE_ARRAY_TYPE( buf, AT_OBJECTID_ARRAY, DmObjectId_t );
UNSERIALIZE_ARRAY_TYPE( buf, AT_COLOR_ARRAY, Color );
UNSERIALIZE_ARRAY_TYPE( buf, AT_VECTOR2_ARRAY, Vector2D );
UNSERIALIZE_ARRAY_TYPE( buf, AT_VECTOR3_ARRAY, Vector );
UNSERIALIZE_ARRAY_TYPE( buf, AT_VECTOR4_ARRAY, Vector4D );
UNSERIALIZE_ARRAY_TYPE( buf, AT_QANGLE_ARRAY, QAngle );
UNSERIALIZE_ARRAY_TYPE( buf, AT_QUATERNION_ARRAY, Quaternion );
UNSERIALIZE_ARRAY_TYPE( buf, AT_VMATRIX_ARRAY, VMatrix );
default:
AssertMsg( 0, "Cannot unserialize elements or element arrays!\n" );
return false;
}
return false;
}
//-----------------------------------------------------------------------------
// Read element from file
//-----------------------------------------------------------------------------
#define UNSERIALIZE_TYPED_ELEMENT( _buf, _attributeType, _dataType ) \
case _attributeType: \
{ \
if ( !bIsDataMemoryAllocated ) \
{ \
Construct( (CUtlVector< _dataType > *)m_pData ); \
} \
_dataType temp; \
bool bReadElement = ::Unserialize( _buf, temp ); \
if ( bReadElement ) \
{ \
GetArrayForEdit< _dataType >().AddToTail( temp ); \
} \
return bReadElement; \
}
bool CDmxAttribute::UnserializeElement( DmAttributeType_t type, CUtlBuffer &buf )
{
if ( !IsArrayType( type ) )
return false;
bool bIsDataMemoryAllocated = ( m_Type == type );
if ( !bIsDataMemoryAllocated )
{
AllocateDataMemory( type );
}
switch( type )
{
UNSERIALIZE_TYPED_ELEMENT( buf, AT_INT_ARRAY, int );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_FLOAT_ARRAY, float );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_BOOL_ARRAY, bool );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_STRING_ARRAY, CUtlString );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_VOID_ARRAY, CUtlBinaryBlock );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_OBJECTID_ARRAY, DmObjectId_t );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_COLOR_ARRAY, Color );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_VECTOR2_ARRAY, Vector2D );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_VECTOR3_ARRAY, Vector );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_VECTOR4_ARRAY, Vector4D );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_QANGLE_ARRAY, QAngle );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_QUATERNION_ARRAY, Quaternion );
UNSERIALIZE_TYPED_ELEMENT( buf, AT_VMATRIX_ARRAY, VMatrix );
default:
AssertMsg( 0, "Cannot unserialize elements!\n" );
return false;
}
return false;
}
//-----------------------------------------------------------------------------
// Sets name
//-----------------------------------------------------------------------------
void CDmxAttribute::SetName( const char *pAttributeName )
{
m_Name = s_AttributeNameSymbols.Find( pAttributeName );
}
//-----------------------------------------------------------------------------
// Sets values
//-----------------------------------------------------------------------------
void CDmxAttribute::SetValue( const char *pString )
{
AllocateDataMemory( AT_STRING );
CUtlString* pUtlString = (CUtlString*)m_pData;
Construct( pUtlString );
pUtlString->Set( pString );
}
void CDmxAttribute::SetValue( const void *pBuffer, size_t nLen )
{
AllocateDataMemory( AT_VOID );
CUtlBinaryBlock* pBlob = (CUtlBinaryBlock*)m_pData;
Construct( pBlob );
pBlob->Set( pBuffer, nLen );
}
// Untyped method for setting used by unpack
void CDmxAttribute::SetValue( DmAttributeType_t type, const void *pSrc, int nLen )
{
if ( m_Type != type )
{
AllocateDataMemory( type );
}
Assert( nLen == CDmxAttribute::AttributeDataSize( type ) );
if ( nLen > CDmxAttribute::AttributeDataSize( type ) )
{
nLen = CDmxAttribute::AttributeDataSize( type );
}
memcpy( m_pData, pSrc, nLen );
}
void CDmxAttribute::SetValue( const CDmxAttribute *pAttribute )
{
DmAttributeType_t type = pAttribute->GetType();
if ( !IsArrayType( type ) )
{
SetValue( type, pAttribute->m_pData, CDmxAttribute::AttributeDataSize( type ) );
}
else
{
// Copying array attributes not done yet..
Assert( 0 );
}
}
// Sets the attribute to its default value based on its type
#define SET_DEFAULT_VALUE( _dataType ) \
case CDmAttributeInfo< _dataType >::ATTRIBUTE_TYPE: \
CDmAttributeInfo< _dataType >::SetDefaultValue( *reinterpret_cast< _dataType* >( m_pData ) ); \
break; \
case CDmAttributeInfo< CUtlVector< _dataType > >::ATTRIBUTE_TYPE: \
CDmAttributeInfo< CUtlVector< _dataType > >::SetDefaultValue( *reinterpret_cast< CUtlVector< _dataType > * >( m_pData ) ); \
break
void CDmxAttribute::SetToDefaultValue()
{
switch( GetType() )
{
SET_DEFAULT_VALUE( int );
SET_DEFAULT_VALUE( float );
SET_DEFAULT_VALUE( bool );
SET_DEFAULT_VALUE( CUtlString );
SET_DEFAULT_VALUE( CUtlBinaryBlock );
SET_DEFAULT_VALUE( DmObjectId_t );
SET_DEFAULT_VALUE( Color );
SET_DEFAULT_VALUE( Vector2D );
SET_DEFAULT_VALUE( Vector );
SET_DEFAULT_VALUE( Vector4D );
SET_DEFAULT_VALUE( QAngle );
SET_DEFAULT_VALUE( Quaternion );
SET_DEFAULT_VALUE( VMatrix );
SET_DEFAULT_VALUE( CDmxElement* );
default:
break;
}
}
//-----------------------------------------------------------------------------
// Convert to and from string
//-----------------------------------------------------------------------------
void CDmxAttribute::SetValueFromString( const char *pValue )
{
switch ( GetType() )
{
case AT_UNKNOWN:
break;
case AT_STRING:
SetValue( pValue );
break;
default:
{
int nLen = pValue ? Q_strlen( pValue ) : 0;
if ( nLen == 0 )
{
SetToDefaultValue();
break;
}
CUtlBuffer buf( pValue, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
if ( !Unserialize( GetType(), buf ) )
{
SetToDefaultValue();
}
}
break;
}
}
const char *CDmxAttribute::GetValueAsString( char *pBuffer, size_t nBufLen ) const
{
Assert( pBuffer );
CUtlBuffer buf( pBuffer, nBufLen, CUtlBuffer::TEXT_BUFFER );
Serialize( buf );
return pBuffer;
}

489
dmxloader/dmxelement.cpp Normal file
View File

@ -0,0 +1,489 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "dmxloader/dmxelement.h"
#include "dmxloader/dmxattribute.h"
#include "tier1/utlbuffer.h"
#include "mathlib/ssemath.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// globals
//-----------------------------------------------------------------------------
CUtlSymbolTableMT CDmxElement::s_TypeSymbols;
//-----------------------------------------------------------------------------
// Creates a dmx element
//-----------------------------------------------------------------------------
CDmxElement* CreateDmxElement( const char *pType )
{
return new CDmxElement( pType );
}
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CDmxElement::CDmxElement( const char *pType )
{
m_Type = s_TypeSymbols.AddString( pType );
m_nLockCount = 0;
m_bResortNeeded = false;
m_bIsMarkedForDeletion = false;
CreateUniqueId( &m_Id );
}
CDmxElement::~CDmxElement()
{
CDmxElementModifyScope modify( this );
RemoveAllAttributes();
}
//-----------------------------------------------------------------------------
// Utility method for getting at the type
//-----------------------------------------------------------------------------
CUtlSymbol CDmxElement::GetType() const
{
return m_Type;
}
const char* CDmxElement::GetTypeString() const
{
return s_TypeSymbols.String( m_Type );
}
const char* CDmxElement::GetName() const
{
return GetValue< CUtlString >( "name" );
}
const DmObjectId_t &CDmxElement::GetId() const
{
return m_Id;
}
//-----------------------------------------------------------------------------
// Sets the object id
//-----------------------------------------------------------------------------
void CDmxElement::SetId( const DmObjectId_t &id )
{
CopyUniqueId( id, &m_Id );
}
//-----------------------------------------------------------------------------
// Sorts the vector when a change has occurred
//-----------------------------------------------------------------------------
void CDmxElement::Resort( ) const
{
if ( m_bResortNeeded )
{
AttributeList_t *pAttributes = const_cast< AttributeList_t *>( &m_Attributes );
pAttributes->RedoSort();
m_bResortNeeded = false;
// NOTE: This checks for duplicate attribute names
int nCount = m_Attributes.Count();
for ( int i = nCount; --i >= 1; )
{
if ( m_Attributes[i]->GetNameSymbol() == m_Attributes[i-1]->GetNameSymbol() )
{
Warning( "Duplicate attribute name %s encountered!\n", m_Attributes[i]->GetName() );
pAttributes->Remove(i);
Assert( 0 );
}
}
}
}
//-----------------------------------------------------------------------------
// Enables modification of the DmxElement
//-----------------------------------------------------------------------------
void CDmxElement::LockForChanges( bool bLock )
{
if ( bLock )
{
++m_nLockCount;
}
else
{
if ( --m_nLockCount == 0 )
{
Resort();
}
Assert( m_nLockCount >= 0 );
}
}
//-----------------------------------------------------------------------------
// Adds, removes attributes
//-----------------------------------------------------------------------------
CDmxAttribute *CDmxElement::AddAttribute( const char *pAttributeName )
{
int nIndex = FindAttribute( pAttributeName );
if ( nIndex >= 0 )
return m_Attributes[nIndex];
CDmxElementModifyScope modify( this );
m_bResortNeeded = true;
CDmxAttribute *pAttribute = new CDmxAttribute( pAttributeName );
m_Attributes.InsertNoSort( pAttribute );
return pAttribute;
}
void CDmxElement::RemoveAttribute( const char *pAttributeName )
{
CDmxElementModifyScope modify( this );
int idx = FindAttribute( pAttributeName );
if ( idx >= 0 )
{
delete m_Attributes[idx];
m_Attributes.Remove( idx );
}
}
void CDmxElement::RemoveAttributeByPtr( CDmxAttribute *pAttribute )
{
CDmxElementModifyScope modify( this );
int nCount = m_Attributes.Count();
for ( int i = 0; i < nCount; ++i )
{
if ( m_Attributes[i] != pAttribute )
continue;
delete pAttribute;
m_Attributes.Remove( i );
break;
}
}
void CDmxElement::RemoveAllAttributes()
{
int nCount = m_Attributes.Count();
for ( int i = 0; i < nCount; ++i )
{
delete m_Attributes[i];
}
m_Attributes.RemoveAll();
m_bResortNeeded = false;
}
//-----------------------------------------------------------------------------
// Rename an attribute
//-----------------------------------------------------------------------------
void CDmxElement::RenameAttribute( const char *pAttributeName, const char *pNewName )
{
CDmxElementModifyScope modify( this );
// No change...
if ( !Q_stricmp( pAttributeName, pNewName ) )
return;
int idx = FindAttribute( pAttributeName );
if ( idx < 0 )
return;
if ( HasAttribute( pNewName ) )
{
Warning( "Tried to rename from \"%s\" to \"%s\", but \"%s\" already exists!\n",
pAttributeName, pNewName, pNewName );
return;
}
m_bResortNeeded = true;
m_Attributes[ idx ]->SetName( pNewName );
}
//-----------------------------------------------------------------------------
// Find an attribute by name-based lookup
//-----------------------------------------------------------------------------
int CDmxElement::FindAttribute( const char *pAttributeName ) const
{
// FIXME: The cost here is O(log M) + O(log N)
// where log N is the binary search for the symbol match
// and log M is the binary search for the attribute name->symbol
// We can eliminate log M by using a hash table in the symbol lookup
Resort();
CDmxAttribute search( pAttributeName );
return m_Attributes.Find( &search );
}
//-----------------------------------------------------------------------------
// Find an attribute by name-based lookup
//-----------------------------------------------------------------------------
int CDmxElement::FindAttribute( CUtlSymbol attributeName ) const
{
Resort();
CDmxAttribute search( attributeName );
return m_Attributes.Find( &search );
}
//-----------------------------------------------------------------------------
// Attribute finding
//-----------------------------------------------------------------------------
bool CDmxElement::HasAttribute( const char *pAttributeName ) const
{
int idx = FindAttribute( pAttributeName );
return ( idx >= 0 );
}
CDmxAttribute *CDmxElement::GetAttribute( const char *pAttributeName )
{
int idx = FindAttribute( pAttributeName );
if ( idx >= 0 )
return m_Attributes[ idx ];
return NULL;
}
const CDmxAttribute *CDmxElement::GetAttribute( const char *pAttributeName ) const
{
int idx = FindAttribute( pAttributeName );
if ( idx >= 0 )
return m_Attributes[ idx ];
return NULL;
}
//-----------------------------------------------------------------------------
// Attribute interation
//-----------------------------------------------------------------------------
int CDmxElement::AttributeCount() const
{
return m_Attributes.Count();
}
CDmxAttribute *CDmxElement::GetAttribute( int nIndex )
{
return m_Attributes[ nIndex ];
}
const CDmxAttribute *CDmxElement::GetAttribute( int nIndex ) const
{
return m_Attributes[ nIndex ];
}
//-----------------------------------------------------------------------------
// Removes all elements recursively
//-----------------------------------------------------------------------------
void CDmxElement::AddElementsToDelete( CUtlVector< CDmxElement * >& elementsToDelete )
{
if ( m_bIsMarkedForDeletion )
return;
m_bIsMarkedForDeletion = true;
elementsToDelete.AddToTail( this );
int nCount = AttributeCount();
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pAttribute = GetAttribute(i);
if ( pAttribute->GetType() == AT_ELEMENT )
{
CDmxElement *pElement = pAttribute->GetValue< CDmxElement* >();
if ( pElement )
{
pElement->AddElementsToDelete( elementsToDelete );
}
continue;
}
if ( pAttribute->GetType() == AT_ELEMENT_ARRAY )
{
const CUtlVector< CDmxElement * > &elements = pAttribute->GetArray< CDmxElement* >();
int nElementCount = elements.Count();
for ( int j = 0; j < nElementCount; ++j )
{
if ( elements[j] )
{
elements[j]->AddElementsToDelete( elementsToDelete );
}
}
continue;
}
}
}
//-----------------------------------------------------------------------------
// Removes all elements recursively
//-----------------------------------------------------------------------------
void CDmxElement::RemoveAllElementsRecursive()
{
CUtlVector< CDmxElement * > elementsToDelete;
AddElementsToDelete( elementsToDelete );
int nCount = elementsToDelete.Count();
for ( int i = 0; i < nCount; ++i )
{
delete elementsToDelete[i];
}
}
//-----------------------------------------------------------------------------
// Method to unpack data into a structure
//-----------------------------------------------------------------------------
void CDmxElement::UnpackIntoStructure( void *pData, size_t DestSizeInBytes, const DmxElementUnpackStructure_t *pUnpack ) const
{
void *pDataEnd = ( char * )pData + DestSizeInBytes;
for ( ; pUnpack->m_AttributeType != AT_UNKNOWN; ++pUnpack )
{
char *pDest = (char*)pData + pUnpack->m_nOffset;
// NOTE: This does not work with array data at the moment
if ( IsArrayType( pUnpack->m_AttributeType ) )
{
AssertMsg( 0, ( "CDmxElement::UnpackIntoStructure: Array attribute types not currently supported!\n" ) );
continue;
}
if ( pUnpack->m_AttributeType == AT_VOID )
{
AssertMsg( 0, ( "CDmxElement::UnpackIntoStructure: Binary blob attribute types not currently supported!\n" ) );
continue;
}
CDmxAttribute temp( NULL );
const CDmxAttribute *pAttribute = GetAttribute( pUnpack->m_pAttributeName );
if ( !pAttribute )
{
if ( !pUnpack->m_pDefaultString )
continue;
// Convert the default string into the target
int nLen = Q_strlen( pUnpack->m_pDefaultString );
if ( nLen > 0 )
{
CUtlBuffer buf( pUnpack->m_pDefaultString, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER );
temp.Unserialize( pUnpack->m_AttributeType, buf );
}
else
{
CUtlBuffer buf;
temp.Unserialize( pUnpack->m_AttributeType, buf );
}
pAttribute = &temp;
}
if ( pUnpack->m_AttributeType != pAttribute->GetType() )
{
Warning( "CDmxElement::UnpackIntoStructure: Mismatched attribute type in attribute \"%s\"!\n", pUnpack->m_pAttributeName );
continue;
}
if ( pAttribute->GetType() == AT_STRING )
{
if ( pDest + pUnpack->m_nSize > pDataEnd )
{
Warning( "ERROR Memory corruption: CDmxElement::UnpackIntoStructure string buffer overrun!\n" );
continue;
}
// Strings get special treatment: they are stored as in-line arrays of chars
Q_strncpy( pDest, pAttribute->GetValueString(), pUnpack->m_nSize );
continue;
}
// special case - if data type is float, but dest size == 16, we are unpacking into simd by
// replication
if ( ( pAttribute->GetType() == AT_FLOAT ) && ( pUnpack->m_nSize == sizeof( fltx4 ) ) )
{
if ( pDest + 4 * sizeof( float ) > pDataEnd )
{
Warning( "ERROR Memory corruption: CDmxElement::UnpackIntoStructure float buffer overrun!\n" );
continue;
}
memcpy( pDest + 0 * sizeof( float ) , pAttribute->m_pData, sizeof( float ) );
memcpy( pDest + 1 * sizeof( float ) , pAttribute->m_pData, sizeof( float ) );
memcpy( pDest + 2 * sizeof( float ) , pAttribute->m_pData, sizeof( float ) );
memcpy( pDest + 3 * sizeof( float ) , pAttribute->m_pData, sizeof( float ) );
}
else
{
if ( pDest + pUnpack->m_nSize > pDataEnd )
{
Warning( "ERROR Memory corruption: CDmxElement::UnpackIntoStructure memcpy buffer overrun!\n" );
continue;
}
AssertMsg( pUnpack->m_nSize == CDmxAttribute::AttributeDataSize( pAttribute->GetType() ),
"CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into in attribute \"%s\"!\n", pUnpack->m_pAttributeName );
memcpy( pDest, pAttribute->m_pData, pUnpack->m_nSize );
}
}
}
//-----------------------------------------------------------------------------
// Creates attributes based on the unpack structure
//-----------------------------------------------------------------------------
void CDmxElement::AddAttributesFromStructure_Internal( const void *pData, size_t byteCount, const DmxElementUnpackStructure_t *pUnpack )
{
for ( ; pUnpack->m_AttributeType != AT_UNKNOWN; ++pUnpack )
{
const char *pSrc = (const char*)pData + pUnpack->m_nOffset;
// NOTE: This does not work with array data at the moment
if ( IsArrayType( pUnpack->m_AttributeType ) )
{
AssertMsg( 0, "CDmxElement::AddAttributesFromStructure: Array attribute types not currently supported!\n" );
continue;
}
if ( pUnpack->m_AttributeType == AT_VOID )
{
AssertMsg( 0, "CDmxElement::AddAttributesFromStructure: Binary blob attribute types not currently supported!\n" );
continue;
}
if ( HasAttribute( pUnpack->m_pAttributeName ) )
{
AssertMsg( 0, "CDmxElement::AddAttributesFromStructure: Attribute %s already exists!\n", pUnpack->m_pAttributeName );
continue;
}
{
if ( (size_t)(pUnpack->m_nOffset + pUnpack->m_nSize) > byteCount )
{
Msg( "Buffer underread! Mismatched type/type-descriptor.\n" );
}
CDmxElementModifyScope modify( this );
CDmxAttribute *pAttribute = AddAttribute( pUnpack->m_pAttributeName );
if ( pUnpack->m_AttributeType == AT_STRING )
{
pAttribute->SetValue( pSrc );
}
else
{
int nSize = pUnpack->m_nSize;
// handle float attrs stored as replicated fltx4's
if ( ( pUnpack->m_AttributeType == AT_FLOAT ) && ( nSize == sizeof( fltx4 ) ) )
{
nSize = sizeof( float );
}
AssertMsg( nSize == CDmxAttribute::AttributeDataSize( pUnpack->m_AttributeType ),
"CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into in attribute \"%s\"!\n", pUnpack->m_pAttributeName );
pAttribute->SetValue( pUnpack->m_AttributeType, pSrc, nSize );
}
}
}
}

697
dmxloader/dmxloader.cpp Normal file
View File

@ -0,0 +1,697 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "dmxloader/dmxelement.h"
#include "tier1/utlbuffer.h"
#include "tier2/tier2.h"
#include "tier2/utlstreambuffer.h"
#include "filesystem.h"
#include "datamodel/idatamodel.h" // for the file format #defines
#include "dmxserializationdictionary.h"
#include "tier1/memstack.h"
//-----------------------------------------------------------------------------
// DMX elements/attributes can only be accessed inside a dmx context
//-----------------------------------------------------------------------------
static int s_bInDMXContext;
CMemoryStack s_DMXAllocator;
static bool s_bAllocatorInitialized;
void BeginDMXContext( )
{
Assert( !s_bInDMXContext );
if ( !s_bAllocatorInitialized )
{
s_DMXAllocator.Init( 2 * 1024 * 1024, 0, 0, 4 );
s_bAllocatorInitialized = true;
}
s_bInDMXContext = true;
}
void EndDMXContext( bool bDecommitMemory )
{
Assert( s_bInDMXContext );
s_bInDMXContext = false;
s_DMXAllocator.FreeAll( bDecommitMemory );
}
void DecommitDMXMemory()
{
s_DMXAllocator.FreeAll( true );
}
//-----------------------------------------------------------------------------
// Used for allocation. All will be freed when we leave the DMX context
//-----------------------------------------------------------------------------
void* DMXAlloc( size_t size )
{
Assert( s_bInDMXContext );
if ( !s_bInDMXContext )
return 0;
return s_DMXAllocator.Alloc( size, false );
}
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
bool UnserializeTextDMX( const char *pFileName, CUtlBuffer &buf, CDmxElement **ppRoot );
bool SerializeTextDMX( const char *pFileName, CUtlBuffer &buf, CDmxElement *pRoot );
//-----------------------------------------------------------------------------
// special element indices
//-----------------------------------------------------------------------------
enum
{
ELEMENT_INDEX_NULL = -1,
ELEMENT_INDEX_EXTERNAL = -2,
};
//-----------------------------------------------------------------------------
// Serialization class for Binary output
//-----------------------------------------------------------------------------
class CDmxSerializer
{
public:
bool Unserialize( CUtlBuffer &buf, int nEncodingVersion, CDmxElement **ppRoot );
bool Serialize( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName );
private:
// Methods related to serialization
bool ShouldWriteAttribute( const char *pAttributeName, CDmxAttribute *pAttribute );
void SerializeElementIndex( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxElement *pElement );
void SerializeElementAttribute( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxAttribute *pAttribute );
void SerializeElementArrayAttribute( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxAttribute *pAttribute );
bool SaveElementDict( CUtlBuffer& buf, CUtlRBTree< const char* > &stringTable, CDmxElement *pElement );
bool SaveElement( CUtlBuffer& buf, CDmxSerializationDictionary& dict, CUtlRBTree< const char* > &stringTable, CDmxElement *pElement);
// Methods related to unserialization
CDmxElement* UnserializeElementIndex( CUtlBuffer &buf, CUtlVector<CDmxElement*> &elementList );
void UnserializeElementAttribute( CUtlBuffer &buf, CDmxAttribute *pAttribute, CUtlVector<CDmxElement*> &elementList );
void UnserializeElementArrayAttribute( CUtlBuffer &buf, CDmxAttribute *pAttribute, CUtlVector<CDmxElement*> &elementList );
bool UnserializeAttributes( CUtlBuffer &buf, CDmxElement *pElement, CUtlVector<CDmxElement*> &elementList, int nStrings, int *offsetTable, char *stringTable );
int GetStringOffsetTable( CUtlBuffer &buf, int *offsetTable, int nStrings );
};
//-----------------------------------------------------------------------------
// Should we write out the attribute?
//-----------------------------------------------------------------------------
bool CDmxSerializer::ShouldWriteAttribute( const char *pAttributeName, CDmxAttribute *pAttribute )
{
if ( !pAttribute )
return false;
// These are already written in the initial element dictionary
if ( !Q_stricmp( pAttributeName, "name" ) )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Write out the index of the element to avoid looks at read time
//-----------------------------------------------------------------------------
void CDmxSerializer::SerializeElementIndex( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxElement *pElement )
{
if ( !pElement )
{
buf.PutInt( ELEMENT_INDEX_NULL ); // invalid handle
return;
}
buf.PutInt( list.Find( pElement ) );
}
//-----------------------------------------------------------------------------
// Writes out element attributes
//-----------------------------------------------------------------------------
void CDmxSerializer::SerializeElementAttribute( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxAttribute *pAttribute )
{
SerializeElementIndex( buf, list, pAttribute->GetValue<CDmxElement*>() );
}
//-----------------------------------------------------------------------------
// Writes out element array attributes
//-----------------------------------------------------------------------------
void CDmxSerializer::SerializeElementArrayAttribute( CUtlBuffer& buf, CDmxSerializationDictionary& list, CDmxAttribute *pAttribute )
{
const CUtlVector<CDmxElement*> &vec = pAttribute->GetArray<CDmxElement*>();
int nCount = vec.Count();
buf.PutInt( nCount );
for ( int i = 0; i < nCount; ++i )
{
SerializeElementIndex( buf, list, vec[ i ] );
}
}
//-----------------------------------------------------------------------------
// Writes out all attributes
//-----------------------------------------------------------------------------
bool CDmxSerializer::SaveElement( CUtlBuffer& buf, CDmxSerializationDictionary& list, CUtlRBTree< const char* > &stringTable, CDmxElement *pElement )
{
int nAttributesToSave = 0;
// Count the attributes...
int nCount = pElement->AttributeCount();
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pAttribute = pElement->GetAttribute( i );
const char *pName = pAttribute->GetName( );
if ( !ShouldWriteAttribute( pName, pAttribute ) )
continue;
++nAttributesToSave;
}
// Now write them all out.
buf.PutInt( nAttributesToSave );
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pAttribute = pElement->GetAttribute( i );
const char *pName = pAttribute->GetName();
if ( !ShouldWriteAttribute( pName, pAttribute ) )
continue;
unsigned short sym = stringTable.Find( pName );
if ( sym == stringTable.InvalidIndex() )
return false;
buf.PutShort( sym );
buf.PutChar( pAttribute->GetType() );
switch( pAttribute->GetType() )
{
default:
pAttribute->Serialize( buf );
break;
case AT_ELEMENT:
SerializeElementAttribute( buf, list, pAttribute );
break;
case AT_ELEMENT_ARRAY:
SerializeElementArrayAttribute( buf, list, pAttribute );
break;
}
}
return buf.IsValid();
}
bool CDmxSerializer::SaveElementDict( CUtlBuffer& buf, CUtlRBTree< const char* > &stringTable, CDmxElement *pElement )
{
unsigned short sym = stringTable.Find( pElement->GetTypeString() );
if ( sym == stringTable.InvalidIndex() )
return false;
buf.PutShort( sym );
buf.PutString( pElement->GetName() );
buf.Put( &pElement->GetId(), sizeof(DmObjectId_t) );
return buf.IsValid();
}
//-----------------------------------------------------------------------------
// Main entry point for serialization
//-----------------------------------------------------------------------------
bool CDmxSerializer::Serialize( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName )
{
// Save elements, attribute links
CDmxSerializationDictionary dict;
dict.BuildElementList( pRoot, true );
// collect list of attribute names and element types into string table
CUtlRBTree< const char* > stringTable( CaselessStringLessThan );
DmxSerializationHandle_t i;
for ( i = dict.FirstRootElement(); i != DMX_SERIALIZATION_HANDLE_INVALID; i = dict.NextRootElement(i) )
{
CDmxElement *pElement = dict.GetRootElement( i );
if ( !pElement )
return false;
stringTable.InsertIfNotFound( pElement->GetTypeString() );
int nAttributes = pElement->AttributeCount();
for ( int ai = 0; ai < nAttributes; ++ai )
{
CDmxAttribute *pAttr = pElement->GetAttribute( ai );
if ( !pAttr )
return false;
stringTable.InsertIfNotFound( pAttr->GetName() );
}
}
// write out the string table
int nStrings = stringTable.Count();
if ( nStrings > 65535 )
return false;
buf.PutShort( nStrings );
for ( int si = 0; si < nStrings; ++si )
{
buf.PutString( stringTable[ si ] );
}
// First write out the dictionary of all elements (to avoid later stitching up in unserialize)
buf.PutInt( dict.RootElementCount() );
for ( i = dict.FirstRootElement(); i != DMX_SERIALIZATION_HANDLE_INVALID; i = dict.NextRootElement(i) )
{
if ( !SaveElementDict( buf, stringTable, dict.GetRootElement( i ) ) )
return false;
}
// Now write out the attributes of each of those elements
for ( i = dict.FirstRootElement(); i != DMX_SERIALIZATION_HANDLE_INVALID; i = dict.NextRootElement(i) )
{
if ( !SaveElement( buf, dict, stringTable, dict.GetRootElement( i ) ) )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Reads an element index and converts it to a handle (local or external)
//-----------------------------------------------------------------------------
CDmxElement* CDmxSerializer::UnserializeElementIndex( CUtlBuffer &buf, CUtlVector<CDmxElement*> &elementList )
{
int nElementIndex = buf.GetInt();
if ( nElementIndex == ELEMENT_INDEX_EXTERNAL )
{
Warning( "Reading externally referenced elements is not supported!\n" );
return NULL;
}
Assert( nElementIndex < elementList.Count() );
Assert( nElementIndex >= 0 || nElementIndex == ELEMENT_INDEX_NULL );
if ( nElementIndex < 0 || !elementList[ nElementIndex ] )
return NULL;
return elementList[ nElementIndex ];
}
//-----------------------------------------------------------------------------
// Reads an element attribute
//-----------------------------------------------------------------------------
void CDmxSerializer::UnserializeElementAttribute( CUtlBuffer &buf, CDmxAttribute *pAttribute, CUtlVector<CDmxElement*> &elementList )
{
CDmxElement *pElement = UnserializeElementIndex( buf, elementList );
pAttribute->SetValue( pElement );
}
//-----------------------------------------------------------------------------
// Reads an element array attribute
//-----------------------------------------------------------------------------
void CDmxSerializer::UnserializeElementArrayAttribute( CUtlBuffer &buf, CDmxAttribute *pAttribute, CUtlVector<CDmxElement*> &elementList )
{
int nElementCount = buf.GetInt();
CUtlVector< CDmxElement* >& elementArray = pAttribute->GetArrayForEdit< CDmxElement* >();
elementArray.EnsureCapacity( nElementCount );
for ( int i = 0; i < nElementCount; ++i )
{
CDmxElement *pElement = UnserializeElementIndex( buf, elementList );
elementArray.AddToTail( pElement );
}
}
//-----------------------------------------------------------------------------
// Reads a single element
//-----------------------------------------------------------------------------
bool CDmxSerializer::UnserializeAttributes( CUtlBuffer &buf, CDmxElement *pElement, CUtlVector<CDmxElement*> &elementList, int nStrings, int *offsetTable, char *stringTable )
{
CDmxElementModifyScope modify( pElement );
char nameBuf[ 1024 ];
int nAttributeCount = buf.GetInt();
for ( int i = 0; i < nAttributeCount; ++i )
{
const char *pName = NULL;
if ( stringTable )
{
int si = buf.GetShort();
if ( si >= nStrings )
return false;
pName = stringTable + offsetTable[ si ];
}
else
{
buf.GetString( nameBuf );
pName = nameBuf;
}
DmAttributeType_t nAttributeType = (DmAttributeType_t)buf.GetChar();
CDmxAttribute *pAttribute = pElement->AddAttribute( pName );
if ( !pAttribute )
return false;
switch( nAttributeType )
{
default:
pAttribute->Unserialize( nAttributeType, buf );
break;
case AT_ELEMENT:
UnserializeElementAttribute( buf, pAttribute, elementList );
break;
case AT_ELEMENT_ARRAY:
UnserializeElementArrayAttribute( buf, pAttribute, elementList );
break;
}
}
return buf.IsValid();
}
int CDmxSerializer::GetStringOffsetTable( CUtlBuffer &buf, int *offsetTable, int nStrings )
{
int nBytes = buf.GetBytesRemaining();
char *pBegin = ( char* )buf.PeekGet();
char *pBytes = pBegin;
for ( int i = 0; i < nStrings; ++i )
{
offsetTable[ i ] = pBytes - pBegin;
do
{
// grow/shift utlbuffer if it hasn't loaded the entire string table into memory
if ( pBytes - pBegin >= nBytes )
{
pBegin = ( char* )buf.PeekGet( nBytes + 1, 0 );
if ( !pBegin )
return false;
pBytes = pBegin + nBytes;
nBytes = buf.GetBytesRemaining();
}
}
while ( *pBytes++ );
}
return pBytes - pBegin;
}
//-----------------------------------------------------------------------------
// Main entry point for the unserialization
//-----------------------------------------------------------------------------
bool CDmxSerializer::Unserialize( CUtlBuffer &buf, int nEncodingVersion, CDmxElement **ppRoot )
{
if ( nEncodingVersion < 0 || nEncodingVersion > 2 )
return false;
bool bReadStringTable = nEncodingVersion >= 2;
// Keep reading until we read a NULL terminator
while( buf.GetChar() != 0 )
{
if ( !buf.IsValid() )
return false;
}
// Read string table
int nStrings = 0;
int *offsetTable = NULL;
char *stringTable = NULL;
if ( bReadStringTable )
{
nStrings = buf.GetShort();
if ( nStrings > 0 )
{
offsetTable = ( int* )stackalloc( nStrings * sizeof( int ) );
// this causes entire string table to be mapped in memory at once
int nStringMemoryUsage = GetStringOffsetTable( buf, offsetTable, nStrings );
stringTable = ( char* )stackalloc( nStringMemoryUsage * sizeof( char ) );
buf.Get( stringTable, nStringMemoryUsage );
}
}
// Read in the element count.
int nElementCount = buf.GetInt();
if ( !nElementCount )
{
// Empty (but valid) file
return true;
}
if ( nElementCount < 0 || ( bReadStringTable && !stringTable ) )
{
// Invalid file. Non-empty files with a string table need at least one to associate with elements.
return false;
}
char pTypeBuf[256];
char pName[2048];
DmObjectId_t id;
// Read + create all elements
CUtlVector<CDmxElement*> elementList( 0, nElementCount );
for ( int i = 0; i < nElementCount; ++i )
{
const char *pType = NULL;
if ( stringTable )
{
int si = buf.GetShort();
if ( si >= nStrings )
return false;
pType = stringTable + offsetTable[ si ];
}
else
{
buf.GetString( pTypeBuf );
pType = pTypeBuf;
}
buf.GetString( pName );
buf.Get( &id, sizeof(DmObjectId_t) );
CDmxElement *pElement = new CDmxElement( pType );
{
CDmxElementModifyScope modify( pElement );
CDmxAttribute *pAttribute = pElement->AddAttribute( "name" );
pAttribute->SetValue( (char const *) pName );
pElement->SetId( id );
}
elementList.AddToTail( pElement );
}
// The root is the 0th element
*ppRoot = elementList[ 0 ];
// Now read all attributes
for ( int i = 0; i < nElementCount; ++i )
{
UnserializeAttributes( buf, elementList[ i ], elementList, nStrings, offsetTable, stringTable );
}
return buf.IsValid();
}
//-----------------------------------------------------------------------------
// Serialization main entry point
//-----------------------------------------------------------------------------
bool SerializeDMX( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName )
{
// Write the format name into the file using XML format so that
// 3rd-party XML readers can read the file without fail
const char *pEncodingName = buf.IsText() ? "keyvalues2" : "binary";
int nEncodingVersion = buf.IsText() ? 1 : 2; // HACK - we should have some way of automatically updating this when the encoding version changes!
const char *pFormatName = GENERIC_DMX_FORMAT;
int nFormatVersion = 1; // HACK - we should have some way of automatically updating this when the encoding version changes!
buf.Printf( "%s encoding %s %d format %s %d %s\n", DMX_VERSION_STARTING_TOKEN, pEncodingName, nEncodingVersion, pFormatName, nFormatVersion, DMX_VERSION_ENDING_TOKEN );
if ( buf.IsText() )
return SerializeTextDMX( pFileName ? pFileName : "<no file>", buf, pRoot );
CDmxSerializer dmxSerializer;
return dmxSerializer.Serialize( buf, pRoot, pFileName );
}
bool SerializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement *pRoot )
{
// NOTE: This guarantees full path names for pathids
char pBuf[MAX_PATH];
const char *pFullPath = pFileName;
if ( !Q_IsAbsolutePath( pFullPath ) && !pPathID )
{
char pDir[MAX_PATH];
if ( g_pFullFileSystem->GetCurrentDirectory( pDir, sizeof(pDir) ) )
{
Q_ComposeFileName( pDir, pFileName, pBuf, sizeof(pBuf) );
Q_RemoveDotSlashes( pBuf );
pFullPath = pBuf;
}
}
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
g_pFullFileSystem->ReadFile( pFullPath, pPathID, buf );
if ( !buf.IsValid() )
{
Warning( "SerializeDMX: Unable to open file \"%s\"\n", pFullPath );
return DMFILEID_INVALID;
}
return SerializeDMX( buf, pRoot, pFullPath );
}
//-----------------------------------------------------------------------------
// Read the header, return the version (or false if it's not a DMX file)
//-----------------------------------------------------------------------------
bool ReadDMXHeader( CUtlBuffer &buf, char *pEncodingName, int nEncodingNameLen, int &nEncodingVersion, char *pFormatName, int nFormatNameLen, int &nFormatVersion )
{
// Make the buffer capable of being read as text
bool bBufIsText = buf.IsText();
bool bBufHasCRLF = buf.ContainsCRLF();
buf.SetBufferType( true, !bBufIsText || bBufHasCRLF );
char header[ DMX_MAX_HEADER_LENGTH ] = { 0 };
bool bOk = buf.ParseToken( DMX_VERSION_STARTING_TOKEN, DMX_VERSION_ENDING_TOKEN, header, sizeof( header ) );
if ( bOk )
{
#ifdef _WIN32
int nAssigned = sscanf_s( header, "encoding %s %d format %s %d\n", pEncodingName, nEncodingNameLen, &nEncodingVersion, pFormatName, nFormatNameLen, &nFormatVersion );
#else
// sscanf considered harmful. We don't have POSIX 2008 support on OS X and "C11 Annex K" is optional... (optional specs considered useful)
char pTmpEncodingName[ sizeof( header ) ] = { 0 };
char pTmpFormatName [ sizeof( header ) ] = { 0 };
int nAssigned = sscanf( header, "encoding %s %d format %s %d\n", pTmpEncodingName, &nEncodingVersion, pTmpFormatName, &nFormatVersion );
bOk = ( V_strlen( pTmpEncodingName ) < nEncodingNameLen ) && ( V_strlen( pTmpFormatName ) < nFormatNameLen );
V_strncpy( pEncodingName, pTmpEncodingName, nEncodingNameLen );
V_strncpy( pFormatName, pTmpFormatName, nFormatNameLen );
#endif
bOk = bOk && ( nAssigned == 4 );
if ( bOk )
{
bOk = !V_stricmp( pEncodingName, bBufIsText ? "keyvalues2" : "binary" );
}
}
// TODO - retire legacy format version reading
if ( !bOk )
{
buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
bOk = buf.ParseToken( DMX_LEGACY_VERSION_STARTING_TOKEN, DMX_LEGACY_VERSION_ENDING_TOKEN, pFormatName, sizeof( pFormatName ) );
if ( bOk )
{
nEncodingVersion = 0;
nFormatVersion = 0; // format version is encoded in the format name string
if ( !V_stricmp( pFormatName, "binary_v1" ) || !V_stricmp( pFormatName, "binary_v2" ) )
{
bOk = !bBufIsText;
V_strncpy( pEncodingName, "binary", nEncodingNameLen );
}
else if ( !V_stricmp( pFormatName, "keyvalues2_v1" ) || !V_stricmp( pFormatName, "keyvalues2_flat_v1" ) )
{
bOk = bBufIsText;
V_strncpy( pEncodingName, "keyvalues2", nEncodingNameLen );
}
else
{
bOk = false;
}
}
}
// Restore the buffer type
buf.SetBufferType( bBufIsText, bBufHasCRLF );
return bOk && buf.IsValid();
}
//-----------------------------------------------------------------------------
// Unserialization main entry point
//-----------------------------------------------------------------------------
bool UnserializeDMX( CUtlBuffer &buf, CDmxElement **ppRoot, const char *pFileName )
{
// NOTE: Checking the format name string for a version check here is how you'd do it
*ppRoot = NULL;
// Read the standard buffer header
int nEncodingVersion, nFormatVersion;
char pEncodingName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
char pFormatName [ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
if ( !ReadDMXHeader( buf,
pEncodingName, sizeof( pEncodingName ), nEncodingVersion,
pFormatName, sizeof( pFormatName ), nFormatVersion ) )
return false;
// TODO - retire legacy format version reading
if ( nFormatVersion == 0 ) // legacy formats store format version in their format name string
{
Warning( "reading file '%s' of legacy format '%s' - dmxconvert this file to a newer format!\n", pFileName ? pFileName : "<no file>", pFormatName );
}
// Only allow binary protocol files
bool bIsBinary = ( buf.GetFlags() & CUtlBuffer::TEXT_BUFFER ) == 0;
if ( bIsBinary )
{
CDmxSerializer dmxUnserializer;
return dmxUnserializer.Unserialize( buf, nEncodingVersion, ppRoot );
}
return UnserializeTextDMX( pFileName ? pFileName : "<no file>", buf, ppRoot );
}
bool UnserializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement **ppRoot )
{
// NOTE: This guarantees full path names for pathids
char pBuf[MAX_PATH];
const char *pFullPath = pFileName;
if ( !Q_IsAbsolutePath( pFullPath ) && !pPathID )
{
char pDir[MAX_PATH];
if ( g_pFullFileSystem->GetCurrentDirectory( pDir, sizeof(pDir) ) )
{
Q_ComposeFileName( pDir, pFileName, pBuf, sizeof(pBuf) );
Q_RemoveDotSlashes( pBuf );
pFullPath = pBuf;
}
}
int nFlags = CUtlBuffer::READ_ONLY;
if ( bTextMode )
{
nFlags |= CUtlBuffer::TEXT_BUFFER;
}
CUtlBuffer buf( 0, 0, nFlags );
g_pFullFileSystem->ReadFile( pFullPath, pPathID, buf );
if ( !buf.IsValid() )
{
Warning( "UnserializeDMX: Unable to open file \"%s\"\n", pFullPath );
return false;
}
return UnserializeDMX( buf, ppRoot, pFullPath );
}
//-----------------------------------------------------------------------------
// Cleans up read-in elements
//-----------------------------------------------------------------------------
void CleanupDMX( CDmxElement *pRoot )
{
if ( pRoot )
{
pRoot->RemoveAllElementsRecursive();
}
}

41
dmxloader/dmxloader.vpc Normal file
View File

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// DMXLOADER.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$Include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$PreprocessorDefinitions "$BASE;DMXLOADER_LIB"
}
}
$Project "Dmxloader"
{
$Folder "Source Files"
{
$File "dmxattribute.cpp"
$File "dmxelement.cpp"
$File "dmxloader.cpp"
$File "dmxloadertext.cpp"
$File "dmxserializationdictionary.cpp"
}
$Folder "Header Files"
{
$File "dmxserializationdictionary.h"
}
$Folder "Interface"
{
$File "$SRCDIR\public\dmxloader\dmxattribute.h"
$File "$SRCDIR\public\dmxloader\dmxelement.h"
$File "$SRCDIR\public\dmxloader\dmxloader.h"
}
}

1442
dmxloader/dmxloadertext.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "dmxserializationdictionary.h"
#include "dmxloader/dmxelement.h"
#include "dmxloader/dmxattribute.h"
//-----------------------------------------------------------------------------
//
// Element dictionary used in serialization
//
//-----------------------------------------------------------------------------
CDmxSerializationDictionary::CDmxSerializationDictionary( int nElementsHint /* = 0 */ ) :
m_Dict( 0, nElementsHint, CDmxSerializationDictionary::LessFunc )
{
}
//-----------------------------------------------------------------------------
// Used to sort the list of elements
//-----------------------------------------------------------------------------
bool CDmxSerializationDictionary::LessFunc( const DmxElementInfo_t &lhs, const DmxElementInfo_t &rhs )
{
return lhs.m_pElement < rhs.m_pElement;
}
//-----------------------------------------------------------------------------
// Finds the handle of the element
//-----------------------------------------------------------------------------
DmxSerializationHandle_t CDmxSerializationDictionary::Find( CDmxElement *pElement )
{
DmxElementInfo_t find;
find.m_pElement = pElement;
return m_Dict.Find( find );
}
//-----------------------------------------------------------------------------
// Creates the list of all things to serialize
//-----------------------------------------------------------------------------
void CDmxSerializationDictionary::BuildElementList_R( CDmxElement *pElement, bool bFlatMode, bool bIsRoot )
{
if ( !pElement )
return;
// FIXME: Right here we should ask the element if it's an external
// file reference and exit immediately if so.
// This means we've already encountered this guy.
// Therefore, he can never be a root element
DmxSerializationHandle_t h = Find( pElement );
if ( h != m_Dict.InvalidIndex() )
{
m_Dict[h].m_bRoot = true;
return;
}
DmxElementInfo_t info;
info.m_bRoot = bFlatMode || bIsRoot;
info.m_pElement = pElement;
m_Dict.Insert( info );
int nCount = pElement->AttributeCount();
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pAttribute = pElement->GetAttribute(i);
switch( pAttribute->GetType() )
{
case AT_ELEMENT:
{
CDmxElement *pChild = pAttribute->GetValue<CDmxElement*>();
if ( !pChild )
break;
BuildElementList_R( pChild, bFlatMode, false );
}
break;
case AT_ELEMENT_ARRAY:
{
const CUtlVector<CDmxElement*> &array = pAttribute->GetArray<CDmxElement*>( );
int nCountArray = array.Count();
for ( int j = 0; j < nCountArray; ++j )
{
CDmxElement *pChild = array[ j ];
if ( !pChild )
break;
BuildElementList_R( pChild, bFlatMode, false );
}
}
break;
}
}
}
void CDmxSerializationDictionary::BuildElementList( CDmxElement *pElement, bool bFlatMode )
{
BuildElementList_R( pElement, bFlatMode, true );
}
//-----------------------------------------------------------------------------
// Should I inline the serialization of this element?
//-----------------------------------------------------------------------------
bool CDmxSerializationDictionary::ShouldInlineElement( CDmxElement *pElement )
{
// This means we've already encountered this guy.
// Therefore, he can never be a root element
DmxSerializationHandle_t h = Find( pElement );
if ( h != m_Dict.InvalidIndex() )
return !m_Dict[h].m_bRoot;
// If we didn't find the element, it means it's a reference to an external
// element (or it's NULL), so don't inline ie.
return false;
}
//-----------------------------------------------------------------------------
// Clears the dictionary
//-----------------------------------------------------------------------------
void CDmxSerializationDictionary::Clear()
{
m_Dict.RemoveAll();
}
//-----------------------------------------------------------------------------
// How many root elements do we have?
//-----------------------------------------------------------------------------
int CDmxSerializationDictionary::RootElementCount() const
{
int nCount = 0;
DmxSerializationHandle_t h = m_Dict.FirstInorder();
while( h != m_Dict.InvalidIndex() )
{
if ( m_Dict[h].m_bRoot )
{
++nCount;
}
h = m_Dict.NextInorder( h );
}
return nCount;
}
//-----------------------------------------------------------------------------
// Iterates over all root elements to serialize
//-----------------------------------------------------------------------------
DmxSerializationHandle_t CDmxSerializationDictionary::FirstRootElement() const
{
// NOTE: I don't have to use First/NextInorder here because there
// are guaranteed to be no removals from the dictionary.
// Also, using inorder traversal won't get my actual root element to be first in the file
int nCount = m_Dict.Count();
for ( DmxSerializationHandle_t h = 0; h < nCount; ++h )
{
if ( m_Dict[h].m_bRoot )
return h;
}
return DMX_SERIALIZATION_HANDLE_INVALID;
}
DmxSerializationHandle_t CDmxSerializationDictionary::NextRootElement( DmxSerializationHandle_t h ) const
{
++h;
int nCount = m_Dict.Count();
for ( ; h < nCount; ++h )
{
if ( m_Dict[h].m_bRoot )
return h;
}
return DMX_SERIALIZATION_HANDLE_INVALID;
}
CDmxElement *CDmxSerializationDictionary::GetRootElement( DmxSerializationHandle_t h )
{
Assert( m_Dict[h].m_bRoot );
return m_Dict[h].m_pElement;
}

View File

@ -0,0 +1,76 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMXSERIALIZATIONDICTIONARY_H
#define DMXSERIALIZATIONDICTIONARY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlrbtree.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CDmxElement;
//-----------------------------------------------------------------------------
// Element dictionary used in unserialization
//-----------------------------------------------------------------------------
typedef int DmxSerializationHandle_t;
enum
{
DMX_SERIALIZATION_HANDLE_INVALID = (DmxSerializationHandle_t)~0
};
//-----------------------------------------------------------------------------
// Element dictionary used in serialization
//-----------------------------------------------------------------------------
class CDmxSerializationDictionary
{
public:
CDmxSerializationDictionary( int nElementsHint = 0 );
// Creates the list of all things to serialize
void BuildElementList( CDmxElement *pRoot, bool bFlatMode );
// Should I inline the serialization of this element?
bool ShouldInlineElement( CDmxElement *pElement );
// Clears the dictionary
void Clear();
// Iterates over all root elements to serialize
DmxSerializationHandle_t FirstRootElement() const;
DmxSerializationHandle_t NextRootElement( DmxSerializationHandle_t h ) const;
CDmxElement* GetRootElement( DmxSerializationHandle_t h );
// Finds the handle of the element
DmxSerializationHandle_t Find( CDmxElement *pElement );
// How many root elements do we have?
int RootElementCount() const;
private:
struct DmxElementInfo_t
{
CDmxElement* m_pElement;
bool m_bRoot;
};
// Creates the list of all things to serialize
void BuildElementList_R( CDmxElement *pRoot, bool bFlatMode, bool bIsRoot );
static bool LessFunc( const DmxElementInfo_t &lhs, const DmxElementInfo_t &rhs );
CUtlRBTree< DmxElementInfo_t, DmxSerializationHandle_t > m_Dict;
};
#endif // DMXSERIALIZATIONDICTIONARY_H