initial
This commit is contained in:
46
dmxloader/_vpc_/manifest_dmxloader/win32/manifest.txt
Normal file
46
dmxloader/_vpc_/manifest_dmxloader/win32/manifest.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
// ----------------------------------------- //
|
||||
// File generated by VPC //
|
||||
// ----------------------------------------- //
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\dmxattribute.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\dmxattribute.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\dmxattribute.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\dmxelement.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\dmxelement.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\dmxelement.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\dmxloader.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\dmxloader.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\dmxloader.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\dmxloadertext.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\dmxloadertext.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\dmxloadertext.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\dmxserializationdictionary.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\dmxserializationdictionary.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\dmxserializationdictionary.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: F:\csgo_64\cstrike15_src\dmxloader\utlsoacontainer_serialization.cpp
|
||||
Debug output file: F:\csgo_64\cstrike15_src\dmxloader\utlsoacontainer_serialization.cpp
|
||||
Release output file: F:\csgo_64\cstrike15_src\dmxloader\utlsoacontainer_serialization.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
666
dmxloader/dmxattribute.cpp
Normal file
666
dmxloader/dmxattribute.cpp
Normal file
@@ -0,0 +1,666 @@
|
||||
//====== Copyright © 1996-2004, 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
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlSymbolTableLargeMT 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(DmeTime_t), // AT_TIME,
|
||||
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<DmeTime_t>), // AT_TIME_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( DmeTime_t ) == 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 );
|
||||
#if !defined( PLATFORM_64BITS )
|
||||
COMPILE_TIME_ASSERT( sizeof( CUtlString ) == 16 );
|
||||
COMPILE_TIME_ASSERT( sizeof( CUtlBinaryBlock ) == 16 );
|
||||
#endif
|
||||
};
|
||||
};
|
||||
static CSizeTest g_sizeTest;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns attribute name for type
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CDmxAttribute::s_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<DmeTime_t>::AttributeTypeName(), // AT_TIME,
|
||||
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< DmeTime_t > >::AttributeTypeName(), // AT_TIME_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( CUtlSymbolLarge 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];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the basic type for a given array attribute type
|
||||
//-----------------------------------------------------------------------------
|
||||
DmAttributeType_t CDmxAttribute::ArrayAttributeBasicType( DmAttributeType_t type )
|
||||
{
|
||||
COMPILE_TIME_ASSERT( ( AT_FIRST_ARRAY_TYPE - AT_FIRST_VALUE_TYPE ) == ( AT_TYPE_COUNT - AT_FIRST_ARRAY_TYPE ) );
|
||||
if ( IsArrayType( type ) )
|
||||
type = (DmAttributeType_t)( type - ( AT_FIRST_ARRAY_TYPE - AT_FIRST_VALUE_TYPE ) ); // Array -> array element
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros to tersify operations on attribute data of any type
|
||||
//-----------------------------------------------------------------------------
|
||||
#define NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
case AT_INT: _func_< int , int >_params_; break; \
|
||||
case AT_FLOAT: _func_< float , float >_params_; break; \
|
||||
case AT_BOOL: _func_< bool , bool >_params_; break; \
|
||||
case AT_STRING: _func_< CUtlString , CUtlString >_params_; break; \
|
||||
case AT_VOID: _func_< CUtlBinaryBlock , CUtlBinaryBlock >_params_; break; \
|
||||
case AT_TIME: _func_< DmeTime_t , DmeTime_t >_params_; break; \
|
||||
case AT_COLOR: _func_< Color , Color >_params_; break; \
|
||||
case AT_VECTOR2: _func_< Vector2D , Vector2D >_params_; break; \
|
||||
case AT_VECTOR3: _func_< Vector , Vector >_params_; break; \
|
||||
case AT_VECTOR4: _func_< Vector4D , Vector4D >_params_; break; \
|
||||
case AT_QANGLE: _func_< QAngle , QAngle >_params_; break; \
|
||||
case AT_QUATERNION: _func_< Quaternion , Quaternion >_params_; break; \
|
||||
case AT_VMATRIX: _func_< VMatrix , VMatrix >_params_; break;
|
||||
|
||||
#define ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
case AT_INT_ARRAY: _func_< CUtlVector<int >, int >_params_; break; \
|
||||
case AT_FLOAT_ARRAY: _func_< CUtlVector<float >, float >_params_; break; \
|
||||
case AT_BOOL_ARRAY: _func_< CUtlVector<bool >, bool >_params_; break; \
|
||||
case AT_STRING_ARRAY: _func_< CUtlVector<CUtlString >, CUtlString >_params_; break; \
|
||||
case AT_VOID_ARRAY: _func_< CUtlVector<CUtlBinaryBlock >, CUtlBinaryBlock >_params_; break; \
|
||||
case AT_TIME_ARRAY: _func_< CUtlVector<DmeTime_t >, DmeTime_t >_params_; break; \
|
||||
case AT_COLOR_ARRAY: _func_< CUtlVector<Color >, Color >_params_; break; \
|
||||
case AT_VECTOR2_ARRAY: _func_< CUtlVector<Vector2D >, Vector2D >_params_; break; \
|
||||
case AT_VECTOR3_ARRAY: _func_< CUtlVector<Vector >, Vector >_params_; break; \
|
||||
case AT_VECTOR4_ARRAY: _func_< CUtlVector<Vector4D >, Vector4D >_params_; break; \
|
||||
case AT_QANGLE_ARRAY: _func_< CUtlVector<QAngle >, QAngle >_params_; break; \
|
||||
case AT_QUATERNION_ARRAY: _func_< CUtlVector<Quaternion >, Quaternion >_params_; break; \
|
||||
case AT_VMATRIX_ARRAY: _func_< CUtlVector<VMatrix >, VMatrix >_params_; break;
|
||||
|
||||
#define NON_ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
|
||||
case AT_ELEMENT: _func_< CDmxElement* , CDmxElement* >_params_; break;
|
||||
|
||||
#define ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
|
||||
case AT_ELEMENT_ARRAY: _func_< CUtlVector<CDmxElement* >, CDmxElement* >_params_; break;
|
||||
|
||||
#define CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( _func_, _params_, _errCase_ ) \
|
||||
switch( m_Type ) \
|
||||
{ \
|
||||
ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
default: _errCase_; \
|
||||
}
|
||||
|
||||
#define CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( _func_, _params_, _errCase_ ) \
|
||||
switch( m_Type ) \
|
||||
{ \
|
||||
ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
|
||||
default: _errCase_; \
|
||||
}
|
||||
|
||||
#define CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( _func_, _params_, _errCase_ ) \
|
||||
switch( m_Type ) \
|
||||
{ \
|
||||
NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
default: _errCase_; \
|
||||
}
|
||||
|
||||
#define CALL_TYPE_TEMPLATIZED_FUNCTION( _func_, _params_, _errCase_ ) \
|
||||
switch( m_Type ) \
|
||||
{ \
|
||||
NON_ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
NON_ARRAY_ELEMENT_CASE(_func_, _params_, _errCase_ ) \
|
||||
ARRAY_TYPE_CASES( _func_, _params_, _errCase_ ) \
|
||||
ARRAY_ELEMENT_CASE( _func_, _params_, _errCase_ ) \
|
||||
default: _errCase_; \
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allocate, free memory for data
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDmxAttribute::AllocateDataMemory( DmAttributeType_t type )
|
||||
{
|
||||
FreeDataMemory();
|
||||
|
||||
m_Type = type;
|
||||
m_pData = DMXAlloc( s_pAttributeSize[m_Type] );
|
||||
}
|
||||
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::ConstructDataMemory( void )
|
||||
{
|
||||
Construct( (VT *)m_pData );
|
||||
}
|
||||
void CDmxAttribute::AllocateDataMemory_AndConstruct( DmAttributeType_t type )
|
||||
{
|
||||
AllocateDataMemory( type );
|
||||
Assert( m_pData != NULL );
|
||||
|
||||
// Process array and non-array types, including elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION( ConstructDataMemory, (), );
|
||||
}
|
||||
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::DestructDataMemory( void )
|
||||
{
|
||||
Destruct( (VT *)m_pData );
|
||||
}
|
||||
void CDmxAttribute::FreeDataMemory()
|
||||
{
|
||||
if ( m_Type != AT_UNKNOWN )
|
||||
{
|
||||
Assert( m_pData != NULL );
|
||||
// Process array and non-array types, including elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION( DestructDataMemory, (), );
|
||||
m_Type = AT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns attribute type string
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const char* CDmxAttribute::GetTypeString() const
|
||||
{
|
||||
return s_pAttributeTypeName[ m_Type ];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns attribute name
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CDmxAttribute::GetName() const
|
||||
{
|
||||
return m_Name.String();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the size of an array, returns 0 if it's not an array type
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::GetArrayCount( int &nCount ) const
|
||||
{
|
||||
nCount = ((VT *)m_pData)->Count();
|
||||
}
|
||||
int CDmxAttribute::GetArrayCount() const
|
||||
{
|
||||
int nCount = 0;
|
||||
// Process array types only, including elements
|
||||
if ( IsArrayType( m_Type ) && m_pData )
|
||||
CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( GetArrayCount, (nCount), );
|
||||
return nCount;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the size of an array, non-destructively
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::SetArrayCount( int nArrayCount )
|
||||
{
|
||||
((VT *)m_pData)->SetCountNonDestructively( nArrayCount );
|
||||
}
|
||||
void CDmxAttribute::SetArrayCount( int nArrayCount )
|
||||
{
|
||||
// Process array types only, including elements
|
||||
CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( SetArrayCount, (nArrayCount), Assert(0) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the base data pointer of an array
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::GetArrayBase( const void * &pBasePtr ) const
|
||||
{
|
||||
pBasePtr = ((VT *)m_pData)->Base();
|
||||
}
|
||||
const void *CDmxAttribute::GetArrayBase( void ) const
|
||||
{
|
||||
const void *pBasePtr = NULL;
|
||||
// Process array types only, including elements
|
||||
CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION( GetArrayBase, (pBasePtr), Assert(0) );
|
||||
return pBasePtr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets whether a given data type serializes to multiple lines
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::SerializesOnMultipleLines( bool &bResult ) const
|
||||
{
|
||||
bResult = ::SerializesOnMultipleLines<VT>();
|
||||
}
|
||||
bool CDmxAttribute::SerializesOnMultipleLines() const
|
||||
{
|
||||
bool bResult = false;
|
||||
// Process array and non-array types, including elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION( SerializesOnMultipleLines, (bResult), );
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Write to file
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::SerializeType( bool &bSuccess, CUtlBuffer &buf ) const
|
||||
{
|
||||
if ( m_pData )
|
||||
{
|
||||
bSuccess = ::Serialize( buf, *(VT *)m_pData );
|
||||
}
|
||||
else
|
||||
{
|
||||
VT temp;
|
||||
CDmAttributeInfo< VT >::SetDefaultValue( temp );
|
||||
bSuccess = ::Serialize( buf, temp );
|
||||
}
|
||||
}
|
||||
|
||||
bool CDmxAttribute::Serialize( CUtlBuffer &buf ) const
|
||||
{
|
||||
bool bSuccess = false;
|
||||
// Process array and non-array types, excluding elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( SerializeType, (bSuccess, buf), AssertMsg( 0, "Cannot serialize elements or element arrays!\n" ) );
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Serialize a single element in an array attribute
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::SerializeTypedElement( bool &bSuccess, int nIndex, CUtlBuffer &buf ) const
|
||||
{
|
||||
if ( m_pData )
|
||||
{
|
||||
const VT &array = *(VT *)m_pData;
|
||||
bSuccess = ::Serialize( buf, array[nIndex] );
|
||||
}
|
||||
else
|
||||
{
|
||||
T temp;
|
||||
CDmAttributeInfo<T>::SetDefaultValue( temp );
|
||||
bSuccess = ::Serialize( buf, temp );
|
||||
}
|
||||
}
|
||||
bool CDmxAttribute::SerializeElement( int nIndex, CUtlBuffer &buf ) const
|
||||
{
|
||||
if ( !IsArrayType( m_Type ) )
|
||||
return false;
|
||||
|
||||
bool bSuccess = false;
|
||||
// Process array types only, excluding elements
|
||||
CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( SerializeTypedElement, (bSuccess, nIndex, buf), AssertMsg( 0, "Cannot serialize elements!\n" ); );
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read from file
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::UnserializeType( bool &bSuccess, CUtlBuffer &buf )
|
||||
{
|
||||
bSuccess = ::Unserialize( buf, *(VT *)m_pData );
|
||||
}
|
||||
bool CDmxAttribute::Unserialize( DmAttributeType_t type, CUtlBuffer &buf )
|
||||
{
|
||||
AllocateDataMemory_AndConstruct( type );
|
||||
|
||||
bool bSuccess = false;
|
||||
// Process array and non-array types, excluding elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( UnserializeType, (bSuccess, buf), AssertMsg( 0, "Cannot unserialize elements or element arrays!\n" ); );
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read element from file
|
||||
//-----------------------------------------------------------------------------
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::UnserializeTypedElement( bool &bSuccess, CUtlBuffer &buf )
|
||||
{
|
||||
T temp;
|
||||
bSuccess = ::Unserialize( buf, temp );
|
||||
if ( bSuccess )
|
||||
((VT *)m_pData)->AddToTail( temp );
|
||||
}
|
||||
bool CDmxAttribute::UnserializeElement( DmAttributeType_t type, CUtlBuffer &buf )
|
||||
{
|
||||
if ( !IsArrayType( type ) )
|
||||
return false;
|
||||
|
||||
if ( m_Type != type )
|
||||
AllocateDataMemory_AndConstruct( type );
|
||||
|
||||
bool bSuccess = false;
|
||||
// Process array types only, excluding elements
|
||||
CALL_ARRAY_TYPE_TEMPLATIZED_FUNCTION_NOELEMENTS( UnserializeTypedElement, (bSuccess, buf), AssertMsg( 0, "Cannot unserialize elements!\n" ) );
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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( char *pString )
|
||||
{
|
||||
SetValue( (const char*)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 );
|
||||
}
|
||||
if ( nLen > CDmxAttribute::AttributeDataSize( type ) )
|
||||
{
|
||||
nLen = CDmxAttribute::AttributeDataSize( type );
|
||||
}
|
||||
memcpy( m_pData, pSrc, nLen );
|
||||
}
|
||||
|
||||
// Untyped method for setting arrays, used by unpack
|
||||
void CDmxAttribute::SetArrayValue( DmAttributeType_t type, const void *pSrc, int nDataTypeSize, int nArrayLength, int nSrcStride )
|
||||
{
|
||||
if ( !IsArrayType( type ) )
|
||||
return;
|
||||
|
||||
if ( m_Type != type )
|
||||
{
|
||||
AllocateDataMemory( type );
|
||||
}
|
||||
|
||||
// NOTE: nDestStride will be 4 for char/short/int values, and the below code is designed to work in all those cases
|
||||
DmAttributeType_t basicType = ArrayAttributeBasicType( type );
|
||||
int nDestStride = CDmxAttribute::AttributeDataSize( basicType );
|
||||
Assert( nDataTypeSize <= nDestStride );
|
||||
nDataTypeSize = MIN( nDataTypeSize, nDestStride );
|
||||
|
||||
SetArrayCount( nArrayLength );
|
||||
void *pDest = (void *)GetArrayBase();
|
||||
if ( !pDest )
|
||||
return;
|
||||
if ( nDataTypeSize != nDestStride )
|
||||
{
|
||||
// Avoid writing junk, keep the data clean in case we inspect the memory or a serialized file:
|
||||
Q_memset( pDest, 0, nDestStride*nArrayLength );
|
||||
}
|
||||
if ( ( nSrcStride == nDestStride ) && ( nDataTypeSize == nSrcStride ) )
|
||||
{
|
||||
memcpy( pDest, pSrc, nDestStride*nArrayLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
byte *pByteDest = (byte *)pDest;
|
||||
const byte *pByteSrc = (const byte *)pSrc;
|
||||
for ( int i = 0; i < nArrayLength; i++ )
|
||||
{
|
||||
memcpy( pByteDest, pByteSrc, nDataTypeSize );
|
||||
pByteDest += nDestStride;
|
||||
pByteSrc += nSrcStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDmxAttribute::GetArrayValue( DmAttributeType_t type, void *pDest, int nDataTypeSize, int nDestArrayLength, const char *pDefaultString ) const
|
||||
{
|
||||
if ( !IsArrayType( type ) || ( m_Type != type ) )
|
||||
return;
|
||||
|
||||
// NOTE: nDestStride will be 4 for char/short/int values, and the below code is designed to work in all those cases
|
||||
DmAttributeType_t basicType = ArrayAttributeBasicType( type );
|
||||
int nSrcStride = CDmxAttribute::AttributeDataSize( basicType );
|
||||
Assert( nDataTypeSize <= nSrcStride );
|
||||
nDataTypeSize = MIN( nDataTypeSize, nSrcStride );
|
||||
|
||||
int nSrcArrayLength = GetArrayCount();
|
||||
const void *pSrc = GetArrayBase();
|
||||
if ( nSrcArrayLength && pSrc )
|
||||
{
|
||||
if ( nSrcStride == nDataTypeSize )
|
||||
{
|
||||
memcpy( pDest, pSrc, nSrcArrayLength*nDataTypeSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
byte *pByteDst = (byte *)pDest;
|
||||
const byte *pByteSrc = (const byte *)pSrc;
|
||||
for ( int i = 0; i < nSrcArrayLength; i++ )
|
||||
{
|
||||
memcpy( pByteDst, pByteSrc, nDataTypeSize );
|
||||
pByteDst += nDataTypeSize;
|
||||
pByteSrc += nSrcStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ( nSrcArrayLength < nDestArrayLength ) && pDefaultString )
|
||||
{
|
||||
CDmxAttribute temp( NULL );
|
||||
temp.AllocateDataMemory_AndConstruct( basicType );
|
||||
temp.SetValueFromString( pDefaultString );
|
||||
|
||||
byte *pByteDst = ( (byte *)pDest ) + nSrcArrayLength*nDataTypeSize;
|
||||
for ( int i = nSrcArrayLength; i < nDestArrayLength; i++ )
|
||||
{
|
||||
memcpy( pByteDst, temp.m_pData, nDataTypeSize );
|
||||
pByteDst += nDataTypeSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
template < class VT, class T >
|
||||
void CDmxAttribute::SetDefaultValue( void )
|
||||
{
|
||||
CDmAttributeInfo< VT >::SetDefaultValue( *(VT *)( m_pData ) );
|
||||
}
|
||||
void CDmxAttribute::SetToDefaultValue()
|
||||
{
|
||||
// Process array and non-array types, including elements
|
||||
CALL_TYPE_TEMPLATIZED_FUNCTION( SetDefaultValue, (), );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
703
dmxloader/dmxelement.cpp
Normal file
703
dmxloader/dmxelement.cpp
Normal file
@@ -0,0 +1,703 @@
|
||||
//====== Copyright 1996-2004, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "dmxloader/dmxelement.h"
|
||||
#include "dmxloader/dmxattribute.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "mathlib/ssemath.h"
|
||||
#include "tier1/utlbufferutil.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef OSX
|
||||
#pragma GCC diagnostic ignored "-Wtautological-compare"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// globals
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlSymbolTableLargeMT 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
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlSymbolLarge CDmxElement::GetType() const
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
|
||||
const char* CDmxElement::GetTypeString() const
|
||||
{
|
||||
return m_Type.String();
|
||||
}
|
||||
|
||||
const char* CDmxElement::GetName() const
|
||||
{
|
||||
return GetValue< CUtlString >( "name" );
|
||||
}
|
||||
|
||||
const DmObjectId_t &CDmxElement::GetId() const
|
||||
{
|
||||
return m_Id;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the object id, name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDmxElement::SetId( const DmObjectId_t &id )
|
||||
{
|
||||
CopyUniqueId( id, &m_Id );
|
||||
}
|
||||
|
||||
void CDmxElement::SetName( const char *pName )
|
||||
{
|
||||
SetValue< CUtlString >( "name", pName );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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] == NULL || m_Attributes[i-1] == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
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( CUtlSymbolLarge 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];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Template for unpacking a bitfield inside of an unpack structure.
|
||||
// pUnpack->m_nSize is the number of bits in the bitfield
|
||||
// pUnpack->m_nBitOffset is the number of bits to offset from pDest
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void CDmxElement::UnpackBitfield( T *pDest, const DmxElementUnpackStructure_t *pUnpack, const CDmxAttribute *pAttribute ) const
|
||||
{
|
||||
// Determine if T is a signed type
|
||||
const bool bIsSigned = ( 0 > (T)(-1) );
|
||||
if ( bIsSigned )
|
||||
{
|
||||
// signed types need to be larger than 1 in size or else you get sign extension problems
|
||||
Assert( pUnpack->m_nSize > 1 );
|
||||
}
|
||||
|
||||
// Right now the max size bitfield we handle is 32.
|
||||
Assert( pUnpack->m_nSize <= 32 );
|
||||
Assert( pUnpack->m_nSize <= 8*sizeof(T) );
|
||||
Assert( pUnpack->m_nBitOffset + pUnpack->m_nSize <= 8*sizeof(T) );
|
||||
|
||||
// Create a mask that covers the bitfield.
|
||||
T mask;
|
||||
T maskBeforeShift;
|
||||
if ( pUnpack->m_nSize == 8*sizeof(T) )
|
||||
{
|
||||
maskBeforeShift = (T)~0;
|
||||
mask = maskBeforeShift;
|
||||
}
|
||||
else
|
||||
{
|
||||
maskBeforeShift = ( 1 << pUnpack->m_nSize ) - 1;
|
||||
mask = maskBeforeShift << pUnpack->m_nBitOffset;
|
||||
}
|
||||
mask = ~mask;
|
||||
|
||||
T value = ( *(T *)pAttribute->m_pData );
|
||||
|
||||
// Determine if value is in the range that this variable can hold.
|
||||
T signedMaskBeforeShift = bIsSigned ? ( 1 << (pUnpack->m_nSize-1) ) - 1 : maskBeforeShift;
|
||||
if ( !bIsSigned || ( value >= 0 ) )
|
||||
{
|
||||
if ( ( value & ~signedMaskBeforeShift ) != 0 )
|
||||
{
|
||||
Warning( "Value %s exeeds size of datatype. \n", pUnpack->m_pAttributeName );
|
||||
value = 0; // Clear value
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !bIsSigned || ( ( value & ~signedMaskBeforeShift ) != ~signedMaskBeforeShift ) )
|
||||
{
|
||||
Warning( "Value %s exeeds size of datatype. \n", pUnpack->m_pAttributeName );
|
||||
value = 0; // Clear value
|
||||
}
|
||||
}
|
||||
|
||||
// Mask value to the correct number of bits (important if value is a neg number!)
|
||||
value &= maskBeforeShift;
|
||||
|
||||
// Pack it together.
|
||||
// Clear value
|
||||
*pDest &= mask;
|
||||
// Install value
|
||||
*pDest |= ( value << pUnpack->m_nBitOffset );
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Method to unpack data into a structure
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDmxElement::UnpackIntoStructure( void *pData, const DmxElementUnpackStructure_t *pUnpack ) const
|
||||
{
|
||||
for ( ; pUnpack->m_AttributeType != AT_UNKNOWN; ++pUnpack )
|
||||
{
|
||||
char *pDest = (char*)pData + pUnpack->m_nOffset;
|
||||
|
||||
// Recurse?
|
||||
if ( pUnpack->m_pSub )
|
||||
{
|
||||
UnpackIntoStructure( (void *)pDest, pUnpack->m_pSub );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// NOTE: This does not work with string/bitfield array data at the moment
|
||||
if ( ( pUnpack->m_AttributeType == AT_STRING_ARRAY ) || ( pUnpack->m_nBitOffset != NO_BIT_OFFSET ) )
|
||||
{
|
||||
AssertMsg( 0, ( "CDmxElement::UnpackIntoStructure: String and bitfield array attribute types not currently supported!\n" ) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( pUnpack->m_AttributeType == AT_VOID ) || ( pUnpack->m_AttributeType == AT_VOID_ARRAY ) )
|
||||
{
|
||||
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;
|
||||
|
||||
temp.AllocateDataMemory_AndConstruct( pUnpack->m_AttributeType );
|
||||
if ( !IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// Convert the default string into the target (array types do this inside GetArrayValue below)
|
||||
temp.SetValueFromString( pUnpack->m_pDefaultString );
|
||||
}
|
||||
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 ( pUnpack->m_nSize == UTL_STRING_SIZE ) // the string is a UtlString.
|
||||
{
|
||||
*(CUtlString *)pDest = pAttribute->GetValueString();
|
||||
}
|
||||
else // the string is a preallocated char array.
|
||||
{
|
||||
// Strings get special treatment: they are stored as in-line arrays of chars
|
||||
Q_strncpy( pDest, pAttribute->GetValueString(), pUnpack->m_nSize );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the basic type, if the attribute is an array:
|
||||
DmAttributeType_t basicType = CDmxAttribute::ArrayAttributeBasicType( pAttribute->GetType() );
|
||||
|
||||
// Special case - if data type is float, but dest size == 16, we are unpacking into simd by replication
|
||||
if ( ( basicType == AT_FLOAT ) && ( pUnpack->m_nSize == sizeof( fltx4 ) ) )
|
||||
{
|
||||
if ( IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// Copy from the attribute into a fixed-size array:
|
||||
float *pfDest = (float *)pDest;
|
||||
const CUtlVector< float > &floatVector = pAttribute->GetArray< float >();
|
||||
for ( int i = 0; i < pUnpack->m_nArrayLength; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 4; j++ ) memcpy( pfDest++, &floatVector[ i ], sizeof( float ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
{
|
||||
int nDataTypeSize = pUnpack->m_nSize;
|
||||
if ( basicType == AT_INT )
|
||||
{
|
||||
if ( pUnpack->m_nBitOffset == NO_BIT_OFFSET ) // This test is not for bitfields
|
||||
{
|
||||
AssertMsg( nDataTypeSize <= CDmxAttribute::AttributeDataSize( basicType ),
|
||||
( "CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into in attribute \"%s\"!\n", pUnpack->m_pAttributeName ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertMsg( nDataTypeSize == CDmxAttribute::AttributeDataSize( basicType ),
|
||||
( "CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into in attribute \"%s\"!\n", pUnpack->m_pAttributeName ) );
|
||||
}
|
||||
|
||||
if ( IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// Copy from the attribute into a fixed-size array (padding with the default value if need be):
|
||||
pAttribute->GetArrayValue( pUnpack->m_AttributeType, pDest, nDataTypeSize, pUnpack->m_nArrayLength, pUnpack->m_pDefaultString );
|
||||
}
|
||||
else if ( pUnpack->m_nBitOffset == NO_BIT_OFFSET )
|
||||
{
|
||||
memcpy( pDest, pAttribute->m_pData, pUnpack->m_nSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pAttribute->GetType() == AT_INT )
|
||||
{
|
||||
// Int attribute types are used for char/short/int.
|
||||
switch ( pUnpack->m_BitfieldType )
|
||||
{
|
||||
case BITFIELD_TYPE_BOOL:
|
||||
// Note: unsigned char handles bools as bitfields.
|
||||
UnpackBitfield( (unsigned char *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_CHAR :
|
||||
UnpackBitfield( (char *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_UNSIGNED_CHAR :
|
||||
UnpackBitfield( (unsigned char *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_SHORT :
|
||||
UnpackBitfield( (short *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_UNSIGNED_SHORT :
|
||||
UnpackBitfield( (unsigned short *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_INT :
|
||||
UnpackBitfield( (int *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
case BITFIELD_TYPE_UNSIGNED_INT :
|
||||
UnpackBitfield( (unsigned int *)pDest, pUnpack, pAttribute );
|
||||
break;
|
||||
default:
|
||||
Assert(0);
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
UnpackBitfield( (char *)pDest, pUnpack, pAttribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates attributes based on the unpack structure
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDmxElement::AddAttributesFromStructure( const void *pData, const DmxElementUnpackStructure_t *pUnpack )
|
||||
{
|
||||
for ( ; pUnpack->m_AttributeType != AT_UNKNOWN; ++pUnpack )
|
||||
{
|
||||
const char *pSrc = (const char*)pData + pUnpack->m_nOffset;
|
||||
if ( pUnpack->m_pSub )
|
||||
{
|
||||
CDmxElement *pDest = CreateDmxElement( pUnpack->m_pTypeName );
|
||||
pDest->AddAttributesFromStructure( pSrc, pUnpack->m_pSub );
|
||||
SetValue( pUnpack->m_pAttributeName, pDest );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// NOTE: This does not work with string/bitfield array data at the moment
|
||||
if ( ( pUnpack->m_AttributeType == AT_STRING_ARRAY ) || ( pUnpack->m_nBitOffset != NO_BIT_OFFSET ) )
|
||||
{
|
||||
AssertMsg( 0, ( "CDmxElement::AddAttributesFromStructure: String and bitfield array attribute types not currently supported!\n" ) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( pUnpack->m_AttributeType == AT_VOID ) || ( pUnpack->m_AttributeType == AT_VOID_ARRAY ) )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
CDmxElementModifyScope modify( this );
|
||||
CDmxAttribute *pAttribute = AddAttribute( pUnpack->m_pAttributeName );
|
||||
if ( pUnpack->m_AttributeType == AT_STRING )
|
||||
{
|
||||
if ( pUnpack->m_nSize == UTL_STRING_SIZE ) // it is a UtlString.
|
||||
{
|
||||
const char *test = (*(CUtlString *)pSrc).Get();
|
||||
pAttribute->SetValue( test );
|
||||
}
|
||||
else
|
||||
{
|
||||
pAttribute->SetValue( pSrc );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the basic data type, if the attribute is an array:
|
||||
DmAttributeType_t basicType = CDmxAttribute::ArrayAttributeBasicType( pUnpack->m_AttributeType );
|
||||
int nDataTypeSize = pUnpack->m_nSize;
|
||||
|
||||
// handle float attrs stored as replicated fltx4's
|
||||
if ( ( basicType == AT_FLOAT ) && ( nDataTypeSize == sizeof( fltx4 ) ) )
|
||||
{
|
||||
nDataTypeSize = sizeof( float );
|
||||
}
|
||||
|
||||
if ( basicType == AT_INT )
|
||||
{
|
||||
if ( pUnpack->m_nBitOffset == NO_BIT_OFFSET ) // This test is not for bitfields.
|
||||
{
|
||||
AssertMsg( nDataTypeSize <= CDmxAttribute::AttributeDataSize( basicType ),
|
||||
( "CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into %s attribute \"%s\"!\n", CDmxAttribute::s_pAttributeTypeName[ pUnpack->m_AttributeType ], pUnpack->m_pAttributeName ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertMsg( nDataTypeSize == CDmxAttribute::AttributeDataSize( basicType ),
|
||||
( "CDmxElement::UnpackIntoStructure: Incorrect size to unpack data into %s attribute \"%s\"!\n", CDmxAttribute::s_pAttributeTypeName[ pUnpack->m_AttributeType ], pUnpack->m_pAttributeName ) );
|
||||
}
|
||||
|
||||
if ( IsArrayType( pUnpack->m_AttributeType ) )
|
||||
{
|
||||
// Copy from a fixed-size array into the attribute:
|
||||
int nArrayStride = pUnpack->m_nSize;
|
||||
pAttribute->SetArrayValue( pUnpack->m_AttributeType, pSrc, nDataTypeSize, pUnpack->m_nArrayLength, nArrayStride );
|
||||
}
|
||||
else if ( pUnpack->m_nBitOffset == NO_BIT_OFFSET )
|
||||
{
|
||||
pAttribute->SetValue( pUnpack->m_AttributeType, pSrc, nDataTypeSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Right now the max size bitfield we handle is 32.
|
||||
Assert( pUnpack->m_nBitOffset + pUnpack->m_nSize <= 32 );
|
||||
|
||||
int mask = 0;
|
||||
if ( pUnpack->m_nSize == 32 )
|
||||
{
|
||||
mask = ~0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = ( 1 << pUnpack->m_nSize ) - 1;
|
||||
mask <<= pUnpack->m_nBitOffset;
|
||||
}
|
||||
|
||||
int value = ( ( *(int *)pSrc ) & mask );
|
||||
if ( ( pUnpack->m_BitfieldType == BITFIELD_TYPE_CHAR ) ||
|
||||
( pUnpack->m_BitfieldType == BITFIELD_TYPE_SHORT ) ||
|
||||
( pUnpack->m_BitfieldType == BITFIELD_TYPE_INT ) )
|
||||
{
|
||||
// move it all the way up to make sure we get the correct sign extension.
|
||||
value <<= ( 32 - ( pUnpack->m_nBitOffset + pUnpack->m_nSize ) );
|
||||
// move it back down into position.
|
||||
value >>= ( 32 - ( pUnpack->m_nBitOffset + pUnpack->m_nSize ) );
|
||||
}
|
||||
value >>= pUnpack->m_nBitOffset;
|
||||
pAttribute->SetValue( pUnpack->m_AttributeType, &value, sizeof( int ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
828
dmxloader/dmxloader.cpp
Normal file
828
dmxloader/dmxloader.cpp
Normal file
@@ -0,0 +1,828 @@
|
||||
//====== Copyright © 1996-2004, 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/dmxheader.h"
|
||||
#include "dmxserializationdictionary.h"
|
||||
#include "tier1/memstack.h"
|
||||
#include "tier1/utldict.h"
|
||||
|
||||
|
||||
#define DMX_BINARY_VER_STRINGTABLE 2
|
||||
#define DMX_BINARY_VER_GLOBAL_STRINGTABLE 4
|
||||
#define DMX_BINARY_VER_STRINGTABLE_LARGESYMBOLS 5
|
||||
|
||||
#define CURRENT_BINARY_ENCODING 5
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 )
|
||||
{
|
||||
#ifdef PLATFORM_64BITS
|
||||
const int k_nStackSize = 4 * 1024 * 1024;
|
||||
#else
|
||||
const int k_nStackSize = 2 * 1024 * 1024;
|
||||
#endif
|
||||
s_DMXAllocator.Init( "DMXAlloc", k_nStackSize, 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;
|
||||
MEM_ALLOC_CREDIT_( "DMXAlloc" );
|
||||
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:
|
||||
// For serialize
|
||||
typedef CUtlDict< int, int > mapSymbolToIndex_t;
|
||||
|
||||
// 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, mapSymbolToIndex_t *pStringValueSymbols, CDmxElement *pElement );
|
||||
bool SaveElement( CUtlBuffer& buf, CDmxSerializationDictionary& dict, mapSymbolToIndex_t *pStringValueSymbols, CDmxElement *pElement);
|
||||
void GatherSymbols( CUtlSymbolTableLarge *pStringValueSymbols, 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 nEncodingVersion );
|
||||
int GetStringOffsetTable( CUtlBuffer &buf, int *offsetTable, int nStrings );
|
||||
|
||||
inline char const *Dme_GetStringFromBuffer( CUtlBuffer &buf, bool bUseLargeSymbols, int nStrings, int *offsetTable, char *stringTable )
|
||||
{
|
||||
int uSym = ( bUseLargeSymbols ) ? buf.GetInt() : buf.GetShort();
|
||||
if ( uSym >= nStrings )
|
||||
return NULL;
|
||||
return stringTable + offsetTable[ uSym ];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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, mapSymbolToIndex_t *pStringValueSymbols, 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;
|
||||
|
||||
buf.PutInt( pStringValueSymbols->Find( pName ) );
|
||||
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;
|
||||
|
||||
case AT_STRING:
|
||||
{
|
||||
buf.PutInt( pStringValueSymbols->Find( pAttribute->GetValueString() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
bool CDmxSerializer::SaveElementDict( CUtlBuffer& buf, mapSymbolToIndex_t *pStringValueSymbols, CDmxElement *pElement )
|
||||
{
|
||||
buf.PutInt( pStringValueSymbols->Find( pElement->GetTypeString() ) );
|
||||
buf.PutInt( pStringValueSymbols->Find( pElement->GetName() ) );
|
||||
buf.Put( &pElement->GetId(), sizeof(DmObjectId_t) );
|
||||
return buf.IsValid();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main entry point for serialization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CDmxSerializer::GatherSymbols( CUtlSymbolTableLarge *pStringValueSymbols, CDmxElement *pElement )
|
||||
{
|
||||
pStringValueSymbols->AddString( pElement->GetTypeString() );
|
||||
pStringValueSymbols->AddString( pElement->GetName() );
|
||||
|
||||
int nAttributes = pElement->AttributeCount();
|
||||
for ( int ai = 0; ai < nAttributes; ++ai )
|
||||
{
|
||||
CDmxAttribute *pAttr = pElement->GetAttribute( ai );
|
||||
if ( !pAttr )
|
||||
continue;
|
||||
|
||||
pStringValueSymbols->AddString( pAttr->GetName() );
|
||||
|
||||
if ( pAttr->GetType() == AT_STRING )
|
||||
{
|
||||
pStringValueSymbols->AddString( pAttr->GetValueString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CDmxSerializer::Serialize( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName )
|
||||
{
|
||||
DmxSerializationHandle_t i;
|
||||
|
||||
// Save elements, attribute links
|
||||
CDmxSerializationDictionary dict;
|
||||
dict.BuildElementList( pRoot, true );
|
||||
|
||||
// collect string table
|
||||
CUtlSymbolTableLarge stringSymbols;
|
||||
|
||||
for ( i = dict.FirstRootElement(); i != DMX_SERIALIZATION_HANDLE_INVALID; i = dict.NextRootElement(i) )
|
||||
{
|
||||
CDmxElement *pElement = dict.GetRootElement( i );
|
||||
if ( !pElement )
|
||||
return false;
|
||||
|
||||
GatherSymbols( &stringSymbols, pElement );
|
||||
}
|
||||
|
||||
// write out the symbol table for this file (may be significantly smaller than datamodel's full symbol table)
|
||||
int nSymbols = stringSymbols.GetNumStrings();
|
||||
|
||||
buf.PutInt( nSymbols );
|
||||
|
||||
CUtlVector< CUtlSymbolLarge > symbols;
|
||||
symbols.EnsureCount( nSymbols );
|
||||
stringSymbols.GetElements( 0, nSymbols, symbols.Base() );
|
||||
|
||||
// It's case sensitive
|
||||
mapSymbolToIndex_t symbolToIndexMap( k_eDictCompareTypeCaseSensitive );
|
||||
|
||||
for ( int si = 0; si < nSymbols; ++si )
|
||||
{
|
||||
CUtlSymbolLarge sym = symbols[ si ];
|
||||
const char *pStr = sym.String();
|
||||
symbolToIndexMap.Insert( pStr, si );
|
||||
buf.PutString( pStr );
|
||||
}
|
||||
|
||||
// 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, &symbolToIndexMap, 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, &symbolToIndexMap, 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" );
|
||||
|
||||
char idstr[ 40 ];
|
||||
buf.GetString( idstr, sizeof( idstr ) );
|
||||
// DmObjectId_t id;
|
||||
// UniqueIdFromString( &id, idstr, sizeof( idstr ) );
|
||||
|
||||
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, int nEncodingVersion )
|
||||
{
|
||||
CDmxElementModifyScope modify( pElement );
|
||||
|
||||
bool bUseLargeSymbols = nEncodingVersion >= DMX_BINARY_VER_STRINGTABLE_LARGESYMBOLS;
|
||||
|
||||
|
||||
char nameBuf[ 1024 ];
|
||||
int nAttributeCount = buf.GetInt();
|
||||
for ( int i = 0; i < nAttributeCount; ++i )
|
||||
{
|
||||
const char *pName = NULL;
|
||||
{
|
||||
if ( stringTable )
|
||||
{
|
||||
pName = Dme_GetStringFromBuffer( buf, bUseLargeSymbols, nStrings, offsetTable, stringTable );
|
||||
if ( !pName )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.GetString( nameBuf, sizeof( nameBuf ) );
|
||||
pName = nameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
DmAttributeType_t nAttributeType = (DmAttributeType_t)buf.GetChar();
|
||||
Assert( nAttributeType >= AT_FIRST_VALUE_TYPE && nAttributeType < AT_TYPE_COUNT );
|
||||
|
||||
CDmxAttribute *pAttribute = pElement->AddAttribute( pName );
|
||||
if ( !pAttribute )
|
||||
{
|
||||
Warning( "WARNING: Failed to create attribute '%s' - likely out of memory in s_DMXAllocator!\n", pName );
|
||||
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;
|
||||
|
||||
case AT_STRING:
|
||||
if ( stringTable && nEncodingVersion >= DMX_BINARY_VER_GLOBAL_STRINGTABLE )
|
||||
{
|
||||
const char *pValue = Dme_GetStringFromBuffer( buf, bUseLargeSymbols, nStrings, offsetTable, stringTable );
|
||||
if ( !pValue )
|
||||
return false;
|
||||
pAttribute->SetValue( pValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
pAttribute->Unserialize( nAttributeType, buf );
|
||||
}
|
||||
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 > CURRENT_BINARY_ENCODING )
|
||||
return false;
|
||||
|
||||
bool bReadStringTable = nEncodingVersion >= DMX_BINARY_VER_STRINGTABLE;
|
||||
bool bUseLargeSymbols = nEncodingVersion >= DMX_BINARY_VER_STRINGTABLE_LARGESYMBOLS;
|
||||
|
||||
// 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 )
|
||||
{
|
||||
if ( nEncodingVersion >= DMX_BINARY_VER_GLOBAL_STRINGTABLE )
|
||||
{
|
||||
nStrings = buf.GetInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
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 pNameBuf[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 )
|
||||
{
|
||||
pType = Dme_GetStringFromBuffer( buf, bUseLargeSymbols, nStrings, offsetTable, stringTable );
|
||||
if ( !pType )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.GetString( pTypeBuf, sizeof( pTypeBuf ) );
|
||||
pType = pTypeBuf;
|
||||
}
|
||||
|
||||
const char *pName = NULL;
|
||||
if ( bReadStringTable && nEncodingVersion >= DMX_BINARY_VER_GLOBAL_STRINGTABLE )
|
||||
{
|
||||
pName = Dme_GetStringFromBuffer( buf, bUseLargeSymbols, nStrings, offsetTable, stringTable );
|
||||
if ( !pName )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.GetString( pNameBuf, sizeof( pNameBuf ) );
|
||||
pName = pNameBuf;
|
||||
}
|
||||
|
||||
buf.Get( &id, sizeof(DmObjectId_t) );
|
||||
|
||||
CDmxElement *pElement = new CDmxElement( pType );
|
||||
{
|
||||
CDmxElementModifyScope modify( pElement );
|
||||
CDmxAttribute *pAttribute = pElement->AddAttribute( "name" );
|
||||
pAttribute->SetValue( 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 )
|
||||
{
|
||||
if ( !UnserializeAttributes( buf, elementList[ i ], elementList, nStrings, offsetTable, stringTable, nEncodingVersion ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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 : CURRENT_BINARY_ENCODING;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bTextMode )
|
||||
{
|
||||
CUtlStreamBuffer buf( pFullPath, pPathID, 0 );
|
||||
if ( !buf.IsValid() )
|
||||
{
|
||||
Warning( "SerializeDMX: Unable to open file \"%s\"\n", pFullPath );
|
||||
return false;
|
||||
}
|
||||
|
||||
return SerializeDMX( buf, pRoot, pFullPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
|
||||
bool bOk = SerializeDMX( buf, pRoot, pFullPath );
|
||||
if ( !bOk )
|
||||
return false;
|
||||
|
||||
if ( !g_pFullFileSystem->WriteFile( pFullPath, pPathID, buf ) )
|
||||
{
|
||||
Warning( "SerializeDMX: Unable to open file \"%s\"\n", pFullPath );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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, nFormatNameLen );
|
||||
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 )
|
||||
{
|
||||
CUtlStreamBuffer buf( pFullPath, pPathID, nFlags );
|
||||
if ( !buf.IsValid() )
|
||||
{
|
||||
Warning( "UnserializeDMX: Unable to open file \"%s\"\n", pFullPath );
|
||||
return false;
|
||||
}
|
||||
|
||||
return UnserializeDMX( buf, ppRoot, pFullPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
nFlags |= CUtlBuffer::TEXT_BUFFER;
|
||||
|
||||
CUtlBuffer buf( 0, 0, nFlags );
|
||||
if ( !g_pFullFileSystem->ReadFile( pFullPath, pPathID, buf ) )
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
45
dmxloader/dmxloader.vpc
Normal file
45
dmxloader/dmxloader.vpc
Normal file
@@ -0,0 +1,45 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
$File "utlsoacontainer_serialization.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"
|
||||
|
||||
$File "$SRCDIR\public\dmxloader\utlsoacontainer_serialization.h"
|
||||
}
|
||||
}
|
||||
13
dmxloader/dmxloader.vpc.vpc_cache
Normal file
13
dmxloader/dmxloader.vpc.vpc_cache
Normal file
@@ -0,0 +1,13 @@
|
||||
"vpc_cache"
|
||||
{
|
||||
"CacheVersion" "1"
|
||||
"win32"
|
||||
{
|
||||
"CRCFile" "dmxloader.vcxproj.vpc_crc"
|
||||
"OutputFiles"
|
||||
{
|
||||
"0" "dmxloader.vcxproj"
|
||||
"1" "dmxloader.vcxproj.filters"
|
||||
}
|
||||
}
|
||||
}
|
||||
1454
dmxloader/dmxloadertext.cpp
Normal file
1454
dmxloader/dmxloadertext.cpp
Normal file
File diff suppressed because it is too large
Load Diff
188
dmxloader/dmxserializationdictionary.cpp
Normal file
188
dmxloader/dmxserializationdictionary.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
//====== Copyright © 1996-2004, 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 nCount = array.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
CDmxElement *pChild = array[ i ];
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
76
dmxloader/dmxserializationdictionary.h
Normal file
76
dmxloader/dmxserializationdictionary.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//====== Copyright © 1996-2004, 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
|
||||
203
dmxloader/utlsoacontainer_serialization.cpp
Normal file
203
dmxloader/utlsoacontainer_serialization.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
|
||||
//
|
||||
// Purpose: see utlsoacontainer_serialization.h
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlsoacontainer.h"
|
||||
#include "dmxloader/dmxloader.h"
|
||||
#include "dmxloader/dmxelement.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
|
||||
// Simple wrapper class to provide access to the CSOAContainer innards
|
||||
class CSOAContainer_Serializable : public CSOAContainer
|
||||
{
|
||||
DECLARE_DMXELEMENT_UNPACK();
|
||||
public:
|
||||
bool Serialize( CDmxElement *pRootElement );
|
||||
bool Unserialize( const CDmxElement *pRootElement );
|
||||
private:
|
||||
bool ContainsValidAttributes( void );
|
||||
enum SoaContainerDmxVersion_t { SOA_CONTAINER_DMX_VERSION = 1 };
|
||||
};
|
||||
|
||||
|
||||
BEGIN_DMXELEMENT_UNPACK( CSOAContainer_Serializable )
|
||||
// NOTE: All other member variables are recomputed from the below values, after unpack, by 'AllocateData' (the stored data is copyied in after that)
|
||||
DMXELEMENT_UNPACK_FIELD( "num_columns", "0", int, m_nColumns )
|
||||
DMXELEMENT_UNPACK_FIELD( "num_rows", "0", int, m_nRows )
|
||||
DMXELEMENT_UNPACK_FIELD( "num_slices", "0", int, m_nSlices )
|
||||
DMXELEMENT_UNPACK_FIELD_ARRAY( "attribute_types", "-1", int, m_nDataType )
|
||||
DMXELEMENT_UNPACK_FIELD( "field_present_mask", "0", int, m_nFieldPresentMask )
|
||||
DMXELEMENT_UNPACK_FIELD( "thread_mode", "-1", int, m_eThreadMode )
|
||||
END_DMXELEMENT_UNPACK( CSOAContainer_Serializable, s_pSOAContainerUnpack )
|
||||
|
||||
|
||||
bool CSOAContainer_Serializable::Serialize( CDmxElement *pRootElement )
|
||||
{
|
||||
CDmxElementModifyScope modifyRoot( pRootElement );
|
||||
|
||||
COMPILE_TIME_ASSERT( ATTRDATATYPE_NONE == -1 ); // If this changes, modify the line for m_nDataType in the BEGIN_DMXELEMENT_UNPACK block above
|
||||
COMPILE_TIME_ASSERT( SOATHREADMODE_AUTO == -1 ); // If this changes, modify the line for m_eThreadMode in the BEGIN_DMXELEMENT_UNPACK block above
|
||||
|
||||
if ( !ContainsValidAttributes() || ( !m_pDataMemory && !m_pConstantDataMemory ) )
|
||||
{
|
||||
Warning( "ERROR: CSOAContainer_Serializable::Unserialize - no data to serialize!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the version number first
|
||||
const int nDmxVersion = SOA_CONTAINER_DMX_VERSION;
|
||||
pRootElement->SetValue( "version", nDmxVersion );
|
||||
|
||||
// Write some member variables (enough to recompute the rest)
|
||||
pRootElement->AddAttributesFromStructure( this, s_pSOAContainerUnpack );
|
||||
|
||||
// Now write out the data, as floats (NOTE: we have to at least init the attribute as a zero-element vector or it won't serialize!)
|
||||
CDmxAttribute *pDataMemoryAttribute = pRootElement->AddAttribute( "memory_data" );
|
||||
CUtlVector< float >& dataVector = pDataMemoryAttribute->GetArrayForEdit< float >();
|
||||
size_t nDataMemorySize = DataMemorySize();
|
||||
dataVector.SetCount( nDataMemorySize / sizeof( float ) );
|
||||
|
||||
// NOTE: Constant data is always zero for now, but we write it out in case that changes (non-zero constant values seem potentially useful)
|
||||
CDmxAttribute *pConstantMemoryAttribute = pRootElement->AddAttribute( "constant_data" );
|
||||
CUtlVector< float >& constantVector = pConstantMemoryAttribute->GetArrayForEdit< float >();
|
||||
size_t nConstantMemorySize = ConstantMemorySize();
|
||||
constantVector.SetCount( nConstantMemorySize / sizeof( float ) );
|
||||
|
||||
// To account for 'separate' memory allocations, we need to copy each attribute one at a time
|
||||
byte *pBaseDataPtr = (byte *)dataVector.Base();
|
||||
byte *pBaseConstantPtr = (byte *)constantVector.Base();
|
||||
for( int i = 0; i < MAX_SOA_FIELDS; i++ )
|
||||
{
|
||||
if ( m_nDataType[i] == ATTRDATATYPE_NONE )
|
||||
continue;
|
||||
|
||||
if ( m_nFieldPresentMask & ( 1 << i ) )
|
||||
{
|
||||
memcpy( pBaseDataPtr, m_pAttributePtrs[ i ], AttributeMemorySize( i ) );
|
||||
pBaseDataPtr += AttributeMemorySize( i );
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( pBaseConstantPtr, m_pAttributePtrs[ i ], AttributeMemorySize( i ) );
|
||||
pBaseConstantPtr += AttributeMemorySize( i );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSOAContainer_Serializable::Unserialize( const CDmxElement *pRootElement )
|
||||
{
|
||||
// Read the version number
|
||||
int nVersion = pRootElement->GetValue( "version", -1 );
|
||||
if ( nVersion == -1 )
|
||||
{
|
||||
Warning( "ERROR: CSOAContainer_Serializable::Unserialize - missing version field!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear, then unpack the stored members
|
||||
Purge();
|
||||
pRootElement->UnpackIntoStructure( this, s_pSOAContainerUnpack );
|
||||
|
||||
// Check that we have enough data to create a valid container!
|
||||
int nError = 0;
|
||||
const CDmxAttribute *pDataMemoryAttribute = pRootElement->GetAttribute( "memory_data" );
|
||||
const CDmxAttribute *pConstantMemoryAttribute = pRootElement->GetAttribute( "constant_data" );
|
||||
if ( !pDataMemoryAttribute || !pConstantMemoryAttribute )
|
||||
nError = 1;
|
||||
if ( !ContainsValidAttributes() )
|
||||
nError = 1;
|
||||
|
||||
if ( !nError )
|
||||
{
|
||||
// Update files saved in old versions
|
||||
switch( nVersion )
|
||||
{
|
||||
case SOA_CONTAINER_DMX_VERSION:
|
||||
break; // Up to date - nothing to do.
|
||||
default:
|
||||
// The DMX unpack structure will set reasonable defaults or flag stuff that needs fixing up
|
||||
nError = 1; // TODO: add code when versions are bumped and fixup needs to happen
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !nError )
|
||||
{
|
||||
SOAThreadMode_t eSavedThreadMode = m_eThreadMode;
|
||||
|
||||
// Allocate memory (fills in all the pointers and strides)
|
||||
AllocateData( NumCols(), NumRows(), NumSlices() );
|
||||
|
||||
// Set thread mode from the unserialized value (AllocateData stomps on it)
|
||||
SetThreadMode( eSavedThreadMode );
|
||||
|
||||
// Now copy in the data
|
||||
if ( m_pDataMemory )
|
||||
{
|
||||
const CUtlVector< float >& floatVector = pDataMemoryAttribute->GetArray< float >();
|
||||
size_t nDataMemorySize = DataMemorySize();
|
||||
int nFloats = nDataMemorySize / sizeof( float );
|
||||
if ( nFloats == floatVector.Count() )
|
||||
memcpy( m_pDataMemory, floatVector.Base(), nDataMemorySize );
|
||||
else
|
||||
nError = 2;
|
||||
}
|
||||
if ( m_pConstantDataMemory )
|
||||
{
|
||||
const CUtlVector< float >& floatVector = pConstantMemoryAttribute->GetArray< float >();
|
||||
size_t nConstantMemorySize = ConstantMemorySize();
|
||||
int nFloats = nConstantMemorySize / sizeof( float );
|
||||
if ( nFloats == floatVector.Count() )
|
||||
memcpy( m_pConstantDataMemory, floatVector.Base(), nConstantMemorySize );
|
||||
else
|
||||
nError = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if ( nError )
|
||||
{
|
||||
switch( nError )
|
||||
{
|
||||
case 1: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - DMX data does not represent a valid container!\n" ); break;
|
||||
case 2: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - found wrong amount of memory data!\n" ); break;
|
||||
case 3: Warning( "ERROR: CSOAContainer_Serializable::Unserialize - found wrong amount of constant data!\n" ); break;
|
||||
}
|
||||
Assert( 0 );
|
||||
Purge();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSOAContainer_Serializable::ContainsValidAttributes( void )
|
||||
{
|
||||
if ( ( NumCols() <= 0 ) || ( NumRows() <= 0 ) || ( NumSlices() <= 0 ) )
|
||||
return false;
|
||||
for ( int i = 0; i < MAX_SOA_FIELDS; i++ )
|
||||
{
|
||||
if ( m_nDataType[ i ] != ATTRDATATYPE_NONE )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SerializeCSOAContainer( const CSOAContainer *pContainer, CDmxElement *pRootElement )
|
||||
{
|
||||
return ((CSOAContainer_Serializable*)pContainer)->Serialize( pRootElement );
|
||||
}
|
||||
|
||||
bool UnserializeCSOAContainer( const CSOAContainer *pContainer, const CDmxElement *pRootElement )
|
||||
{
|
||||
return ((CSOAContainer_Serializable*)pContainer)->Unserialize( pRootElement );
|
||||
}
|
||||
2
dmxloader/vsi.nul
Normal file
2
dmxloader/vsi.nul
Normal file
@@ -0,0 +1,2 @@
|
||||
SN Visual Studio Integration
|
||||
IMPORTANT: Do not remove the custom build step for this file
|
||||
Reference in New Issue
Block a user