Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
16 KiB

  1. //===== Copyright c 1996-2008, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Describes data which is used to help determine introspection
  4. // data for a resource file. Specifies which fields are what types, and
  5. // also specifies which fields refer to other types (by ptr or array).
  6. //
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #ifndef RESOURCEINTROSPECTION_H
  10. #define RESOURCEINTROSPECTION_H
  11. #pragma once
  12. #include "resourcefile/schema.h"
  13. #include "mathlib/vmatrix.h"
  14. #include "mathlib/ssemath.h"
  15. class CResourceIntrospection;
  16. //-----------------------------------------------------------------------------
  17. // Enum definitions
  18. //-----------------------------------------------------------------------------
  19. schema enum ResourceIntrospectionVersion_t
  20. {
  21. RESOURCE_INTROSPECTION_VERSION = 2,
  22. };
  23. // NOTE: If you add to this enum, you'll need to update s_pFieldTypes in resourceintrospection.cpp
  24. schema enum ResourceFieldType_t
  25. {
  26. RESOURCE_FIELD_TYPE_UNKNOWN,
  27. RESOURCE_FIELD_TYPE_RESOURCE_POINTER, // nFieldData = CResourcePointer<CResourceFieldTypeIntrospection> for pointed-to type
  28. RESOURCE_FIELD_TYPE_RESOURCE_ARRAY, // nFieldData = CResourcePointer<CResourceFieldTypeIntrospection> for element type
  29. RESOURCE_FIELD_TYPE_STRUCT, // nFieldData = hash(struct_name)
  30. RESOURCE_FIELD_TYPE_ENUM, // nFieldData = hash(enum_name)
  31. RESOURCE_FIELD_TYPE_RESOURCE_REFERENCE, // nFieldData = member of ResourceTypeEngine_t
  32. ////////////////////////
  33. // fields of these types are never serialized to disk
  34. RESOURCE_FIELD_TYPE_CHAR,
  35. RESOURCE_FIELD_TYPE_C_POINTER,
  36. ////////////////////////
  37. // ints and uints are always serialized at RESOURCE_PLAIN_INT_SERIALIZATION_SIZE bytes
  38. RESOURCE_FIELD_TYPE_INT,
  39. RESOURCE_FIELD_TYPE_UINT,
  40. // floats are always serialized at RESOURCE_PLAIN_FLOAT_SERIALIZATION_SIZE bytes
  41. RESOURCE_FIELD_TYPE_FLOAT,
  42. // simple types
  43. RESOURCE_FIELD_TYPE_INT8,
  44. RESOURCE_FIELD_TYPE_UINT8,
  45. RESOURCE_FIELD_TYPE_INT16,
  46. RESOURCE_FIELD_TYPE_UINT16,
  47. RESOURCE_FIELD_TYPE_INT32,
  48. RESOURCE_FIELD_TYPE_UINT32,
  49. RESOURCE_FIELD_TYPE_INT64,
  50. RESOURCE_FIELD_TYPE_UINT64,
  51. RESOURCE_FIELD_TYPE_FLOAT32,
  52. RESOURCE_FIELD_TYPE_FLOAT64,
  53. // common primitive types
  54. RESOURCE_FIELD_TYPE_TIME,
  55. RESOURCE_FIELD_TYPE_VECTOR2D,
  56. RESOURCE_FIELD_TYPE_VECTOR3D,
  57. RESOURCE_FIELD_TYPE_VECTOR4D,
  58. RESOURCE_FIELD_TYPE_QANGLE,
  59. RESOURCE_FIELD_TYPE_QUATERNION,
  60. RESOURCE_FIELD_TYPE_VMATRIX,
  61. RESOURCE_FIELD_TYPE_FLTX4,
  62. // TODO -
  63. RESOURCE_FIELD_TYPE_BOOL,
  64. RESOURCE_FIELD_TYPE_STRING,
  65. RESOURCE_FIELD_TYPE_VOID,
  66. RESOURCE_FIELD_TYPE_COUNT,
  67. };
  68. schema enum ResourceIntrospectionMetadataType_t
  69. {
  70. RESOURCE_META_TYPE_NAMEONLY,
  71. RESOURCE_META_TYPE_STRING,
  72. RESOURCE_META_TYPE_INT,
  73. RESOURCE_META_TYPE_FLOAT,
  74. };
  75. enum ResourceDataLayout_t
  76. {
  77. RESOURCE_DATA_LAYOUT_MEMORY,
  78. RESOURCE_DATA_LAYOUT_DISK,
  79. };
  80. enum IntrospectionCompatibilityType_t
  81. {
  82. INTROSPECTION_COMPAT_UNKNOWN,
  83. INTROSPECTION_COMPAT_IDENTICAL, // Disk and memory layout are the same
  84. INTROSPECTION_COMPAT_REQUIRES_SCATTER, // Identical structures, but disk layout != memory layout
  85. INTROSPECTION_COMPAT_REQUIRES_CONVERSION, // CRCs don't match, requires name-based, per-element conversion
  86. };
  87. const uint RESOURCE_PLAIN_INT_SERIALIZATION_SIZE = 4;
  88. const uint RESOURCE_PLAIN_FLOAT_SERIALIZATION_SIZE = 4;
  89. //-----------------------------------------------------------------------------
  90. // Structure id: it's generated by a hash of the structure name
  91. //-----------------------------------------------------------------------------
  92. typedef uint32 ResourceStructureId_t;
  93. #define RESOURCE_STRUCTURE_ID_INVALID ( (ResourceStructureId_t)0 )
  94. //-----------------------------------------------------------------------------
  95. // Information for resource fields
  96. //-----------------------------------------------------------------------------
  97. struct ResourceFieldProperties_t
  98. {
  99. // helper function
  100. static const ResourceFieldProperties_t* GetFieldProperties( ResourceFieldType_t nFieldType );
  101. const char * m_pTypeName;
  102. ResourceFieldType_t m_nFieldType;
  103. uint m_nMemorySize;
  104. uint m_nDiskSize; // 0 = not serialized to disk
  105. uint m_nAlignment;
  106. };
  107. //-----------------------------------------------------------------------------
  108. schema class CResourceFieldIntrospection
  109. {
  110. DECLARE_SCHEMA_DATA_CLASS( CResourceFieldIntrospection );
  111. // These methods are used for reading the data
  112. public:
  113. ResourceFieldType_t GetRootType() const;
  114. uint32 GetRootTypeData() const;
  115. ResourceFieldType_t ReadTypeChain( int nChainIndex ) const;
  116. // These methods are used for writing the data
  117. public:
  118. void SetFieldInfo( CResourceStream *pStream, const char *pFieldName, int nMemoryOffset, int nDiskOffset, int nArrayCount );
  119. void SetFieldInfo( CResourceStream *pStream, const CResourceFieldIntrospection *src );
  120. void SetFieldType( CResourceStream *pStream, const CUtlVector<ResourceFieldType_t>& TypeChain, uint32 nRootFieldData );
  121. // Introspection helper routines
  122. public:
  123. int GetElementMemorySize( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
  124. int GetElementDiskSize( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
  125. int GetElementSize( const ResourceDataLayout_t nDataLocation, int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
  126. int GetElementAlignment( int nTypeChainIndex, const CResourceIntrospection* pIntroDct ) const;
  127. public:
  128. CResourceString m_pFieldName;
  129. int16 m_nCount;
  130. int16 m_nInMemoryOffset;
  131. int16 m_nOnDiskOffset; // -1 means not serialized to disk
  132. // FIXME: The following representation will need to be tweaked;
  133. // Ideally none of the simple cases requires an allocation, (including ptr to struct)
  134. // and we do have 16 bits to work with due to alignment, plus 8 bits if we want to trim TypeChainCount.
  135. // If m_nTypeChainCount == 1, then m_nTypeChain is the field data
  136. // If m_nTypeChainCount > 1, m_nTypeChain is a CResourcePointer<uint32> to N uint32's
  137. // that looks like [FieldType, ..., FieldType, FieldData]
  138. // Examples of: [ m_nFieldType, m_nTypeChainCount ; m_nTypeChain ]
  139. // -------------------------------------------------------------------------------
  140. // Simple inline int8: [ RESOURCE_FIELD_TYPE_INT8, 1 ; 0 ]
  141. // Pointer to int8: [ RESOURCE_FIELD_TYPE_RESOURCE_POINTER, 2 ; RESOURCE_FIELD_TYPE_INT8 ]
  142. // Pointer to struct X: [ RESOURCE_FIELD_TYPE_RESOURCE_POINTER, 3 ; Ptr ]
  143. // where *Ptr = [RESOURCE_FIELD_TYPE_STRUCT; hash(X)]
  144. // Array of pointers to struct X: [ RESOURCE_FIELD_TYPE_DYNAMIC_ARRAY, 4 ; Ptr ]
  145. // where *Ptr = [RESOURCE_FIELD_TYPE_RESOURCE_POINTER; RESOURCE_FIELD_TYPE_STRUCT; hash(X)]
  146. int16 m_nTypeChainCount;
  147. int16 m_nFieldType;
  148. uint32 m_nTypeChain;
  149. };
  150. schema enum ResourceStructFlags_t
  151. {
  152. RESOURCE_STRUCT_HAS_VTABLE = 1,
  153. };
  154. schema class CResourceStructIntrospection
  155. {
  156. DECLARE_SCHEMA_DATA_CLASS( CResourceStructIntrospection );
  157. // These methods are used for reading the data
  158. public:
  159. // Iterate over all fields
  160. int GetFieldCount() const;
  161. const CResourceFieldIntrospection* GetField( int nIndex ) const;
  162. // Find a field
  163. const CResourceFieldIntrospection* FindField( const char *pFieldName ) const;
  164. bool HasVTable() const;
  165. // (to determine whether version up-conversion is necessary)
  166. // These methods are used for writing the data
  167. public:
  168. 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 );
  169. void SetStructInfo( CResourceStream *pStream, const CResourceStructIntrospection *src );
  170. void ComputeCRC( CResourceStream *pStream );
  171. void AllocateFields( CResourceStream *pStream, int nCount );
  172. CResourceFieldIntrospection* GetWritableField( int nIndex );
  173. public:
  174. uint32 m_nId;
  175. CResourceString m_pName;
  176. uint32 m_nCrc;
  177. uint16 m_nMemorySize;
  178. uint16 m_nDiskSize;
  179. uint16 m_nAlignment;
  180. uint32 m_nBaseStructId;
  181. uint32 m_nUncacheableStructId;
  182. uint8 m_ResourceBlockType[4]; // Specifies the block four-CC code if this structure is a type associated with a resource file block.
  183. CResourceString m_pResourceType; // Specifies the resource type if this structure is a type associated with a resource type.
  184. CResourceString m_pDmeElementType; // Specifies the DmElement type associated with this structure. Empty string means use CDmElement.
  185. CResourceArray< CResourceFieldIntrospection > m_FieldIntrospection;
  186. uint8 m_nStructFlags;
  187. };
  188. //-----------------------------------------------------------------------------
  189. // Enums
  190. //-----------------------------------------------------------------------------
  191. schema class CResourceEnumValueIntrospection
  192. {
  193. DECLARE_SCHEMA_DATA_CLASS( CResourceEnumValueIntrospection );
  194. // These methods are used for reading the data
  195. public:
  196. const char *GetName() const;
  197. int GetValue() const;
  198. // These methods are used for writing the data
  199. public:
  200. void SetEnumValueInfo( CResourceStream *pStream, const char *pEnumValueName, int32 nValue );
  201. public:
  202. CResourceString m_pEnumValueName;
  203. int32 m_nEnumValue;
  204. };
  205. schema class CResourceEnumIntrospection
  206. {
  207. DECLARE_SCHEMA_DATA_CLASS( CResourceEnumIntrospection );
  208. // These methods are used for reading the data
  209. public:
  210. // Iterate over all enum values
  211. int GetEnumValueCount() const;
  212. const CResourceEnumValueIntrospection* GetEnumValue( int nIndex ) const;
  213. CResourceEnumValueIntrospection* GetWritableEnumValue( int nIndex );
  214. // Find a field
  215. const CResourceEnumValueIntrospection* FindEnumValue( const char *pEnumValueName ) const;
  216. const char *FindEnumString( int nValue ) const;
  217. // Gets CRC information about the struct
  218. // (to determine whether version up-conversion is necessary)
  219. // These methods are used for writing the data
  220. public:
  221. void SetEnumName( CResourceStream *pStream, const char *pEnumName );
  222. void ComputeCRC( CResourceStream *pStream );
  223. void AllocateEnumValues( CResourceStream *pStream, int nCount );
  224. public:
  225. uint32 m_nId;
  226. CResourceString m_pName;
  227. uint32 m_nCrc;
  228. CResourceArray< CResourceEnumValueIntrospection > m_EnumValueIntrospection;
  229. };
  230. //-----------------------------------------------------------------------------
  231. // Typedefs
  232. //-----------------------------------------------------------------------------
  233. schema class CResourceTypedefIntrospection
  234. {
  235. DECLARE_SCHEMA_DATA_CLASS( CResourceTypedefIntrospection );
  236. // These methods are used for reading the data
  237. public:
  238. // These methods are used for writing the data
  239. public:
  240. void SetTypedefInfo( CResourceStream *pStream, const char *pTypedefName, const char *pTypedefType );
  241. public:
  242. uint32 m_nId;
  243. CResourceString m_pName;
  244. CResourceString m_pType;
  245. };
  246. //-----------------------------------------------------------------------------
  247. // Metadata
  248. //-----------------------------------------------------------------------------
  249. schema class CResourceIntrospectionMetadataElement
  250. {
  251. friend class CResourceIntrospectionMetadata;
  252. public:
  253. const char* GetStringValue() const;
  254. int GetIntValue() const;
  255. float GetFloatValue() const;
  256. private:
  257. CResourceString m_Name;
  258. ResourceIntrospectionMetadataType_t m_Type;
  259. uint32 m_Value;
  260. };
  261. schema class CResourceIntrospectionChildMetadata
  262. {
  263. friend class CResourceIntrospectionMetadata;
  264. private:
  265. CResourceString m_ChildName;
  266. CResourceArray<CResourceIntrospectionMetadataElement> m_MetaElements;
  267. };
  268. schema class CResourceIntrospectionMetadata
  269. {
  270. public:
  271. DECLARE_SCHEMA_DATA_CLASS( CResourceIntrospectionMetadata );
  272. protected:
  273. CResourceString m_ObjectName;
  274. CResourceArray<CResourceIntrospectionMetadataElement> m_RootMetaElements;
  275. CResourceArray<CResourceIntrospectionChildMetadata> m_ChildrenMeta;
  276. };
  277. //-----------------------------------------------------------------------------
  278. // Root introspection block
  279. //-----------------------------------------------------------------------------
  280. //! resourceBlockType = "RESI"
  281. schema class CResourceIntrospection
  282. {
  283. DECLARE_SCHEMA_DATA_CLASS( CResourceIntrospection );
  284. public:
  285. static CResourceIntrospection* AddToStream( CResourceStream *pStream, ResourceFileHeader_t *pHeader, int nBlockIndex );
  286. static const CResourceIntrospection* FindInFile( const ResourceFileHeader_t *pHeader );
  287. // These methods are used for reading the data
  288. public:
  289. uint32 GetVersion() const;
  290. int GetStructCount() const;
  291. const CResourceStructIntrospection* GetStructIntrospection( int nIndex ) const;
  292. const CResourceStructIntrospection* FindStructIntrospection( ResourceStructureId_t id ) const;
  293. const CResourceStructIntrospection* FindStructIntrospection( const char *pStructName ) const;
  294. CResourceStructIntrospection* GetWritableStructIntrospection( int nIndex );
  295. const CResourceStructIntrospection* FindStructIntrospectionForResourceType( ResourceType_t nType ) const;
  296. const CResourceStructIntrospection* FindPermanentStructIntrospectionForResourceType( ResourceType_t nType ) const;
  297. int GetEnumCount() const;
  298. const CResourceEnumIntrospection* GetEnumIntrospection( int nIndex ) const;
  299. const CResourceEnumIntrospection* FindEnumIntrospection( ResourceStructureId_t id ) const;
  300. const CResourceEnumIntrospection* FindEnumIntrospection( const char *pEnumName ) const;
  301. CResourceEnumIntrospection* GetWritableEnumIntrospection( int nIndex );
  302. int GetTypedefCount() const;
  303. const CResourceTypedefIntrospection* GetTypedefIntrospection( int nIndex ) const;
  304. CResourceTypedefIntrospection* GetWritableTypedefIntrospection( int nIndex );
  305. // Compare with the current EXE's introspection
  306. IntrospectionCompatibilityType_t CalculateCompatibility() const;
  307. // These methods are used for writing the data
  308. public:
  309. void AllocateStructs( CResourceStream *pStream, int nCount );
  310. void AllocateEnums( CResourceStream *pStream, int nCount );
  311. void AllocateTypedefs( CResourceStream *pStream, int nCount );
  312. const void *GetPtr() const { return this; }
  313. private:
  314. // This should always be the first 4 bytes, since this structure can't be fully-introspected
  315. uint32 m_nVersion;
  316. CResourceArray< CResourceTypedefIntrospection > m_TypedefIntrospection;
  317. CResourceArray< CResourceEnumIntrospection > m_EnumIntrospection;
  318. CResourceArray< CResourceStructIntrospection > m_StructIntrospection;
  319. CResourcePointer< CResourceIntrospectionMetadata > m_Metadata;
  320. };
  321. DEFINE_RESOURCE_BLOCK_TYPE( CResourceIntrospection, 'R', 'E', 'S', 'I' )
  322. //-----------------------------------------------------------------------------
  323. // Computes a resource structure id given a structure name string
  324. //-----------------------------------------------------------------------------
  325. ResourceStructureId_t ComputeStructureNameHash( const char *pStructName );
  326. //-----------------------------------------------------------------------------
  327. // Inherit from this to fully-traverse a piece of memory using introspection
  328. //-----------------------------------------------------------------------------
  329. class CResourceIntrospectionTraversal
  330. {
  331. public:
  332. CResourceIntrospectionTraversal( const CResourceIntrospection *pResIntro = NULL );
  333. virtual void TraverseStruct( const void *pStruct, const CResourceStructIntrospection *pStructIntro );
  334. protected:
  335. virtual void TraverseField( const void *pField, const CResourceFieldIntrospection *pFieldIntro, ResourceFieldType_t fieldType, int nTypeChainIndex );
  336. virtual void TraverseRootField( const void *pField, const CResourceFieldIntrospection *pFieldIntro );
  337. // Simple overridable methods
  338. virtual bool VisitField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro, int nTypeChainIndex ) { return true; }
  339. virtual void PostVisitField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro, int nTypeChainIndex ) { }
  340. virtual bool VisitRootField( const void *pFieldInstance, const CResourceFieldIntrospection *pFieldIntro ) { return true; }
  341. virtual bool VisitStruct( const void *pStruct, const CResourceStructIntrospection *pStructIntro ) { return true; }
  342. virtual bool VisitEnum( const void *pEnum, const CResourceEnumIntrospection *pEnumIntro ) { return true; }
  343. bool m_bTraverseDiskLayout; // as opposed to memory layout
  344. const CResourceIntrospection *m_pResIntro;
  345. // TODO: Probably want more flags, like bFollowStructPointers, etc.
  346. };
  347. #endif // RESOURCEINTROSPECTION_H