431 lines
16 KiB
C++
431 lines
16 KiB
C++
//===== 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
|