This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,93 @@
//===== Copyright c 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Describes our resource format. Resource files consist of two files:
// The first is a resource descriptor file containing various blocks of
// arbitrary data, including a resource dictionary describing raw data which
// is stored in a second, parallel file.
//
// $NoKeywords: $
//===========================================================================//
#ifndef RESOURCEDICTIONARY_H
#define RESOURCEDICTIONARY_H
#pragma once
#include "resourcefile/schema.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct ResourceDictionary_t;
struct ResourceDictionaryGroup_t;
struct ResourceDescription_t;
//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------
schema typedef uint32 ResourceId_t;
//-----------------------------------------------------------------------------
// Enum definitions
//-----------------------------------------------------------------------------
schema enum ResourceDictionaryVersion_t
{
RESOURCE_DICT_VERSION = 1,// (explicit)
};
schema enum ResourceCompressionType_t
{
RESOURCE_COMPRESSION_NONE = 0,
};
schema enum ResourceStandardIds_t
{
RESOURCE_ID_INVALID = 0,
};
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
//! resourceBlockType = "RESD"
schema struct ResourceDictionary_t
{
uint32 m_nCompressionType;
uint32 m_nUncompressedLength;
uint32 m_nPageSize;
uint32 m_nAlignment;
CResourceArray< ResourceDictionaryGroup_t > m_ResourceGroups;
};
DEFINE_RESOURCE_BLOCK_TYPE( ResourceDictionary_t, 'R', 'E', 'S', 'D' )
schema struct ResourceDictionaryGroup_t
{
uint32 m_nResourceType; // see ResourceType_t
uint16 m_nCompressionType;
uint16 m_nFlags;
CResourceArray< ResourceDescription_t > m_Resources;
};
schema struct ResourceDescription_t
{
uint32 m_nId;
uint32 m_nStartOffset;
uint32 m_nSize;
uint32 m_nUncompressedSize;
};
//-----------------------------------------------------------------------------
// Computes a resource id given a resource name
// NOTE: Most resource names are of the format:
// <relative file name under content>::<subresource name>
//-----------------------------------------------------------------------------
ResourceId_t ComputeResourceIdHash( const char *pResourceName );
ResourceId_t ComputeResourceIdHash( const char *pFileName, const char *pSubResourceName );
void GenerateResourceName( const char *pFileName, const char *pSubResourceName, char *pResourceName, size_t pBufLen );
void GenerateResourceFileName( const char *pFileName, char *pResourceFileName, size_t nBufLen );
#endif // RESOURCEDICTIONARY_H

View File

@@ -0,0 +1,145 @@
//===== Copyright c 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Describes our resource format. All resource files have a simplistic
// dictionary of resource "blocks", which can be looked up using a block type id.
// Each resource block type is expected to be associated with a well defined
// structure. The macro DEFINE_RESOURCE_BLOCK_TYPE is used to create this
// association.
//
// The current design choice is that we expect files using this resource format
// to be small. Large-scale files, like sound or texture bits, are expected to
// exist in a file parallel to the file containing these resource blocks owing
// to issues of alignment or streaming. We therefore expect users of files
// containing the data described in this header to load the entire file in
// so that all blocks are in memory.
//
// $NoKeywords: $
//===========================================================================//
#ifndef RESOURCEFILE_H
#define RESOURCEFILE_H
#pragma once
#include "resourcefile/schema.h"
#include "tier0/platform.h"
#include "resourcefile/resourcestream.h"
#include "datamap.h"
//-----------------------------------------------------------------------------
//
// On-disk structures related to the resource file format
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Resource block types
//-----------------------------------------------------------------------------
typedef uint32 ResourceBlockId_t;
//-----------------------------------------------------------------------------
// A block of resource data
//-----------------------------------------------------------------------------
struct ResourceBlockEntry_t
{
DECLARE_BYTESWAP_DATADESC();
ResourceBlockId_t m_nBlockType;
CResourcePointer<void> m_pBlockData;
};
//-----------------------------------------------------------------------------
// Structure of resource file header
//-----------------------------------------------------------------------------
enum ResourceFileHeaderVersion_t
{
RESOURCE_FILE_HEADER_VERSION = 1,
};
struct ResourceFileHeader_t
{
DECLARE_BYTESWAP_DATADESC();
uint32 m_nVersion; // see ResourceFileHeaderVersion_t
uint32 m_nSizeInBytes; // Size in bytes of entire file
CResourceArray< ResourceBlockEntry_t > m_ResourceBlocks;
};
//-----------------------------------------------------------------------------
//
// Methods used to define resource blocks/read them from files
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Resource block IDs
//-----------------------------------------------------------------------------
#define RSRC_BYTE_POS( byteVal, shft ) ResourceBlockId_t( uint32(uint8(byteVal)) << uint8(shft * 8) )
#if !defined( PLATFORM_X360 )
#define MK_RSRC_BLOCK_ID(a, b, c, d) ResourceBlockId_t( RSRC_BYTE_POS(a, 0) | RSRC_BYTE_POS(b, 1) | RSRC_BYTE_POS(c, 2) | RSRC_BYTE_POS(d, 3) )
#else
#define MK_RSRC_BLOCK_ID(a, b, c, d) ResourceBlockId_t( RSRC_BYTE_POS(a, 3) | RSRC_BYTE_POS(b, 2) | RSRC_BYTE_POS(c, 1) | RSRC_BYTE_POS(d, 0) )
#endif
#define RESOURCE_BLOCK_ID_INVALID 0xFFFFFFFF
//-----------------------------------------------------------------------------
// Helpers used to define resource block IDs + associated structs
//-----------------------------------------------------------------------------
template< class T >
struct ResourceBlockIdSelector_t
{
enum { RESOURCE_BLOCK_ID = RESOURCE_BLOCK_ID_INVALID };
};
#define DEFINE_RESOURCE_BLOCK_TYPE( _class, _ida, _idb, _idc, _idd ) \
template <> struct ResourceBlockIdSelector_t< _class > { enum { RESOURCE_BLOCK_ID = MK_RSRC_BLOCK_ID( _ida, _idb, _idc, _idd ) }; };
//-----------------------------------------------------------------------------
// Does this resource file contain a particular block?
//-----------------------------------------------------------------------------
bool Resource_IsBlockDefined( const ResourceFileHeader_t *pHeader, ResourceBlockId_t id );
//-----------------------------------------------------------------------------
// Gets the data associated with a particular data block
//-----------------------------------------------------------------------------
const void *Resource_GetBlock( const ResourceFileHeader_t *pHeader, ResourceBlockId_t id );
template< class T > inline const T* Resource_GetBlock( const ResourceFileHeader_t *pHeader )
{
return (const T*)Resource_GetBlock( pHeader, ResourceBlockIdSelector_t< T >::RESOURCE_BLOCK_ID );
}
//-----------------------------------------------------------------------------
// Helper methods to write block information
//-----------------------------------------------------------------------------
inline ResourceFileHeader_t *Resource_AllocateHeader( CResourceStream *pStream, int nBlockCount )
{
ResourceFileHeader_t *pHeader = pStream->Allocate< ResourceFileHeader_t >();
pHeader->m_nVersion = RESOURCE_FILE_HEADER_VERSION;
pHeader->m_ResourceBlocks = pStream->Allocate< ResourceBlockEntry_t >( nBlockCount );
return pHeader;
}
//-----------------------------------------------------------------------------
// Helper methods to write block information
//-----------------------------------------------------------------------------
template< class T > inline T* Resource_AllocateBlock( CResourceStream *pStream, ResourceFileHeader_t *pHeader, int nBlockIndex )
{
pHeader->m_ResourceBlocks[nBlockIndex].m_nBlockType = ResourceBlockIdSelector_t< T >::RESOURCE_BLOCK_ID;
T *pBlockData = pStream->Allocate< T >( 1 );
pHeader->m_ResourceBlocks[nBlockIndex].m_pBlockData = pBlockData;
return pBlockData;
}
#endif // RESOURCEFILE_H

View File

@@ -0,0 +1,430 @@
//===== Copyright c 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Describes data which is used to help determine introspection
// data for a resource file. Specifies which fields are what types, and
// also specifies which fields refer to other types (by ptr or array).
//
// $NoKeywords: $
//===========================================================================//
#ifndef RESOURCEINTROSPECTION_H
#define RESOURCEINTROSPECTION_H
#pragma once
#include "resourcefile/schema.h"
#include "mathlib/vmatrix.h"
#include "mathlib/ssemath.h"
class CResourceIntrospection;
//-----------------------------------------------------------------------------
// Enum definitions
//-----------------------------------------------------------------------------
schema enum ResourceIntrospectionVersion_t
{
RESOURCE_INTROSPECTION_VERSION = 2,
};
// NOTE: If you add to this enum, you'll need to update s_pFieldTypes in resourceintrospection.cpp
schema enum ResourceFieldType_t
{
RESOURCE_FIELD_TYPE_UNKNOWN,
RESOURCE_FIELD_TYPE_RESOURCE_POINTER, // nFieldData = CResourcePointer<CResourceFieldTypeIntrospection> for pointed-to type
RESOURCE_FIELD_TYPE_RESOURCE_ARRAY, // nFieldData = CResourcePointer<CResourceFieldTypeIntrospection> for element type
RESOURCE_FIELD_TYPE_STRUCT, // nFieldData = hash(struct_name)
RESOURCE_FIELD_TYPE_ENUM, // nFieldData = hash(enum_name)
RESOURCE_FIELD_TYPE_RESOURCE_REFERENCE, // nFieldData = member of ResourceTypeEngine_t
////////////////////////
// fields of these types are never serialized to disk
RESOURCE_FIELD_TYPE_CHAR,
RESOURCE_FIELD_TYPE_C_POINTER,
////////////////////////
// ints and uints are always serialized at RESOURCE_PLAIN_INT_SERIALIZATION_SIZE bytes
RESOURCE_FIELD_TYPE_INT,
RESOURCE_FIELD_TYPE_UINT,
// floats are always serialized at RESOURCE_PLAIN_FLOAT_SERIALIZATION_SIZE bytes
RESOURCE_FIELD_TYPE_FLOAT,
// simple types
RESOURCE_FIELD_TYPE_INT8,
RESOURCE_FIELD_TYPE_UINT8,
RESOURCE_FIELD_TYPE_INT16,
RESOURCE_FIELD_TYPE_UINT16,
RESOURCE_FIELD_TYPE_INT32,
RESOURCE_FIELD_TYPE_UINT32,
RESOURCE_FIELD_TYPE_INT64,
RESOURCE_FIELD_TYPE_UINT64,
RESOURCE_FIELD_TYPE_FLOAT32,
RESOURCE_FIELD_TYPE_FLOAT64,
// common primitive types
RESOURCE_FIELD_TYPE_TIME,
RESOURCE_FIELD_TYPE_VECTOR2D,
RESOURCE_FIELD_TYPE_VECTOR3D,
RESOURCE_FIELD_TYPE_VECTOR4D,
RESOURCE_FIELD_TYPE_QANGLE,
RESOURCE_FIELD_TYPE_QUATERNION,
RESOURCE_FIELD_TYPE_VMATRIX,
RESOURCE_FIELD_TYPE_FLTX4,
// TODO -
RESOURCE_FIELD_TYPE_BOOL,
RESOURCE_FIELD_TYPE_STRING,
RESOURCE_FIELD_TYPE_VOID,
RESOURCE_FIELD_TYPE_COUNT,
};
schema enum ResourceIntrospectionMetadataType_t
{
RESOURCE_META_TYPE_NAMEONLY,
RESOURCE_META_TYPE_STRING,
RESOURCE_META_TYPE_INT,
RESOURCE_META_TYPE_FLOAT,
};
enum ResourceDataLayout_t
{
RESOURCE_DATA_LAYOUT_MEMORY,
RESOURCE_DATA_LAYOUT_DISK,
};
enum IntrospectionCompatibilityType_t
{
INTROSPECTION_COMPAT_UNKNOWN,
INTROSPECTION_COMPAT_IDENTICAL, // Disk and memory layout are the same
INTROSPECTION_COMPAT_REQUIRES_SCATTER, // Identical structures, but disk layout != memory layout
INTROSPECTION_COMPAT_REQUIRES_CONVERSION, // CRCs don't match, requires name-based, per-element conversion
};
const uint RESOURCE_PLAIN_INT_SERIALIZATION_SIZE = 4;
const uint RESOURCE_PLAIN_FLOAT_SERIALIZATION_SIZE = 4;
//-----------------------------------------------------------------------------
// Structure id: it's generated by a hash of the structure name
//-----------------------------------------------------------------------------
typedef uint32 ResourceStructureId_t;
#define RESOURCE_STRUCTURE_ID_INVALID ( (ResourceStructureId_t)0 )
//-----------------------------------------------------------------------------
// Information for resource fields
//-----------------------------------------------------------------------------
struct ResourceFieldProperties_t
{
// helper function
static const ResourceFieldProperties_t* GetFieldProperties( ResourceFieldType_t nFieldType );
const char * m_pTypeName;
ResourceFieldType_t m_nFieldType;
uint m_nMemorySize;
uint m_nDiskSize; // 0 = not serialized to disk
uint m_nAlignment;
};
//-----------------------------------------------------------------------------
schema class CResourceFieldIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceFieldIntrospection );
// These methods are used for reading the data
public:
ResourceFieldType_t GetRootType() const;
uint32 GetRootTypeData() const;
ResourceFieldType_t ReadTypeChain( int nChainIndex ) const;
// These methods are used for writing the data
public:
void SetFieldInfo( CResourceStream *pStream, const char *pFieldName, int nMemoryOffset, int nDiskOffset, int nArrayCount );
void SetFieldInfo( CResourceStream *pStream, const CResourceFieldIntrospection *src );
void SetFieldType( CResourceStream *pStream, const CUtlVector<ResourceFieldType_t>& TypeChain, uint32 nRootFieldData );
// Introspection helper routines
public:
int GetElementMemorySize( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
int GetElementDiskSize( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
int GetElementSize( const ResourceDataLayout_t nDataLocation, int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
int GetElementAlignment( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
public:
CResourceString m_pFieldName;
int16 m_nCount;
int16 m_nInMemoryOffset;
int16 m_nOnDiskOffset; // -1 means not serialized to disk
// FIXME: The following representation will need to be tweaked;
// Ideally none of the simple cases requires an allocation, (including ptr to struct)
// and we do have 16 bits to work with due to alignment, plus 8 bits if we want to trim TypeChainCount.
// If m_nTypeChainCount == 1, then m_nTypeChain is the field data
// If m_nTypeChainCount > 1, m_nTypeChain is a CResourcePointer<uint32> to N uint32's
// that looks like [FieldType, ..., FieldType, FieldData]
// Examples of: [ m_nFieldType, m_nTypeChainCount ; m_nTypeChain ]
// -------------------------------------------------------------------------------
// Simple inline int8: [ RESOURCE_FIELD_TYPE_INT8, 1 ; 0 ]
// Pointer to int8: [ RESOURCE_FIELD_TYPE_RESOURCE_POINTER, 2 ; RESOURCE_FIELD_TYPE_INT8 ]
// Pointer to struct X: [ RESOURCE_FIELD_TYPE_RESOURCE_POINTER, 3 ; Ptr ]
// where *Ptr = [RESOURCE_FIELD_TYPE_STRUCT; hash(X)]
// Array of pointers to struct X: [ RESOURCE_FIELD_TYPE_DYNAMIC_ARRAY, 4 ; Ptr ]
// where *Ptr = [RESOURCE_FIELD_TYPE_RESOURCE_POINTER; RESOURCE_FIELD_TYPE_STRUCT; hash(X)]
int16 m_nTypeChainCount;
int16 m_nFieldType;
uint32 m_nTypeChain;
};
schema enum ResourceStructFlags_t
{
RESOURCE_STRUCT_HAS_VTABLE = 1,
};
schema class CResourceStructIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceStructIntrospection );
// These methods are used for reading the data
public:
// Iterate over all fields
int GetFieldCount() const;
const CResourceFieldIntrospection* GetField( int nIndex ) const;
// Find a field
const CResourceFieldIntrospection* FindField( const char *pFieldName ) const;
bool HasVTable() const;
// (to determine whether version up-conversion is necessary)
// These methods are used for writing the data
public:
void SetStructInfo( CResourceStream *pStream, const char *pStructName, const char *pBaseStruct, const char *pUncacheableStruct, uint32 nMemorySize, uint32 nDiskSize, uint32 nAlignment, const char *pDmeElementType, const char *pBlockType, const char *pResourceType, bool bHasVTable );
void SetStructInfo( CResourceStream *pStream, const CResourceStructIntrospection *src );
void ComputeCRC( CResourceStream *pStream );
void AllocateFields( CResourceStream *pStream, int nCount );
CResourceFieldIntrospection* GetWritableField( int nIndex );
public:
uint32 m_nId;
CResourceString m_pName;
uint32 m_nCrc;
uint16 m_nMemorySize;
uint16 m_nDiskSize;
uint16 m_nAlignment;
uint32 m_nBaseStructId;
uint32 m_nUncacheableStructId;
uint8 m_ResourceBlockType[4]; // Specifies the block four-CC code if this structure is a type associated with a resource file block.
CResourceString m_pResourceType; // Specifies the resource type if this structure is a type associated with a resource type.
CResourceString m_pDmeElementType; // Specifies the DmElement type associated with this structure. Empty string means use CDmElement.
CResourceArray< CResourceFieldIntrospection > m_FieldIntrospection;
uint8 m_nStructFlags;
};
//-----------------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------------
schema class CResourceEnumValueIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceEnumValueIntrospection );
// These methods are used for reading the data
public:
const char *GetName() const;
int GetValue() const;
// These methods are used for writing the data
public:
void SetEnumValueInfo( CResourceStream *pStream, const char *pEnumValueName, int32 nValue );
public:
CResourceString m_pEnumValueName;
int32 m_nEnumValue;
};
schema class CResourceEnumIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceEnumIntrospection );
// These methods are used for reading the data
public:
// Iterate over all enum values
int GetEnumValueCount() const;
const CResourceEnumValueIntrospection* GetEnumValue( int nIndex ) const;
CResourceEnumValueIntrospection* GetWritableEnumValue( int nIndex );
// Find a field
const CResourceEnumValueIntrospection* FindEnumValue( const char *pEnumValueName ) const;
const char *FindEnumString( int nValue ) const;
// Gets CRC information about the struct
// (to determine whether version up-conversion is necessary)
// These methods are used for writing the data
public:
void SetEnumName( CResourceStream *pStream, const char *pEnumName );
void ComputeCRC( CResourceStream *pStream );
void AllocateEnumValues( CResourceStream *pStream, int nCount );
public:
uint32 m_nId;
CResourceString m_pName;
uint32 m_nCrc;
CResourceArray< CResourceEnumValueIntrospection > m_EnumValueIntrospection;
};
//-----------------------------------------------------------------------------
// Typedefs
//-----------------------------------------------------------------------------
schema class CResourceTypedefIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceTypedefIntrospection );
// These methods are used for reading the data
public:
// These methods are used for writing the data
public:
void SetTypedefInfo( CResourceStream *pStream, const char *pTypedefName, const char *pTypedefType );
public:
uint32 m_nId;
CResourceString m_pName;
CResourceString m_pType;
};
//-----------------------------------------------------------------------------
// Metadata
//-----------------------------------------------------------------------------
schema class CResourceIntrospectionMetadataElement
{
friend class CResourceIntrospectionMetadata;
public:
const char* GetStringValue() const;
int GetIntValue() const;
float GetFloatValue() const;
private:
CResourceString m_Name;
ResourceIntrospectionMetadataType_t m_Type;
uint32 m_Value;
};
schema class CResourceIntrospectionChildMetadata
{
friend class CResourceIntrospectionMetadata;
private:
CResourceString m_ChildName;
CResourceArray<CResourceIntrospectionMetadataElement> m_MetaElements;
};
schema class CResourceIntrospectionMetadata
{
public:
DECLARE_SCHEMA_DATA_CLASS( CResourceIntrospectionMetadata );
protected:
CResourceString m_ObjectName;
CResourceArray<CResourceIntrospectionMetadataElement> m_RootMetaElements;
CResourceArray<CResourceIntrospectionChildMetadata> m_ChildrenMeta;
};
//-----------------------------------------------------------------------------
// Root introspection block
//-----------------------------------------------------------------------------
//! resourceBlockType = "RESI"
schema class CResourceIntrospection
{
DECLARE_SCHEMA_DATA_CLASS( CResourceIntrospection );
public:
static CResourceIntrospection* AddToStream( CResourceStream *pStream, ResourceFileHeader_t *pHeader, int nBlockIndex );
static const CResourceIntrospection* FindInFile( const ResourceFileHeader_t *pHeader );
// These methods are used for reading the data
public:
uint32 GetVersion() const;
int GetStructCount() const;
const CResourceStructIntrospection* GetStructIntrospection( int nIndex ) const;
const CResourceStructIntrospection* FindStructIntrospection( ResourceStructureId_t id ) const;
const CResourceStructIntrospection* FindStructIntrospection( const char *pStructName ) const;
CResourceStructIntrospection* GetWritableStructIntrospection( int nIndex );
const CResourceStructIntrospection* FindStructIntrospectionForResourceType( ResourceType_t nType ) const;
const CResourceStructIntrospection* FindPermanentStructIntrospectionForResourceType( ResourceType_t nType ) const;
int GetEnumCount() const;
const CResourceEnumIntrospection* GetEnumIntrospection( int nIndex ) const;
const CResourceEnumIntrospection* FindEnumIntrospection( ResourceStructureId_t id ) const;
const CResourceEnumIntrospection* FindEnumIntrospection( const char *pEnumName ) const;
CResourceEnumIntrospection* GetWritableEnumIntrospection( int nIndex );
int GetTypedefCount() const;
const CResourceTypedefIntrospection* GetTypedefIntrospection( int nIndex ) const;
CResourceTypedefIntrospection* GetWritableTypedefIntrospection( int nIndex );
// Compare with the current EXE's introspection
IntrospectionCompatibilityType_t CalculateCompatibility() const;
// These methods are used for writing the data
public:
void AllocateStructs( CResourceStream *pStream, int nCount );
void AllocateEnums( CResourceStream *pStream, int nCount );
void AllocateTypedefs( CResourceStream *pStream, int nCount );
const void *GetPtr() const { return this; }
private:
// This should always be the first 4 bytes, since this structure can't be fully-introspected
uint32 m_nVersion;
CResourceArray< CResourceTypedefIntrospection > m_TypedefIntrospection;
CResourceArray< CResourceEnumIntrospection > m_EnumIntrospection;
CResourceArray< CResourceStructIntrospection > m_StructIntrospection;
CResourcePointer< CResourceIntrospectionMetadata > m_Metadata;
};
DEFINE_RESOURCE_BLOCK_TYPE( CResourceIntrospection, 'R', 'E', 'S', 'I' )
//-----------------------------------------------------------------------------
// Computes a resource structure id given a structure name string
//-----------------------------------------------------------------------------
ResourceStructureId_t ComputeStructureNameHash( const char *pStructName );
//-----------------------------------------------------------------------------
// Inherit from this to fully-traverse a piece of memory using introspection
//-----------------------------------------------------------------------------
class CResourceIntrospectionTraversal
{
public:
CResourceIntrospectionTraversal( const CResourceIntrospection *pResIntro = NULL );
virtual void TraverseStruct( const void *pStruct, const CResourceStructIntrospection *pStructIntro );
protected:
virtual void TraverseField( const void *pField, const CResourceFieldIntrospection *pFieldIntro, ResourceFieldType_t fieldType, int nTypeChainIndex );
virtual void TraverseRootField( const void *pField, const CResourceFieldIntrospection *pFieldIntro );
// Simple overridable methods
virtual bool VisitField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro, int nTypeChainIndex ) { return true; }
virtual void PostVisitField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro, int nTypeChainIndex ) { }
virtual bool VisitRootField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro ) { return true; }
virtual bool VisitStruct( const void *pStruct, const CResourceStructIntrospection *pStructIntro ) { return true; }
virtual bool VisitEnum( const void *pEnum, const CResourceEnumIntrospection *pEnumIntro ) { return true; }
bool m_bTraverseDiskLayout; // as opposed to memory layout
const CResourceIntrospection *m_pResIntro;
// TODO: Probably want more flags, like bFollowStructPointers, etc.
};
#endif // RESOURCEINTROSPECTION_H

View File

@@ -0,0 +1,966 @@
//===== Copyright © Valve Corporation, All rights reserved. ======//
//
// Purpose: Resource Stream is conceptually memory file where you write the data
// that you want to live both on disk and in memory. The constraint then is
// that the data must be movable in memory, since you don't know in advance,
// when you're creating the data, what will be its start address once it gets
// loaded. To accomplish this, we use CResourcePointer and CResourceArray
// in places of pointers and dynamic arrays. They store offsets rather than
// absolute addresses of the referenced objects, thus they are moveable.
// On Intel, the available addressing modes make the access to CResourcePointer
// as fast as pointer dereferencing in most cases. On architectures with
// rigid addressing, adding the base address is still virtually free.
//
// $NoKeywords: $
//===========================================================================//
#include "resourcefile/schema.h"
#ifndef RESOURCESTREAM_H
#define RESOURCESTREAM_H
#ifdef COMPILER_MSVC
#pragma once
#endif
#include "tier0/platform.h"
#include "tier0/basetypes.h"
#include "tier0/dbg.h"
#include "tier1/strtools.h"
class CResourceStream;
inline byte *ResolveOffset( const int32 *pOffset )
{
int offset = *pOffset;
return offset ? ( ( byte* )pOffset ) + offset : NULL;
}
inline byte *ResolveOffsetFast( const int32 *pOffset )
{
int offset = *pOffset;
AssertDbg( offset != 0 );
return ( ( byte* )pOffset ) + offset;
}
template <typename T>
class CLockedResource
{
private:
T *m_pData; // data; may be const
uint m_nCount; // number of allocated data elements
//uint m_nStride; // normally sizeof(T), but may be not
//uint m_nClassCRC;
public:
CLockedResource(): m_pData( NULL ), m_nCount( 0 ) {}
CLockedResource( T *pData, uint nCount ): m_pData( pData ), m_nCount( nCount ) {}
// emulates pointer arithmetics
CLockedResource<T> operator + ( int nOffset ) { Assert( m_nCount <= (uint)nOffset); return CLockedResource<T>( m_pData + nOffset, m_nCount - (uint)nOffset ); }
operator const T* ()const { return m_pData; }
operator T* () { return m_pData; }
T* operator ->() { return m_pData; }
const T* operator ->() const { return m_pData; }
uint Count()const {return m_nCount;}
};
template <typename T>
class CUnlockedResource
{
private:
CResourceStream *m_pStream; // data; may be const
uint32 m_nOffset;
uint32 m_nCount; // number of allocated data elements
//uint m_nStride; // normally sizeof(T), but may be not
//uint m_nClassCRC;
public:
CUnlockedResource( ): m_pStream( NULL ), m_nOffset( 0 ), m_nCount( 0 ) {}
CUnlockedResource( CResourceStream *pStream, T *pData, uint nCount );
bool IsValid( )const { return m_pStream != NULL; }
void Reset( ) { m_pStream = NULL; }
// emulates pointer arithmetics
CUnlockedResource<T> operator + ( int nOffset )
{
Assert( m_nCount <= ( uint ) nOffset );
return CUnlockedResource<T>( m_pStream, GetPtr() + nOffset, m_nCount - ( uint ) nOffset );
}
operator const T* ( )const { return GetPtr(); }
operator T* ( ) { return GetPtr(); }
T* operator ->( ) { return GetPtr(); }
const T* operator ->( ) const { return GetPtr(); }
uint Count( )const { return m_nCount; }
T* GetPtr( );
const T* GetPtr( )const;
};
// AT RUN-TIME ONLY the offset converts automatically into pointers to the appropritate type
// at tool-time, you should use LinkSource_t and LinkTarget_t
class CResourcePointerBase
{
protected:
int32 m_nOffset;
public:
CResourcePointerBase() : m_nOffset( 0 ) {}
bool operator == ( int zero )const
{
AssertDbg( zero == 0 );
return m_nOffset == zero;
}
bool IsNull()const
{
return m_nOffset == 0;
}
int32 NotNull()const
{
return m_nOffset;
}
int32 GetOffset() const
{
return m_nOffset;
}
const byte* GetUncheckedRawPtr() const
{
// assumes non-null; returns garbage if this is a null pointer
return ResolveOffsetFast( &m_nOffset );
}
byte* GetUncheckedRawPtr()
{
// assumes non-null; returns garbage if this is a null pointer
return ResolveOffsetFast( &m_nOffset );
}
const byte* GetRawPtr() const
{
return ResolveOffset( &m_nOffset );
}
byte* GetRawPtr()
{
return ResolveOffset( &m_nOffset );
}
void SetRawPtr( const void* p )
{
if ( p == NULL )
{
m_nOffset = 0;
}
else
{
intp nOffset = ( intp )p - ( intp )&m_nOffset;
m_nOffset = ( int32 )nOffset;
AssertDbg( m_nOffset == nOffset );
}
}
void SetNull()
{
m_nOffset = 0;
}
};
template <typename T>
class CResourcePointer: public CResourcePointerBase
{
public:
FORCEINLINE const T* GetUncheckedPtr() const
{
// assumes non-null; returns garbage if this is a null pointer
AssertDbg( m_nOffset != 0 );
byte *ptr = ResolveOffsetFast( &m_nOffset );
return ( const T* )ptr;
}
FORCEINLINE const T* GetPtr() const
{
byte *ptr = ResolveOffset( &m_nOffset );
return ( const T* )ptr;
}
FORCEINLINE operator const T*() const
{
return GetPtr();
}
FORCEINLINE const T* operator->() const
{
return GetPtr();
}
void operator = ( const T* pT )
{
SetRawPtr( pT );
}
void SetPtr( const T* pT )
{
SetRawPtr( pT );
}
// FIXME: Should these be in a 'CResourceWritablePointer' subclass?
// There are plenty of cases where we know that a CResourcePointer should be read-only
public:
FORCEINLINE T* GetUncheckedPtr()
{
// assumes non-null; returns garbage if this is a null pointer
Assert( m_nOffset != 0 );
byte *ptr = ResolveOffsetFast( &m_nOffset );
return ( T* )ptr;
}
FORCEINLINE T* GetPtr()
{
byte *ptr = ResolveOffset( &m_nOffset );
return ( T* )ptr;
}
FORCEINLINE operator T*()
{
return GetPtr();
}
FORCEINLINE T* operator->()
{
return GetPtr();
}
public:
void Unsafe_OutOfBoundsAllocate()
{
SetPtr( new T() );
}
void Unsafe_OutOfBoundsFree()
{
delete GetPtr();
}
void SwapBytes()
{
m_nOffset = DWordSwapC( m_nOffset );
}
};
// never construct this - only the Resource stream may construct or load data that contains ResourceArray or ResourcePointer; use LockedResource or naked pointer or CUtlBuffer or something like that instead
class CResourceArrayBase
{
public:
CResourceArrayBase()
{
m_nOffset = 0;
m_nCount = 0;
}
bool operator == ( int zero )const
{
AssertDbg( zero == 0 );
return m_nOffset == zero;
}
bool IsNull()const
{
return m_nOffset == 0;
}
int32 NotNull()const
{
return m_nOffset;
}
const byte* GetRawPtr() const
{
// validate
return ResolveOffset( &m_nOffset );
}
byte* GetRawPtr()
{
// validate
return ResolveOffset( &m_nOffset );
}
int Count() const
{
return m_nCount;
}
void WriteDirect( int nCount, void *pData )
{
if ( pData == NULL )
{
AssertDbg( nCount == 0 );
m_nOffset = 0;
m_nCount = 0;
}
else
{
m_nOffset = ((intp)pData) - (intp)&m_nOffset;
m_nCount = nCount;
}
}
void SwapMemberBytes()
{
m_nCount = DWordSwapC( m_nCount );
m_nOffset = DWordSwapC( m_nOffset );
}
private:
CResourceArrayBase(const CResourceArrayBase&rThat ){} // private: we don't want to recompute offsets every time we copy a structure
protected:
int32 m_nOffset;
uint32 m_nCount;
};
template < typename T >
class CResourceArray: public CResourceArrayBase
{
public:
CResourceArray(): CResourceArrayBase() {}
private:
CResourceArray( const CResourceArray<T>&rThat ){} // private: we don't want to recompute offsets every time we copy a structure
public:
const T& operator []( int nIndex ) const
{
AssertDbg( (uint)nIndex < m_nCount );
return this->GetPtr()[nIndex];
}
T& operator []( int nIndex )
{
AssertDbg( (uint)nIndex < m_nCount );
return this->GetPtr()[nIndex];
}
const T& Element( int nIndex ) const
{
AssertDbg( (uint)nIndex < m_nCount );
return this->GetPtr()[nIndex];
}
T& Element( int nIndex )
{
AssertDbg( (uint)nIndex < m_nCount );
return this->GetPtr()[nIndex];
}
CResourceArray<T>& operator = ( const CLockedResource<T> & lockedResource )
{
m_nOffset = ( lockedResource.Count() ) ? ( ((intp)(const T*)lockedResource) - (intp)&m_nOffset ) : 0;
m_nCount = lockedResource.Count();
return *this;
}
CResourceArray<T>& operator = ( const CResourceArray<T> & that )
{
m_nOffset = ( that.Count() ) ? ( ((intp)(const T*)that.GetPtr()) - (intp)&m_nOffset ) : 0;
m_nCount = that.Count();
return *this;
}
const T* GetPtr() const
{
return ( const T* )GetRawPtr();
}
T* GetPtr()
{
return ( T* )GetRawPtr();
}
const T* Base() const
{
return ( const T* )GetRawPtr();
}
T* Base()
{
return ( T* )GetRawPtr();
}
bool IsEmpty() const
{
return m_nCount == 0;
}
operator CLockedResource<T> () {return CLockedResource<T>( GetPtr(), Count() ) ; }
// Temporary functions
void Unsafe_OutOfBoundsAllocate( int nCount )
{
const T* pAlloc = new T[nCount];
m_nOffset = ((intp)(const T*)pAlloc) - (intp)&m_nOffset;
m_nCount = nCount;
}
void Unsafe_OutOfBoundsPurgeAndFreeRPs()
{
for ( uint32 i = 0; i < m_nCount; ++i )
{
Element(i).Unsafe_OutOfBoundsFree();
}
delete[] GetPtr();
}
// Remove all the NULL pointers from this resource array and shorten it (without changing any allocations)
// (assumes that the elements of the array can be equality-tested with NULL)
inline void CoalescePointerArrayInPlace()
{
int nValidElements = 0;
int nArrayLen = Count();
T* pBase = GetPtr();
for ( int i = 0; i < nArrayLen; ++i )
{
if ( pBase[i] == 0 )
continue;
if ( nValidElements != i )
{
pBase[nValidElements].SetRawPtr( pBase[i].GetRawPtr() );
}
nValidElements++;
}
m_nCount = nValidElements;
}
// Enable support for range-based loops in C++ 11
inline T* begin()
{
return GetPtr();
}
inline const T* begin() const
{
return GetPtr( );
}
inline T* end()
{
return GetPtr() + m_nCount;
}
inline const T* end() const
{
return GetPtr( ) + m_nCount;
}
};
//////////////////////////////////////////////////////////////////////////
// this class may be useful at runtime to use fast serialize interface (without data linking)
//
class CResourceStream
{
public:
// Constructor, destructor
CResourceStream( );
virtual ~CResourceStream( ) {} // make sure to implement proper cleanup in derived classes
// Methods used to allocate space in the stream
// just use Allocate<uint8>(100) to simply allocate 100 bytes of crap
void *AllocateBytes( uint nCount );
template <typename T> CLockedResource<T> Allocate( uint count = 1 );
template <typename T> CUnlockedResource<T> AllocateUnaligned( uint count = 1 );
// Methods that write data into the stream
template <typename T> CLockedResource<T> Write( const T &x );
template <typename T> CUnlockedResource<T> WriteUnaligned( const T &x );
CLockedResource<float> WriteFloat( float x );
CLockedResource<uint64> WriteU64( uint64 x );
CLockedResource<uint32> WriteU32( uint32 x );
CLockedResource<uint16> WriteU16( uint16 x );
CLockedResource<uint8> WriteByte( byte x );
CLockedResource<char> WriteString( const char *pString );
CLockedResource<char> WriteStringMaxLen( const char *pString, int nMaxLen ); // will never read beyond pString[nMaxLen-1] and will force-null-terminate if necessary
// Methods to force alignment of the next data written into the stream
void Align( uint nAlignment, int nOffset = 0 );
void AlignPointer();
// How much data have we written into the stream?
uint32 Tell() const;
uint32 Tell( const void * pPast )const;
const void *TellPtr() const;
void Rollback( uint32 nPreviousTell );
void Rollback( const void *pPreviousTell );
void* Compile( );
template <class Memory>
void* CompileToMemory( Memory &memory );
uint GetTotalSize() const;
void Barrier() {} // no pointers crossing barriers allowed! all pointers are invalidated
void PrintStats();
void ClearStats();
// This is the max alignment ever used within the stream
uint GetStreamAlignment() const;
void* GetDataPtr( uint Offset = 0 );
template <typename T> T* GetDataPtrTypeAligned( uint Offset );
void Clear();
protected:
void EnsureAvailable( uint nAddCapacity )
{
Assert( nAddCapacity < 0x40000000 ); // we don't support >1Gb of data yet
uint nNewCommit = m_nUsed + nAddCapacity;
if ( nNewCommit > m_nCommitted )
{
Commit( nNewCommit ); // Commit is only called when necessary, as it may be expensive
}
}
// the only logic entry the derived class needs to reimplement, besides constructor+destructor pair.
// depending on how expensive it is to call this function, it may commit (allocate) large chunks of extra memory, that's totally ok
virtual void Commit( uint nNewCommit ) = 0;
template <typename T> friend class CUnlockedResource;
protected:
uint8 *m_pData; // the reserved virtual address space address; or just the start of allocated block of memory if virtual memory is not being used
uint m_nCommitted; // how much memory was already committed (or allocated, in case no virtual memory is being used)
uint m_nUsed; // this is the amount of currently used/allocated data, in bytes; may be unaligned
uint m_nAlignBits; // the ( max alignment - 1 ) of the current block of data
uint m_nMaxAlignment;
};
class CResourceStreamVM: public CResourceStream
{
public:
// Constructor, destructor
CResourceStreamVM( uint nReserveSize = 16 * 1024 * 1024 );
virtual ~CResourceStreamVM( ) OVERRIDE;
void CloneStream( CResourceStreamVM& copyFromStream );
protected:
virtual void Commit( uint nNewCommit ) OVERRIDE;
void ReserveVirtualMemory( uint nAddressSize );
void ReleaseVirtualMemory( );
enum
{
COMMIT_STEP = 64 * 1024
};
protected:
uint m_nReserved; // the reserved virtual address space for the block of data
};
// use this class to create resources efficiently in runtime using your own allocator
// supply a fixed buffer; it belongs to the caller
class CResourceStreamFixed: public CResourceStream
{
private:
bool m_bOwnMemory;
public:
CResourceStreamFixed( uint nPreallocateDataSize );// NOTE: the preallocated data is Zeroed in this constructor
CResourceStreamFixed( void *pPreallocatedData, uint nPreallocatedDataSize ); // NOTE: the preallocated data is Zeroed in this constructor
virtual ~CResourceStreamFixed() OVERRIDE;
int GetSlack(); // remaining bytes
virtual void Commit( uint nNewCommit );
};
class CResourceStreamGrowable: public CResourceStream
{
public:
CResourceStreamGrowable( uint nReserveDataSize );
~CResourceStreamGrowable( );
virtual void Commit( uint nNewCommit );
uint8 *Detach( )
{
uint8 *pData = m_pData;
m_pData = 0;
m_nCommitted = 0;
m_nUsed = 0;
m_pData = NULL;
return pData;
}
};
class CLockedResourceAutoAggregator
{
protected:
CResourceStreamVM *m_pStream;
const void * m_pTellStart;
uint m_nTellStart;
public:
CLockedResourceAutoAggregator( CResourceStreamVM *pStream, const void * pTellStart )
{
m_pStream = pStream;
m_pTellStart = pTellStart;
m_nTellStart = pStream->Tell( pTellStart );
}
CLockedResource<uint8> GetAggregate()
{
return CLockedResource<uint8>( ( uint8* )m_pTellStart, m_pStream->Tell() - m_nTellStart );
}
};
//-----------------------------------------------------------------------------
// Specialization for strings
//-----------------------------------------------------------------------------
class CResourceString: public CResourcePointer<char>
{
public:
CResourceString& operator = ( const CLockedResource<char> & lockedCharResource )
{
SetPtr( (const char*)lockedCharResource );
return *this;
}
CResourceString& operator = ( const CResourcePointerBase & lockedCharResource )
{
SetPtr( ( const char* )lockedCharResource.GetRawPtr() );
return *this;
}
// empty strings can be serialized as a null pointer (instead of a pointer to '\0')
const char* GetPtr() const
{
if ( GetRawPtr() == NULL )
{
return "";
}
else
{
return ( const char* )GetRawPtr();
}
}
char* GetPtr()
{
if ( GetRawPtr() == NULL )
{
return ( char* )"";
}
else
{
return ( char* )GetRawPtr();
}
}
operator const char* ()const
{
if ( GetRawPtr() == NULL )
{
return "";
}
else
{
return ( char* )GetRawPtr();
}
}
void Unsafe_OutOfBoundsCopy( const char* pStr )
{
int nLen = V_strlen(pStr);
char* pAlloc = new char[nLen+1];
V_strcpy( pAlloc, pStr );
SetPtr( pAlloc );
}
bool IsEmpty() const
{
return IsNull() || !*GetUncheckedRawPtr();
}
private:
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Disable comparison operators for ResourceStrings, otherwise they'll
// be implicitly converted to char* (we don't want to actually implement
// these because it's ambiguous whether it's case-sensitive or not.
bool operator==( const CResourceString &rhs ) const;
bool operator!=( const CResourceString &rhs ) const;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
template <typename T>
inline CLockedResource<T> CResourceStream::Allocate( uint nCount )
{
// TODO: insert reflection code here
uint nAlignment = VALIGNOF( T );
Align( nAlignment );
T *ptr = AllocateUnaligned< T >( nCount );
// Construct
for ( uint i = 0; i < nCount; i++ )
{
Construct< T >( &ptr[ i ] );
}
return CLockedResource<T>( ptr, nCount );
}
template <typename T>
inline CUnlockedResource<T> CResourceStream::AllocateUnaligned( uint nCount )
{
// Allocate
return CUnlockedResource< T >( this, ( T* )AllocateBytes( nCount * sizeof( T ) ), nCount );
}
inline void CResourceStream::AlignPointer()
{
Align( sizeof( intp ) );
}
template <typename T>
inline CUnlockedResource<T> CResourceStream::WriteUnaligned( const T &x )
{
CUnlockedResource<T> pMemory = AllocateUnaligned<T>( );
V_memcpy( pMemory, &x, sizeof( T ) );
return pMemory;
}
template <typename T>
inline CLockedResource<T> CResourceStream::Write( const T &x )
{
CLockedResource<T> memory = Allocate<T>();
*memory = x;
return memory;
}
inline CLockedResource<float> CResourceStream::WriteFloat( float x )
{
return Write( x );
}
inline CLockedResource<uint64> CResourceStream::WriteU64( uint64 x )
{
return Write( x );
}
inline CLockedResource<uint32> CResourceStream::WriteU32( uint32 x )
{
return Write( x );
}
inline CLockedResource<uint16> CResourceStream::WriteU16( uint16 x )
{
return Write( x );
}
inline CLockedResource<uint8> CResourceStream::WriteByte( byte x )
{
return Write( x );
}
inline CLockedResource<char> CResourceStream::WriteString( const char *pString )
{
int nLength = pString ? V_strlen( pString ) : 0;
if ( nLength == 0 )
{
return CLockedResource<char>( NULL, 0 );
}
else
{
CLockedResource<char> memory = Allocate<char>(nLength+1);
memcpy( (char*)memory, pString, nLength+1 );
return memory;
}
}
inline CLockedResource<char> CResourceStream::WriteStringMaxLen( const char *pString, int nMaxLen )
{
int nStrLen = 0;
while ( pString && nStrLen < nMaxLen && pString[nStrLen] != '\0' )
{
nStrLen++;
}
if ( nStrLen == 0 )
{
return CLockedResource<char>( NULL, 0 );
}
else
{
CLockedResource<char> memory = Allocate<char>( nStrLen + 1 ); // +1 for null term
memcpy( (char*)memory, pString, nStrLen );
((char*)memory)[nStrLen] = '\0';
return memory;
}
}
inline uint32 CResourceStream::Tell() const
{
return m_nUsed;
}
inline void CResourceStream::Rollback( uint32 nPreviousTell )
{
Assert( nPreviousTell <= m_nUsed );
m_nUsed = nPreviousTell;
}
inline void CResourceStream::Rollback( const void *pPreviousTell )
{
Assert( pPreviousTell > m_pData && pPreviousTell <= m_pData + m_nUsed );
m_nUsed = ( ( uint8* ) pPreviousTell ) - m_pData;
}
inline uint32 CResourceStream::Tell( const void * pPast )const
{
// we do not reallocate the reserved memory , so the pointers do not invalidate and m_pData stays the same, and all absolute addresses stay the same in memory
uint nTell = uintp( pPast ) - uintp( m_pData );
AssertDbg( nTell <= m_nUsed );
return nTell;
}
inline const void *CResourceStream::TellPtr() const
{
return m_pData + m_nUsed;
}
inline void* CResourceStream::Compile( )
{
return m_pData;
}
template< class Memory >
inline void* CResourceStream::CompileToMemory( Memory &memory )
{
memory.Init( 0, GetTotalSize() );
V_memcpy( memory.Base(), Compile(), GetTotalSize() );
return memory.Base();
}
inline uint CResourceStream::GetTotalSize() const
{
return m_nUsed;
}
inline uint CResourceStream::GetStreamAlignment() const
{
return m_nMaxAlignment;
}
inline void* CResourceStream::GetDataPtr( uint nOffset )
{
if ( nOffset > m_nUsed )
{
return NULL;
}
else
{
return m_pData + nOffset;
}
}
inline void CResourceStream::Clear()
{
V_memset( m_pData, 0, m_nCommitted );
m_nUsed = 0;
}
template <typename T>
inline T* CResourceStream::GetDataPtrTypeAligned( uint Offset )
{
uint nAlignment = VALIGNOF( T );
Offset += ( ( 0 - Offset ) & ( nAlignment - 1 ) );
return ( T* ) GetDataPtr( Offset );
}
template <typename T>
inline const T* OffsetPointer( const T *p, intp nOffsetBytes )
{
return p ? ( const T* )( intp( p ) + nOffsetBytes ) : NULL;
}
template <typename T>
inline T* ConstCastOffsetPointer( const T *p, intp nOffsetBytes )
{
return p ? ( T* ) ( intp( p ) + nOffsetBytes ) : NULL;
}
template < typename T >
inline CLockedResource< T > CloneArray( CResourceStream *pStream, const T *pArray, uint nCount )
{
if ( nCount > 0 && pArray )
{
CLockedResource< T > pOut = pStream->Allocate< T >( nCount );
V_memcpy( pOut, pArray, nCount * sizeof( T ) );
return pOut;
}
else
{
return CLockedResource< T >( );
}
}
inline int CResourceStreamFixed::GetSlack( )
{
return m_nCommitted - m_nUsed;
}
template < typename T >
CUnlockedResource< T >::CUnlockedResource( CResourceStream *pStream, T *pData, uint nCount ):
m_pStream( pStream ),
m_nOffset( ( ( uint8* ) pData ) - pStream->m_pData ),
m_nCount( nCount )
{
AssertDbg( ( ( uint8* ) pData ) >= pStream->m_pData && ( ( uint8* ) ( pData + nCount ) <= pStream->m_pData + pStream->m_nUsed ) );
AssertDbg( m_nOffset <= pStream->m_nUsed && m_nOffset + nCount * sizeof( T ) <= pStream->m_nUsed );
}
template < typename T >
inline T* CUnlockedResource< T >::GetPtr( )
{
return ( T* )m_pStream->GetDataPtr( m_nOffset );
}
template < typename T >
inline const T* CUnlockedResource< T >::GetPtr( )const
{
return ( const T * )m_pStream->GetDataPtr( m_nOffset );
}
#endif // RESOURCESTREAM_H

View File

@@ -0,0 +1,256 @@
//===== Copyright c 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Describes our resource format. Resource files consist of two files:
// The first is a resource descriptor file containing various blocks of
// arbitrary data, including a resource dictionary describing raw data which
// is stored in a second, parallel file.
//
// $NoKeywords: $
//===========================================================================//
#ifndef RESOURCETYPE_H
#define RESOURCETYPE_H
#pragma once
#include "resourcefile/schema.h"
#include "tier0/threadtools.h"
#include "tier2/tier2.h" // g_nResourceFrameCount defn
//-----------------------------------------------------------------------------
// Enum definitions
//-----------------------------------------------------------------------------
schema enum ResourceTypeEngine_t
{
RESOURCE_TYPE_NONE = -1,
//! schemaName = "TextureBits_t"
//! className = "CTextureBits"
//! handlePrefix = "RenderTexture2"
RESOURCE_TYPE_TEXTURE = 0,
//! schemaName = "ParticleSystemDefinition_t"; handlePrefix = "ParticleSystem"
RESOURCE_TYPE_PARTICLE_SYSTEM,
//! schemaName = "Sheet_t"; className = "CSheet"; handlePrefix = "Sheet"
RESOURCE_TYPE_SHEET,
//! schemaName = "RenderBufferBits_t"; className = "CRenderBufferBits"; handlePrefix = "RenderBuffer"
RESOURCE_TYPE_RENDER_BUFFER,
//! schemaName = "Renderable_t"; className = "CRenderable"; handlePrefix = "Renderable"
RESOURCE_TYPE_RENDERABLE,
//! schemaName = "WorldNode_t"; className = "CWorldNode"; handlePrefix = "WorldNode"
RESOURCE_TYPE_WORLD_NODE,
//! schemaName = "World_t"; className = "CWorld"; handlePrefix = "World"
RESOURCE_TYPE_WORLD,
RESOURCE_TYPE_COUNT,
RESOURCE_FIRST_MOD_TYPE = 0x80000000,
};
//-----------------------------------------------------------------------------
// Resource type.. typedeffed because we can have engine or mod types
//-----------------------------------------------------------------------------
typedef int ResourceType_t;
//-----------------------------------------------------------------------------
// Resource binding flags
//-----------------------------------------------------------------------------
enum ResourceBindingFlags_t
{
RESOURCE_BINDING_CACHED = 0x1,
RESOURCE_BINDING_ERROR = 0x2,
RESOURCE_BINDING_PERMANENT = 0x4, // Will never be uncached
RESOURCE_BINDING_ANONYMOUS = 0x8, // Will never be in the map
RESOURCE_BINDING_FIRST_UNUSED_FLAG = 0x10,
};
//-----------------------------------------------------------------------------
// Resource binding
// NOTE: This is a private implementational detail of the resource system
// and should never be used directly by client code
//-----------------------------------------------------------------------------
struct ResourceBindingBase_t
{
void *m_pData; // Needs to be a pointer type or a handle (RenderTextureHandle_t etc)
mutable uint32 m_nLastBindFrame; // When's the last frame this was used?
uint32 m_nFlags; // Flags
mutable CInterlockedInt m_nRefCount; // How many resource pointers point to this resource?
};
template< class T >
struct ResourceBinding_t : public ResourceBindingBase_t
{
template< class S > friend class CStrongHandle;
template< class S > friend const S* ResourceHandleToData( const ResourceBinding_t< S > *hResource, bool bUnsafe );
template< class S > friend int ResourceAddRef( const ResourceBinding_t< S > *hResource );
template< class S > friend int ResourceRelease( const ResourceBinding_t< S > *hResource );
};
// This is a 'weak reference' and can only be used if it's referenced
// somewhere and if it's the appropriate frame
template< class T > FORCEINLINE const T* ResourceHandleToData( const ResourceBinding_t< T > *hResource, bool bUnsafe = false )
{
Assert( !hResource || bUnsafe || hResource->m_nRefCount > 0 );
Assert( !hResource || bUnsafe || ( hResource->m_nFlags & RESOURCE_BINDING_PERMANENT ) || ( hResource->m_nLastBindFrame == g_nResourceFrameCount ) );
return hResource ? ( const T* )hResource->m_pData : NULL;
}
template< class T > FORCEINLINE int ResourceAddRef( const ResourceBinding_t< T > *hResource )
{
return ++hResource->m_nRefCount;
}
template< class T > FORCEINLINE int ResourceRelease( const ResourceBinding_t< T > *hResource )
{
Assert( hResource->m_nRefCount > 0 );
return --hResource->m_nRefCount;
}
//-----------------------------------------------------------------------------
// Declares a resource pointer
//-----------------------------------------------------------------------------
typedef const ResourceBindingBase_t *ResourceHandle_t;
#define RESOURCE_HANDLE_INVALID ( (ResourceHandle_t)0 )
//-----------------------------------------------------------------------------
// Forward declaration
//-----------------------------------------------------------------------------
template< class T > class CStrongHandle;
//-----------------------------------------------------------------------------
// Helpers used to define resource types + associated structs + dm elements
//-----------------------------------------------------------------------------
template< class ResourceStruct_t >
struct ResourceTypeInfo_t
{
enum { RESOURCE_TYPE = RESOURCE_TYPE_NONE };
typedef ResourceStruct_t Schema_t;
typedef ResourceStruct_t Class_t;
static ResourceType_t ResourceType() { return RESOURCE_TYPE_NONE; }
static const char *SchemaName() { return "unknown"; }
static const char *ClassName() { return "unknown"; }
};
#define DEFINE_RESOURCE_TYPE( _schema, _resourceType ) \
template <> struct ResourceTypeInfo_t< _schema > \
{ \
enum { RESOURCE_TYPE = _resourceType }; \
typedef _schema Schema_t; \
typedef _schema Class_t; \
static ResourceType_t ResourceType() { return _resourceType; } \
static const char *SchemaName() { return #_schema; } \
static const char *ClassName() { return #_schema; } \
};
#define DEFINE_RESOURCE_CLASS_TYPE( _schema, _class, _resourceType ) \
template <> struct ResourceTypeInfo_t< _schema > \
{ \
enum { RESOURCE_TYPE = _resourceType }; \
typedef _schema Schema_t; \
typedef _class Class_t; \
static ResourceType_t ResourceType() { return _resourceType; } \
static const char *SchemaName() { return #_schema; } \
static const char *ClassName() { return #_class; } \
}; \
template <> struct ResourceTypeInfo_t< _class > \
{ \
enum { RESOURCE_TYPE = _resourceType }; \
typedef _schema Schema_t; \
typedef _class Class_t; \
static ResourceType_t ResourceType() { return _resourceType; } \
static const char *SchemaName() { return #_schema; } \
static const char *ClassName() { return #_class; } \
}; \
//-----------------------------------------------------------------------------
// This contains an external resource reference
//-----------------------------------------------------------------------------
typedef const struct ResourceBindingBase_t *ResourceHandle_t;
template <typename T>
class CResourceReference
{
private:
union
{
int64 m_nResourceId; // On-disk format
ResourceHandle_t m_hResource; // Run-time format. ResourceSystem is responsible for conversion
};
public:
// Tool-time only
void WriteReference( uint32 nId )
{
m_nResourceId = nId;
}
void operator=( uint32 nId )
{
m_nResourceId = nId;
}
bool operator==( int nZero ) const
{
Assert( nZero == 0 );
return m_nResourceId == 0;
}
bool IsNull()const
{
return m_nResourceId == 0;
}
const ResourceBinding_t< T > *GetHandle() const
{
// validate
Assert( g_pResourceSystem );
const ResourceBinding_t< T > *pBinding = (const ResourceBinding_t< T > *)m_hResource;
pBinding->m_nLastBindFrame = g_nResourceFrameCount;
return pBinding;
}
const T* GetPtr() const
{
// validate
Assert( g_pResourceSystem );
const ResourceBinding_t< T > *pBinding = (const ResourceBinding_t< T > *)m_hResource;
pBinding->m_nLastBindFrame = g_nResourceFrameCount;
return ResourceHandleToData( pBinding );
}
operator const T* ()const
{
return GetPtr();
}
const T* operator->() const
{
return GetPtr();
}
// NOTE: The following two methods should only be used during resource fixup on load
uint32 GetResourceId() const
{
return m_nResourceId;
}
void SetHandle( ResourceHandle_t hResource )
{
m_hResource = hResource;
}
};
#endif // RESOURCETYPE_H

View File

@@ -0,0 +1,201 @@
#ifndef SCHEMA_H_
#define SCHEMA_H_
#include "basetypes.h" // for 'schema' define
#include "resourcefile/resourcestream.h"
#include "resourcefile/resourcefile.h"
#include "resourcefile/resourcetype.h"
class CResourceStructIntrospection;
#ifdef COMPILING_SCHEMA
#define INTERNAL_SCHEMA_CLASS_MARKER_DATA `__schema_class_marker_data__`
#define INTERNAL_SCHEMA_CLASS_MARKER_VIRTUAL `__schema_class_marker_virtual__`
#define INTERNAL_SCHEMA_CLASS_MARKER_ABSTRACT `__schema_class_marker_abstract__`
#define INTERNAL_SCHEMA_CLASS_MARKER_SIMPLE `__schema_class_marker_simple__`
#else
#define INTERNAL_SCHEMA_CLASS_MARKER_DATA
#define INTERNAL_SCHEMA_CLASS_MARKER_VIRTUAL
#define INTERNAL_SCHEMA_CLASS_MARKER_ABSTRACT
#define INTERNAL_SCHEMA_CLASS_MARKER_SIMPLE
#endif
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Pay no attention to the code behind the curtain
#define DECLARE_SCHEMA_CLASS_HELPER( _className, _bindingType ) \
friend class _bindingType < _className >; \
friend class CSchemaVerificationFor##_className; \
public: \
static _bindingType < _className > s_##_className##SchemaBinding; \
static const CResourceStructIntrospection *Schema_StaticBinding( ) { return (s_##_className##SchemaBinding).GetIntrospection(); }
#define DECLARE_SCHEMA_VIRTUAL_CLASS_HELPER( _className, _bindingType ) \
DECLARE_SCHEMA_CLASS_HELPER( _className, _bindingType ); \
public: \
virtual const CSchemaClassBindingBase *Schema_GetBinding( ) const { return &s_##_className##SchemaBinding; } \
const CResourceStructIntrospection *Schema_GetIntrospection( ) const { return Schema_GetBinding()->GetIntrospection(); }
#define DECLARE_SCHEMA_PLAIN_CLASS_HELPER( _className, _bindingType ) \
DECLARE_SCHEMA_CLASS_HELPER( _className, _bindingType ); \
public: \
const CSchemaClassBindingBase *Schema_GetBinding( ) const { return &s_##_className##SchemaBinding; } \
const CResourceStructIntrospection *Schema_GetIntrospection( ) const { return Schema_GetBinding()->GetIntrospection(); }
#define DEFINE_SCHEMA_CLASS_HELPER( _className, _bindingType ) \
_bindingType < _className > _className :: s_##_className##SchemaBinding( #_className );
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Data Classes (no vtable)
#define DECLARE_SCHEMA_DATA_CLASS( _className ) \
INTERNAL_SCHEMA_CLASS_MARKER_DATA \
DECLARE_SCHEMA_PLAIN_CLASS_HELPER( _className, CSchemaClassBinding )
#define DEFINE_SCHEMA_DATA_CLASS( _className ) DEFINE_SCHEMA_CLASS_HELPER( _className, CSchemaClassBinding )
///////////////////////////////////////
// Virtual Classes
#define DECLARE_SCHEMA_VIRTUAL_CLASS( _className ) \
INTERNAL_SCHEMA_CLASS_MARKER_VIRTUAL \
DECLARE_SCHEMA_VIRTUAL_CLASS_HELPER( _className, CSchemaClassBinding )
#define DEFINE_SCHEMA_VIRTUAL_CLASS( _className ) DEFINE_SCHEMA_CLASS_HELPER( _className, CSchemaClassBinding )
///////////////////////////////////////
// Abstract Classes
#define DECLARE_SCHEMA_ABSTRACT_CLASS( _className ) \
INTERNAL_SCHEMA_CLASS_MARKER_ABSTRACT \
DECLARE_SCHEMA_VIRTUAL_CLASS_HELPER( _className, CSchemaAbstractClassBinding )
#define DEFINE_SCHEMA_ABSTRACT_CLASS( _className ) DEFINE_SCHEMA_CLASS_HELPER( _className, CSchemaAbstractClassBinding )
///////////////////////////////////////
// Simple Classes
// For classes where you don't want to use a DEFINE_ macro
// - Only works for classes with no vtable.
// - If unserialized, it will be memzeroed rather than constructed
#define DECLARE_SCHEMA_SIMPLE_CLASS( _name ) \
INTERNAL_SCHEMA_CLASS_MARKER_SIMPLE \
const CResourceStructIntrospection *Schema_GetIntrospection( ) const { return g_pResourceSystem->FindStructIntrospection( #_name ); }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/*
template<class T> void Serialize( const T* pObj )
{
const CResourceStructIntrospection *pIntrospection = pObj ? pObj->Schema_GetIntrospection() : NULL;
SerializeGeneric( (const void*)pObj, pIntrospection );
}
template<class T> void Print( const T* pObj )
{
const CResourceStructIntrospection *pIntrospection = pObj ? pObj->Schema_GetIntrospection() : NULL;
PrintGeneric( (const void*)pObj, pIntrospection );
}
void SerializeGeneric( const void *pData, const CResourceStructIntrospection *pIntrospection );
void PrintGeneric( const void *pData, const CResourceStructIntrospection *pIntrospection );
*/
//////////////////////////////////////////////////////////////////////////
class CSchemaClassBindingBase
{
public:
CSchemaClassBindingBase( const char* pClassName ):
m_pClassName(pClassName),
m_pIntrospection(NULL)
{
// Hook into the local class binding list
m_pNextBinding = sm_pClassBindingList;
sm_pClassBindingList = this;
}
inline const char* GetName() const
{
return m_pClassName;
}
virtual void ConstructInPlace( void* pMemory ) const = 0;
virtual void DestructInPlace( void* pMemory ) const = 0;
virtual int GetSize() const = 0;
const CResourceStructIntrospection *GetIntrospection() const;
static void Install();
protected:
const char *m_pClassName;
mutable const CResourceStructIntrospection *m_pIntrospection;
CSchemaClassBindingBase *m_pNextBinding;
static CSchemaClassBindingBase *sm_pClassBindingList;
};
template<class TSchemaClass> class CSchemaClassBinding: public CSchemaClassBindingBase
{
public:
CSchemaClassBinding( const char* pClassName ):
CSchemaClassBindingBase( pClassName )
{
// nop
}
virtual void ConstructInPlace( void* pMemory ) const
{
new(pMemory) TSchemaClass;
}
virtual void DestructInPlace( void* pMemory ) const
{
((TSchemaClass*)(pMemory))->~TSchemaClass();
}
virtual int GetSize() const
{
return sizeof(TSchemaClass);
}
};
template<class TSchemaClass> class CSchemaAbstractClassBinding: public CSchemaClassBindingBase
{
public:
CSchemaAbstractClassBinding( const char* pClassName ):
CSchemaClassBindingBase(pClassName)
{
// nop
}
virtual void ConstructInPlace( void* pMemory ) const
{
Error( "Cannot construct abstract class %s\n", m_pClassName );
}
virtual void DestructInPlace( void* pMemory ) const
{
Error( "Cannot destruct abstract class %s\n", m_pClassName );
}
virtual int GetSize() const
{
return sizeof(TSchemaClass);
}
};
#endif

View File

@@ -0,0 +1,42 @@
//-----------------------------------------------------------------------------
// Autogenerated by schema compiler, compiled May 22 2009 14:03:37
// Do not hand-edit or check in this file!!
//-----------------------------------------------------------------------------
#ifndef PARTICLES_G_H
#define PARTICLES_G_H
#ifdef COMPILER_MSVC
#pragma once
#endif
#include "resourcefile/schema.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct ParticleSystemDefinition_t;
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
//! dmeElementType = "DmeParticleSystemDefinition"
schema struct ParticleSystemDefinition_t
{
int32 max_particles;
int32 initial_particles;
CResourceString material;
float32 cull_radius;
CResourceArray< CResourceReference< ParticleSystemDefinition_t > > children;
};
DEFINE_RESOURCE_TYPE( ParticleSystemDefinition_t, RESOURCE_TYPE_PARTICLE_SYSTEM );
typedef const ResourceBinding_t< ParticleSystemDefinition_t > *HParticleSystem;
typedef CStrongHandle< ParticleSystemDefinition_t > HParticleSystemStrong;
#define PARTICLE_SYSTEM_HANDLE_INVALID ( (HParticleSystem)0 )
#endif // PARTICLES_G_H

View File

@@ -0,0 +1,55 @@
#ifndef RESOURCEEXTREFLIST_G_H
#define RESOURCEEXTREFLIST_G_H
#ifdef COMPILER_MSVC
#pragma once
#endif
#include "resourcefile/schema.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct ResourceExtRefList_t;
struct ResourceExtRefTypeList_t;
struct ResourceExtRefInfo_t;
//-----------------------------------------------------------------------------
// Enum definitions
//-----------------------------------------------------------------------------
schema enum ResourceExtRefistVersion_t
{
RESOURCE_EXT_REF_LIST_VERSION = 1,// (explicit)
};
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
//! resourceBlockType = "RERL"
schema struct ResourceExtRefList_t
{
uint32 m_nVersion;
CResourceArray< ResourceExtRefTypeList_t > m_ResourceTypeList;
CResourceArray< CResourcePointer< char > > m_FileNameList;
};
DEFINE_RESOURCE_BLOCK_TYPE( ResourceExtRefList_t, 'R', 'E', 'R', 'L' )
schema struct ResourceExtRefTypeList_t
{
uint32 m_nResourceType; // see ResourceType_t
CResourceArray< ResourceExtRefInfo_t > m_Resources;
};
schema struct ResourceExtRefInfo_t
{
uint32 m_nId; // see ResourceId_t
uint32 m_nFileNameIndex; // index into ResourceExtRefList_t::m_pFileNameList
CResourcePointer< char > m_pResourceName;
};
#endif // RESOURCEEXTREFLIST_G_H

View File

@@ -0,0 +1,54 @@
#ifndef RESOURCEIDLIST_G_H
#define RESOURCEIDLIST_G_H
#ifdef COMPILER_MSVC
#pragma once
#endif
#include "resourcefile/schema.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct ResourceIdList_t;
struct ResourceIdTypeList_t;
struct ResourceIdInfo_t;
//-----------------------------------------------------------------------------
// Enum definitions
//-----------------------------------------------------------------------------
schema enum ResourceIdListVersion_t
{
RESOURCE_ID_LIST_VERSION = 1,// (explicit)
};
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
//! resourceBlockType = "RIDL"
schema struct ResourceIdList_t
{
uint32 m_nVersion;
CResourceArray< ResourceIdTypeList_t > m_ResourceTypeList;
};
DEFINE_RESOURCE_BLOCK_TYPE( ResourceIdList_t, 'R', 'I', 'D', 'L' )
schema struct ResourceIdTypeList_t
{
uint32 m_nResourceType; // see ResourceType_t
CResourceArray< ResourceIdInfo_t > m_Resources;
};
schema struct ResourceIdInfo_t
{
uint32 m_nId; // see ResourceId_t
uint32 m_nEstimatedSize;
uint32 m_nPermanentDataSize;
CResourcePointer< void > m_PermanentData;
};
#endif // RESOURCEIDLIST_G_H

View File

@@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
// Autogenerated by schema compiler, compiled May 25 2009 11:22:37
// Do not hand-edit or check in this file!!
//-----------------------------------------------------------------------------
#ifndef SHEET_G_H
#define SHEET_G_H
#ifdef COMPILER_MSVC
#pragma once
#endif
#include "resourcefile/schema.h"
#include "rendersystem/schema/texture.g.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct Sheet_t;
struct SheetSequence_t;
struct SheetSequenceFrame_t;
struct SheetFrameImage_t;
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
schema struct Sheet_t
{
CResourceReference< TextureBits_t > m_hTexture;
CResourceArray< SheetSequence_t > m_Sequences;
};
class CSheet; // Forward declaration of associated runtime class
DEFINE_RESOURCE_CLASS_TYPE( Sheet_t, CSheet, RESOURCE_TYPE_SHEET );
typedef const ResourceBinding_t< CSheet > *HSheet;
typedef CStrongHandle< CSheet > HSheetStrong;
#define SHEET_HANDLE_INVALID ( (HSheet)0 )
schema struct SheetSequence_t
{
uint32 m_nId;
bool m_bClamp;
CResourceArray< SheetSequenceFrame_t > m_Frames;
float32 m_flTotalTime;
};
schema struct SheetSequenceFrame_t
{
float32 m_flDisplayTime;
CResourceArray< SheetFrameImage_t > m_Images;
};
schema struct SheetFrameImage_t
{
Vector2D uv[2];
};
#endif // SHEET_G_H

View File

@@ -0,0 +1,94 @@
#ifndef SCHEMA_VERIFICATION_H_
#define SCHEMA_VERIFICATION_H_
/*
inline int SchemaVerificationMemberSize( const char *pStructName, const char *pMemberName )
{
const CResourceStructIntrospection* pStructIntro = g_pResourceSystem->FindStructIntrospection( pStructName );
if ( !pStructIntro )
{
return -1;
}
const CResourceFieldIntrospection* pFieldIntro = pStructIntro->FindField( pMemberName );
if ( !pFieldIntro )
{
return -1;
}
return pFieldIntro->GetElementSize(0);
}
inline int SchemaVerificationMemberMemoryOffset( const char *pStructName, const char *pMemberName )
{
const CResourceStructIntrospection* pStructIntro = g_pResourceSystem->FindStructIntrospection( pStructName );
if ( !pStructIntro )
{
return -1;
}
const CResourceFieldIntrospection* pFieldIntro = pStructIntro->FindField( pMemberName );
if ( !pFieldIntro )
{
return -1;
}
return pFieldIntro->m_nInMemoryOffset;
}
*/
template<class T> class CTAlignmentOfHelper
{
T t; byte b; // the extra byte will force the compiler to pad it out by an additional alignment
};
#define schema_alignmentof( _className ) ( sizeof( CTAlignmentOfHelper<_className> ) - sizeof(_className) )
#define VERIFY_FOR_SCHEMA( _description, _expectedValue, _value ) \
{ \
if ( ( (_expectedValue) != (_value) ) ) \
{ \
Warning( "[FAILED] - " _description " - Expected %d but got %d\n", (_expectedValue), (_value) ); \
nLocalErrors++; \
} \
else \
{ \
Msg( "[ OK ] - " _description "\n" ); \
} \
}
#define VERIFY_SCHEMA_MEMBER_SIZE( _className, _memberName, _expectedSize ) \
VERIFY_FOR_SCHEMA( "Member size of " #_className "::" #_memberName, _expectedSize, sizeof( (( _className *)(0))->_memberName ) );
#define VERIFY_SCHEMA_MEMBER_MEMORY_OFFSET( _className, _memberName, _expectedOffset ) \
VERIFY_FOR_SCHEMA( "Member offset of " #_className "::" #_memberName, _expectedOffset, offsetof( _className , _memberName ) );
#define VERIFY_SCHEMA_TYPE_MEMORY_SIZE( _className, _expectedSize ) \
VERIFY_FOR_SCHEMA( "Struct size of " #_className, _expectedSize, sizeof( _className ) );
#define VERIFY_SCHEMA_TYPE_ALIGNMENT( _className, _expectedAlignment ) \
VERIFY_FOR_SCHEMA( "Struct alignment of " #_className, _expectedAlignment, schema_alignmentof( _className ) );
#define VERIFY_SCHEMA_MEMBER_FIX_ARRAY_ELEMENT_SIZE( _className, _memberName, _expectedSize ) \
VERIFY_FOR_SCHEMA( "Member array element size of " #_className "::" #_memberName, _expectedSize, sizeof( (( _className *)(0))->_memberName [ 0 ] ) );
#define VERIFY_SCHEMA_MEMBER_FIX_ARRAY_LENGTH( _className, _memberName, _expectedLength ) \
VERIFY_FOR_SCHEMA( "Member array length of " #_className "::" #_memberName, _expectedLength, ( sizeof( (( _className *)(0))->_memberName ) / sizeof( (( _className *)(0))->_memberName [ 0 ] ) ) );
#define BEGIN_SCHEMA_CLASS_VERIFY( _className ) \
class CSchemaVerificationFor##_className { \
public: static int DoVerify() { \
int nLocalErrors = 0; \
Msg( "Schema Verification: " #_className "\n" );
#define END_SCHEMA_CLASS_VERIFY( ) \
Msg( "\n\n" ); \
return nLocalErrors; \
} };
#define PERFORM_SCHEMA_CLASS_VERIFY( _className ) nErrors += CSchemaVerificationFor##_className::DoVerify();
#endif