From 6a703f7fd03ce3b1e798c6884480dda6491f1b79 Mon Sep 17 00:00:00 2001 From: GAMMACASE Date: Wed, 26 Jul 2023 14:01:46 +0300 Subject: [PATCH] Add CVariant --- public/basehandle.h | 15 + public/datamap.h | 27 + public/entity2/entityidentity.h | 15 + public/tier1/strtools.h | 102 +++- public/tier1/utlscratchmemory.h | 88 +++ public/tier1/utlstring.h | 5 + public/variant.h | 985 ++++++++++++++++++++++++++++++++ public/vscript/ivscript.h | 302 +--------- 8 files changed, 1240 insertions(+), 299 deletions(-) create mode 100644 public/entity2/entityidentity.h create mode 100644 public/tier1/utlscratchmemory.h create mode 100644 public/variant.h diff --git a/public/basehandle.h b/public/basehandle.h index e02ddd31..30ff49a8 100644 --- a/public/basehandle.h +++ b/public/basehandle.h @@ -17,6 +17,21 @@ class IHandleEntity; +// Represents EHANDLE2 class +// TODO: GAMMACASE: Replace old CBaseHandle with this +class CEntityHandle +{ +public: + union + { + uint32 m_Index; + struct + { + uint32 m_EntityIndex : 15; + uint32 m_Serial : 17; + } m_Parts; + }; +}; // -------------------------------------------------------------------------------------------------- // // CBaseHandle. diff --git a/public/datamap.h b/public/datamap.h index 6c4799d7..9cf934ce 100644 --- a/public/datamap.h +++ b/public/datamap.h @@ -93,6 +93,33 @@ typedef enum _fieldtypes FIELD_V8_ARRAY, FIELD_V8_CALLBACK_INFO, FIELD_UTLSTRING, + + FIELD_NETWORK_ORIGIN_CELL_QUANTIZED_POSITION_VECTOR, + FIELD_HRENDERTEXTURE, + + FIELD_HPARTICLESYSTEMDEFINITION, + FIELD_UINT8, + FIELD_UINT16, + FIELD_CTRANSFORM, + FIELD_CTRANSFORM_WORLDSPACE, + FIELD_HPOSTPROCESSING, + FIELD_MATRIX3X4, + FIELD_SHIM, + FIELD_CMOTIONTRANSFORM, + FIELD_CMOTIONTRANSFORM_WORLDSPACE, + FIELD_ATTACHMENT_HANDLE, + FIELD_AMMO_INDEX, + FIELD_CONDITION_ID, + FIELD_AI_SCHEDULE_BITS, + FIELD_MODIFIER_HANDLE, + FIELD_ROTATION_VECTOR, + FIELD_ROTATION_VECTOR_WORLDSPACE, + FIELD_HVDATA, + FIELD_SCALE32, + FIELD_STRING_AND_TOKEN, + FIELD_ENGINE_TIME, + FIELD_ENGINE_TICK, + FIELD_WORLD_GROUP_ID, FIELD_TYPECOUNT } fieldtype_t; diff --git a/public/entity2/entityidentity.h b/public/entity2/entityidentity.h new file mode 100644 index 00000000..6711d551 --- /dev/null +++ b/public/entity2/entityidentity.h @@ -0,0 +1,15 @@ +#ifndef ENTITYIDENTITY_H +#define ENTITYIDENTITY_H + +#if _WIN32 +#pragma once +#endif + +class CEntityIdentity +{ +public: + +private: +}; + +#endif // ENTITYIDENTITY_H \ No newline at end of file diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h index de0e4eca..2038deba 100644 --- a/public/tier1/strtools.h +++ b/public/tier1/strtools.h @@ -22,6 +22,30 @@ #include #include +// Forward declaration +class CBufferString; +class Vector; +class Vector2D; +class Vector4D; +class Quaternion; +class Color; +class QAngle; + +abstract_class IParsingErrorListener +{ + virtual void OnParsingError(CBufferString &error_msg) = 0; +}; + +#define PARSING_FLAG_NONE (0) +#define PARSING_FLAG_ERROR_ASSERT (1 << 0) // Triggers debug assertion on parsing errors +#define PARSING_FLAG_INTERNAL_ASSERT_TRIGGERED (1 << 1) // Internal flag that is set when assertion is triggered +#define PARSING_FLAG_EMIT_WARNING (1 << 2) // Emits global console warning on parsing errors +#define PARSING_FLAG_INTERNAL_WARNING_EMITTED (1 << 3) // Internal flag that is set when global warning is emitted +#define PARSING_FLAG_SILENT (1 << 4) // Won't call callback when parsing errors are encountered +#define PARSING_FLAG_ERROR_IF_EMPTY (1 << 5) // Emits parsing error if the input string was empty or NULL +#define PARSING_FLAG_UNK006 (1 << 6) +#define PARSING_FLAG_USE_BASE_AUTO (1 << 7) // Use auto detection of a number base when parsing (uses https://en.cppreference.com/w/cpp/string/basic_string/stol under the hood, so same base rules applies) +#define PARSING_FLAG_USE_BASE_16 (1 << 8) // Use base of 16 when parsing // 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination // strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1. @@ -31,8 +55,6 @@ void CopyMemory3D( void *pDestAdr, void const *pSrcAdr, int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest ); - - template< class T, class I > class CUtlMemory; template< class T, class A > class CUtlVector; @@ -102,6 +124,82 @@ inline char *strlwr( char *start ) // AM TODO: handle this for the rest (above and more) now exported by tier0 PLATFORM_INTERFACE int V_stricmp_fast(const char* s1, const char* s2); +// Compares two strings with the support of wildcarding only for the first arg (includes '*' for multiple and '?' for single char usages) +PLATFORM_INTERFACE int V_CompareNameWithWildcards(const char *wildcarded_string, const char *compare_to, bool case_sensitive = false); + +// Parses string equivalent of ("true", "false", "yes", "no", "1", "0") to the boolean value +// where default_value is what would be returned if parsing has failed +PLATFORM_INTERFACE bool V_StringToBool(const char *buf, bool default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a float array up to the amount of arr_size or up to the string limit, the amount of parsed values is returned +PLATFORM_INTERFACE int V_StringToFloatArray(const char *buf, float *out_arr, int arr_size, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into an int array up to the amount of arr_size or up to the string limit, the amount of parsed values is returned +PLATFORM_INTERFACE int V_StringToIntArray(const char *buf, int *out_arr, int arr_size, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a Vector structure +PLATFORM_INTERFACE void V_StringToVector(const char *buf, Vector &out_vec, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a Vector2D structure +PLATFORM_INTERFACE void V_StringToVector2D(const char *buf, Vector2D &out_vec, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a Vector4D structure +PLATFORM_INTERFACE void V_StringToVector4D(const char *buf, Vector4D &out_vec, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a Color structure +PLATFORM_INTERFACE void V_StringToColor(const char *buf, Color &out_clr, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a QAngle structure +PLATFORM_INTERFACE void V_StringToQAngle(const char *buf, QAngle &out_ang, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string into a Quaternion structure +PLATFORM_INTERFACE void V_StringToQuaternion(const char *buf, Quaternion &out_quat, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a uint64 value, where if the value exceeds min/max limits (inclusive), the parsing fails and default_value is returned +PLATFORM_INTERFACE uint64 V_StringToUint64Limit(const char *buf, uint64 min, uint64 max, uint64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a int64 value, where if the value exceeds min/max limits (inclusive), the parsing fails and default_value is returned +PLATFORM_INTERFACE int64 V_StringToInt64Limit(const char *buf, int64 min, int64 max, int64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a uint64 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE uint64 V_StringToUint64(const char *buf, uint64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a int64 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE int64 V_StringToInt64(const char *buf, int64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a uint32 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE uint32 V_StringToUint32(const char *buf, uint32 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a int32 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE int32 V_StringToInt32(const char *buf, int32 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a uint16 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE uint16 V_StringToUint16(const char *buf, uint16 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a int16 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE int16 V_StringToInt16(const char *buf, int16 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a uint8 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE uint8 V_StringToUint8(const char *buf, uint8 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a int8 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE int8 V_StringToInt8(const char *buf, int8 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a float64 value, where if the value exceeds min/max limits (inclusive), the parsing fails and default_value is returned +PLATFORM_INTERFACE float64 V_StringToFloat64Limit(const char *buf, float64 min, float64 max, float64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a float64 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE float64 V_StringToFloat64(const char *buf, float64 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a float32 value, if the parsing fails, default_value is returned +PLATFORM_INTERFACE float32 V_StringToFloat32(const char *buf, float32 default_value, bool *successful = NULL, char **remainder = NULL, uint flags = PARSING_FLAG_NONE, IParsingErrorListener *err_listener = NULL); + +// Parses string as a float64 value, if the parsing fails, default_value is returned, doesn't perform error checking/reporting +PLATFORM_INTERFACE float64 V_StringToFloat64Raw(const char *buf, float64 default_value, bool *successful = NULL, char **remainder = NULL); + +// Parses string as a float32 value, if the parsing fails, default_value is returned, doesn't perform error checking/reporting +PLATFORM_INTERFACE float32 V_StringToFloat32Raw(const char *buf, float32 default_value, bool *successful = NULL, char **remainder = NULL); + #else inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); } diff --git a/public/tier1/utlscratchmemory.h b/public/tier1/utlscratchmemory.h new file mode 100644 index 00000000..4d852df4 --- /dev/null +++ b/public/tier1/utlscratchmemory.h @@ -0,0 +1,88 @@ +#ifndef UTLSCRATCHMEMORY_H +#define UTLSCRATCHMEMORY_H + +#if _WIN32 +#pragma once +#endif + +struct UtlScratchMemoryPoolMark_t +{ + void *m_pBlock; + int m_nBytesFree; +}; + +// Chunks memory allocator of a size (m_nBlockSize), where first 16 bytes are allocated for +// MemoryBlock_t struct, that holds additional information about next chunk. +class CUtlScratchMemoryPool +{ +public: + CUtlScratchMemoryPool() : m_pFirstBlock(NULL), m_nBlockSize(0), m_bSearchAllBlocks(false) {} + CUtlScratchMemoryPool(int nBlockSize, void *pExternalMem, bool bSearchAllBlocks) : + m_pFirstBlock(NULL), m_nBlockSize(nBlockSize), m_bSearchAllBlocks(bSearchAllBlocks) + { + Init(nBlockSize, pExternalMem, bSearchAllBlocks); + } + + ~CUtlScratchMemoryPool() + { + // FreeAll(); + } + + void Init(int nBlockSize, void *pExternalMem, bool bSearchAllBlocks) + { + Assert(nBlockSize > sizeof(MemoryBlock_t)); + + if(pExternalMem != NULL) + { + m_pFirstBlock = (MemoryBlock_t *)pExternalMem; + + m_pFirstBlock->m_pNext = NULL; + m_pFirstBlock->m_nBytesFree = nBlockSize - 16; + m_pFirstBlock->m_bSkipDeallocation = true; + } + } + + UtlScratchMemoryPoolMark_t GetCurrentAllocPoint() const + { + UtlScratchMemoryPoolMark_t result{}; + result.m_pBlock = m_pFirstBlock; + + if(m_pFirstBlock) + result.m_nBytesFree = m_pFirstBlock->m_nBytesFree; + else + result.m_nBytesFree = 0; + + return result; + } + + // GAMMACASE: Not finished functions: + // void *AddNewBlock(int nSizeInBytes); + // void *AllocAligned(int nSizeInBytes, int nAlignment); + // void FreeToAllocPoint(UtlScratchMemoryPoolMark_t mark); + // void FreeAll(); + +private: + struct MemoryBlock_t + { + MemoryBlock_t *m_pNext; + int m_nBytesFree; + bool m_bSkipDeallocation; + }; + + MemoryBlock_t *m_pFirstBlock; + int m_nBlockSize; + bool m_bSearchAllBlocks; +}; + +template +class CUtlScratchMemoryPoolFixedGrowable : public CUtlScratchMemoryPool +{ +public: + CUtlScratchMemoryPoolFixedGrowable(bool bSearchAllBlocks) : CUtlScratchMemoryPool(SIZE, &m_initialAllocationMemory, bSearchAllBlocks) { } + +private: + unsigned char m_initialAllocationMemory[SIZE]; +}; + + +#endif // UTLSCRATCHMEMORY_H \ No newline at end of file diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h index 79a6e8ac..7d698fec 100644 --- a/public/tier1/utlstring.h +++ b/public/tier1/utlstring.h @@ -40,6 +40,11 @@ inline size_t strnlen(const char *s, size_t n) #endif +class CUtlStringToken +{ + unsigned int m_nHashCode; +}; + //----------------------------------------------------------------------------- // Simple string class. // NOTE: This is *not* optimal! Use in tools, but not runtime code diff --git a/public/variant.h b/public/variant.h new file mode 100644 index 00000000..2369d514 --- /dev/null +++ b/public/variant.h @@ -0,0 +1,985 @@ +#ifndef CVARIANT_H +#define CVARIANT_H + +#if _WIN32 +#pragma once +#endif + +#include "datamap.h" +#include "vector.h" +#include "vector2d.h" +#include "vector4d.h" +#include "Color.h" +#include "entity2/entityidentity.h" +#include "basehandle.h" +#include "bufferstring.h" +#include "utlscratchmemory.h" + +// Forward declaration +class CEntityInstance; + +// Non-implemented classes/structs +struct ResourceBindingBase_t; +typedef const ResourceBindingBase_t *ResourceHandle_t; + +// ======== + +class CVariantDefaultAllocator +{ +public: + static void Free(void *pMemory) + { + free(pMemory); + } + + static void *Allocate(int nSize) + { + return malloc(nSize); + } +}; + +class CEntityVariantAllocator +{ +public: + static void Free(void *pMemory) { /* Skipped intentionally */ } + + static void *Allocate(int nSize) + { + // GAMMACASE: Remove #if condition once CUtlScratchMemoryPool is finished. +#if defined(UTLSCRATCHMEMORYPOOL_FINISHED) + return sm_pMemoryPool.AllocAligned(nSize, 8 * (nSize >= 16) + 8); +#else + return NULL; +#endif + } + + static void Activate(CUtlScratchMemoryPool *pMemoryPool, bool bEnable) + { + sm_pMemoryPool = bEnable ? pMemoryPool : NULL; + } + +private: + static CUtlScratchMemoryPool *sm_pMemoryPool; +}; + +inline const char *VariantFieldTypeName(int16 eType) +{ + switch(eType) + { + case FIELD_VOID: return "void"; + case FIELD_FLOAT: return "float"; + case FIELD_STRING: return "string_t"; + case FIELD_VECTOR: return "vector"; + case FIELD_QUATERNION: return "quaternion"; + case FIELD_INTEGER: return "integer"; + case FIELD_BOOLEAN: return "boolean"; + case FIELD_CHARACTER: return "character"; + case FIELD_COLOR32: return "color"; + case FIELD_EHANDLE: return "ehandle"; + case FIELD_VECTOR2D: return "vector2d"; + case FIELD_VECTOR4D: return "vector4d"; + case FIELD_INTEGER64: return "int64"; + case FIELD_RESOURCE: return "resourcehandle"; + case FIELD_CSTRING: return "cstring"; + case FIELD_HSCRIPT: return "hscript"; + case FIELD_VARIANT: return "variant"; + case FIELD_UINT64: return "uint64"; + case FIELD_FLOAT64: return "float64"; + case FIELD_UINT: return "unsigned"; + case FIELD_UTLSTRINGTOKEN: return "utlstringtoken"; + case FIELD_QANGLE: return "qangle"; + case FIELD_HSCRIPT_LIGHTBINDING: return "hscript_lightbinding"; + case FIELD_V8_VALUE: return "js_value"; + case FIELD_V8_OBJECT: return "js_object"; + case FIELD_V8_ARRAY: return "js_array"; + case FIELD_V8_CALLBACK_INFO: return "js_raw_args"; + default: return "unknown_variant_type"; + } +} + +template struct VariantTypeDeducer { }; +#define DECLARE_DEDUCE_VARIANT_FIELDTYPE( fieldType, type ) template<> struct VariantTypeDeducer { enum { FIELD_TYPE = fieldType }; }; + +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VOID, void); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_CSTRING, const char *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_CSTRING, char *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR, Vector); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR, Vector *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR, const Vector &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR2D, Vector2D); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR2D, Vector2D *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR2D, const Vector2D &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR4D, Vector4D); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR4D, Vector4D *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_VECTOR4D, const Vector4D &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_COLOR32, Color); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_COLOR32, Color *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_COLOR32, const Color &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QANGLE, QAngle); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QANGLE, QAngle *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QANGLE, const QAngle &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QUATERNION, Quaternion); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QUATERNION, Quaternion *); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_QUATERNION, const Quaternion &); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_STRING, string_t); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_BOOLEAN, bool); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_CHARACTER, char); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_INTEGER64, int64); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_UINT64, uint64); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_FLOAT, float); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_FLOAT64, float64); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_INTEGER, int); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_UINT, uint); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_HSCRIPT, HSCRIPT); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_EHANDLE, CEntityHandle); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_RESOURCE, ResourceHandle_t); +DECLARE_DEDUCE_VARIANT_FIELDTYPE(FIELD_UTLSTRINGTOKEN, CUtlStringToken); + +#define VariantDeduceType( T ) VariantTypeDeducer::FIELD_TYPE +#undef DECLARE_DEDUCE_VARIANT_FIELDTYPE + +template +inline const char *VariantFieldTypeName() +{ + return T::using_unknown_variant_type(); +} + +#define DECLARE_NAMED_VARIANT_FIELDTYPE( fieldType, strName ) template <> inline const char * VariantFieldTypeName() { return strName; } + +DECLARE_NAMED_VARIANT_FIELDTYPE(void, "void"); +DECLARE_NAMED_VARIANT_FIELDTYPE(const char *, "cstring"); +DECLARE_NAMED_VARIANT_FIELDTYPE(char *, "cstring"); +DECLARE_NAMED_VARIANT_FIELDTYPE(bool, "boolean"); +DECLARE_NAMED_VARIANT_FIELDTYPE(char, "character"); +DECLARE_NAMED_VARIANT_FIELDTYPE(int, "integer"); +DECLARE_NAMED_VARIANT_FIELDTYPE(uint, "unsigned integer"); +DECLARE_NAMED_VARIANT_FIELDTYPE(int64, "int64"); +DECLARE_NAMED_VARIANT_FIELDTYPE(uint64, "uint64"); +DECLARE_NAMED_VARIANT_FIELDTYPE(float, "float"); +DECLARE_NAMED_VARIANT_FIELDTYPE(float64, "float64"); + +#undef DECLARE_NAMED_VARIANT_FIELDTYPE + +enum CVFlags_t +{ + // Indicates that variant has the memory allocated in place of a primitive types and it would be freed when needed + CV_FREE = 0x01, +}; + +template +class CVariantBase +{ +public: + typedef A Allocator; + + CVariantBase() : m_type( FIELD_VOID ), m_flags( 0 ) { m_pData = NULL; } + CVariantBase( int val ) : m_type( FIELD_INTEGER ), m_flags( 0 ) { m_int = val;} + CVariantBase( uint val) : m_type( FIELD_UINT ), m_flags( 0 ) { m_uint = val; } + CVariantBase( float val ) : m_type( FIELD_FLOAT ), m_flags( 0 ) { m_float = val; } + CVariantBase( float64 val ) : m_type( FIELD_FLOAT64 ), m_flags( 0 ) { m_float64 = val; } + CVariantBase( char val ) : m_type( FIELD_CHARACTER ), m_flags( 0 ) { m_char = val; } + CVariantBase( bool val ) : m_type( FIELD_BOOLEAN ), m_flags( 0 ) { m_bool = val; } + CVariantBase( HSCRIPT val ) : m_type( FIELD_HSCRIPT ), m_flags( 0 ) { m_hScript = val; } + CVariantBase( CEntityHandle val ) : m_type( FIELD_EHANDLE ), m_flags( 0 ) { m_hEntity = val; } + CVariantBase( CUtlStringToken val ) : m_type( FIELD_UTLSTRINGTOKEN ), m_flags( 0 ){ m_utlStringToken = val; } + CVariantBase( ResourceHandle_t val ) : m_type( FIELD_RESOURCE ), m_flags( 0 ) { m_hResource = val; } + CVariantBase( string_t val ) : m_type( FIELD_STRING ), m_flags( 0 ) { m_stringt = val; } + CVariantBase( int64 val ) : m_type( FIELD_INTEGER64 ), m_flags( 0 ) { m_int64 = val; } + CVariantBase( uint64 val ) : m_type( FIELD_UINT64), m_flags( 0 ) { m_uint64 = val; } + + CVariantBase( const Vector &val, bool bCopy = true) : m_type( FIELD_VECTOR ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const Vector *val, bool bCopy = true) : m_type( FIELD_VECTOR ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const QAngle &val, bool bCopy = true) : m_type( FIELD_QANGLE ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const QAngle *val, bool bCopy = true) : m_type( FIELD_QANGLE ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const Vector2D &val, bool bCopy = true ) : m_type( FIELD_VECTOR2D ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const Vector2D *val, bool bCopy = true ) : m_type( FIELD_VECTOR2D ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const Vector4D &val, bool bCopy = true ) : m_type( FIELD_VECTOR4D ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const Vector4D *val, bool bCopy = true ) : m_type( FIELD_VECTOR4D ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const Quaternion &val, bool bCopy = true ) : m_type( FIELD_QUATERNION ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const Quaternion *val, bool bCopy = true ) : m_type( FIELD_QUATERNION ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const Color &val, bool bCopy = true ) : m_type( FIELD_COLOR32 ), m_flags( 0 ) { CopyData(val, bCopy); } + CVariantBase( const Color *val, bool bCopy = true ) : m_type( FIELD_COLOR32 ), m_flags( 0 ) { CopyData(*val, bCopy); } + CVariantBase( const char *val, bool bCopy = true ) : m_type( FIELD_CSTRING ), m_flags( 0 ) { CopyData(val, bCopy); } + + // Checks if the stored value is of type FIELD_VOID + bool IsNull() const { return (m_type == FIELD_VOID ); } + + // Copies the src data into an internal value, setting bForceCopy would allocate its own memory to store the contents + void CopyData(const char *src, bool bForceCopy) + { + Free(); + + m_type = FIELD_CSTRING; + + if(src && bForceCopy) + { + int len = strlen(src) + 1; + m_pszString = (char *)Allocator::Allocate(len); + memcpy((void *)m_pszString, src, len); + + m_flags |= CV_FREE; + } + else + { + m_pszString = src; + } + } + + // Copies the src data into an internal value, setting bForceCopy would allocate its own memory to store the contents + template + void CopyData(const T &src, bool bForceCopy) + { + Free(); + + m_type = VariantDeduceType(T); + + if(bForceCopy) + { + m_pData = Allocator::Allocate(sizeof(T)); + *this = src; + + m_flags |= CV_FREE; + } + else + { + m_pData = *(void **)&src; + } + } + + operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; } + operator uint() const { Assert( m_type == FIELD_UINT ); return m_uint; } + operator int64() const { Assert( m_type == FIELD_INTEGER64); return m_int64; } + operator uint64() const { Assert( m_type == FIELD_UINT64); return m_uint64; } + operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; } + operator float64() const { Assert( m_type == FIELD_FLOAT64 ); return m_float64; } + operator const string_t() const { Assert( m_type == FIELD_STRING ); return m_stringt; } + operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; } + operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; } + operator const Vector2D &() const { Assert( m_type == FIELD_VECTOR2D ); static Vector2D vecNull(0, 0); return (m_pVector2D) ? *m_pVector2D : vecNull; } + operator const Vector4D &() const { Assert( m_type == FIELD_VECTOR4D ); static Vector4D vecNull(0, 0, 0, 0); return (m_pVector4D) ? *m_pVector4D : vecNull; } + operator const QAngle &() const { Assert( m_type == FIELD_QANGLE); static QAngle angNull(0, 0, 0); return (m_pQAngle) ? *m_pQAngle : angNull; } + operator const Quaternion &() const { Assert( m_type == FIELD_QUATERNION); static Quaternion quatNull(0, 0, 0, 0); return (m_pQuaternion) ? *m_pQuaternion : quatNull; } + operator const Color &() const { Assert( m_type == FIELD_COLOR32); static Color colorNull(0, 0, 0); return (m_pColor) ? *m_pColor : colorNull; } + operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; } + operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; } + operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; } + operator CEntityHandle() const { Assert( m_type == FIELD_EHANDLE); return m_hEntity; } + operator CUtlStringToken() const { Assert( m_type == FIELD_UTLSTRINGTOKEN); return m_utlStringToken; } + operator ResourceHandle_t() const { Assert( m_type == FIELD_RESOURCE); return m_hResource; } + + void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; } + void operator=( uint u ) { m_type = FIELD_UINT; m_uint = u; } + void operator=( int64 i ) { m_type = FIELD_INTEGER64; m_int64 = i; } + void operator=( uint64 u ) { m_type = FIELD_UINT64; m_uint64 = u; } + void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; } + void operator=( float64 d ) { m_type = FIELD_FLOAT64; m_float64 = d; } + void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; *(Vector *)m_pVector = vec; } + void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; } + void operator=( const Vector2D &vec ) { m_type = FIELD_VECTOR2D; *(Vector2D *)m_pVector2D = vec; } + void operator=( const Vector2D *vec ) { m_type = FIELD_VECTOR2D; m_pVector2D = vec; } + void operator=( const Vector4D &vec ) { m_type = FIELD_VECTOR4D; *(Vector4D *)m_pVector4D = vec; } + void operator=( const Vector4D *vec ) { m_type = FIELD_VECTOR4D; m_pVector4D = vec; } + void operator=( const QAngle &ang ) { m_type = FIELD_QANGLE; *(QAngle *)m_pQAngle = ang; } + void operator=( const QAngle *ang ) { m_type = FIELD_QANGLE; m_pQAngle = ang; } + void operator=( const Quaternion &quat ){ m_type = FIELD_QUATERNION; *(Quaternion *)m_pQuaternion = quat; } + void operator=( const Quaternion *quat ){ m_type = FIELD_QUATERNION; m_pQuaternion = quat; } + void operator=( const Color &color ) { m_type = FIELD_COLOR32; *(Color *)m_pColor = color; } + void operator=( const Color *color ) { m_type = FIELD_COLOR32; m_pColor = color; } + void operator=( string_t psz ) { m_type = FIELD_STRING; m_stringt = psz; } + void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; } + void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; } + void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; } + void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; } + void operator=( CEntityHandle eh) { m_type = FIELD_EHANDLE; m_hEntity = eh; } + void operator=( CUtlStringToken tok ) { m_type = FIELD_UTLSTRINGTOKEN; m_utlStringToken = tok; } + void operator=( ResourceHandle_t r ) { m_type = FIELD_RESOURCE; m_hResource = r; } + + ~CVariantBase() + { + Free(); + } + + // Frees the internal buffer and resets the value to be FIELD_VOID + void Free() + { + if(m_flags & CV_FREE) + { + Allocator::Free(m_pData); + m_flags &= ~CV_FREE; + } + + m_pData = NULL; + m_type = FIELD_VOID; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(CBufferString &buf) + { + buf.Purge(0); + + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_FLOAT: buf.Format("%g", m_float); return true; + case FIELD_FLOAT64: buf.Format("%g", m_float64); return true; + case FIELD_INTEGER: buf.Format("%d", m_int); return true; + case FIELD_UINT: buf.Format("%u", m_uint); return true; + case FIELD_INTEGER64: buf.Format("%lld", m_int64); return true; + case FIELD_UINT64: buf.Format("%llu", m_uint64); return true; + case FIELD_BOOLEAN: buf.Insert(0, m_bool ? "true" : "false"); return true; + case FIELD_STRING: buf.Insert(0, m_stringt.ToCStr()); return true; + case FIELD_CSTRING: buf.Insert(0, m_pszString ? m_pszString : "(null)"); return true; + case FIELD_CHARACTER: buf.Format("%c", m_char); return true; + case FIELD_VECTOR2D: buf.Format("%g %g", m_pVector2D->x, m_pVector2D->y); return true; + case FIELD_COLOR32: buf.Format("%d %d %d %d", m_pColor->r(), m_pColor->g(), m_pColor->b(), m_pColor->a()); return true; + + case FIELD_VECTOR: + case FIELD_QANGLE: + { + buf.Format("%g %g %g", m_pVector->x, m_pVector->y, m_pVector->z); + return true; + } + + case FIELD_QUATERNION: + case FIELD_VECTOR4D: + { + buf.Format("%g %g %g %g", m_pVector4D->x, m_pVector4D->y, m_pVector4D->z, m_pVector4D->w); + return true; + } + + default: Warning("No conversion from %s to string at the moment!\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(float *pDest) + { + switch(m_type) + { + case FIELD_VOID: *pDest = 0.0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_INTEGER64: *pDest = m_int64; return true; + case FIELD_UINT: *pDest = m_uint; return true; + case FIELD_UINT64: *pDest = m_uint64; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_FLOAT64: *pDest = m_float64; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0]) + { + *pDest = V_atof(m_pszString); + return true; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + *pDest = V_atof(m_stringt.ToCStr()); + return true; + } + } + + default: Warning("No conversion from %s to float right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(int *pDest) + { + switch(m_type) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_INTEGER64: *pDest = m_int64; return true; + case FIELD_UINT: *pDest = m_uint; return true; + case FIELD_UINT64: *pDest = m_uint64; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_FLOAT64: *pDest = m_float64; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0]) + { + *pDest = V_atoi(m_pszString); + return true; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + *pDest = V_atoi(m_stringt.ToCStr()); + return true; + } + } + + default: Warning("No conversion from %s to int right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(bool *pDest) + { + switch(m_type) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int != 0; return true; + case FIELD_INTEGER64: *pDest = m_int64 != 0; return true; + case FIELD_UINT: *pDest = m_uint != 0; return true; + case FIELD_UINT64: *pDest = m_uint64 != 0; return true; + case FIELD_FLOAT: *pDest = m_float != 0.0; return true; + case FIELD_FLOAT64: *pDest = m_float64 != 0.0; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0]) + { + bool successful = false; + *pDest = V_StringToBool(m_pszString, false, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + *pDest = V_StringToBool(m_stringt.ToCStr(), false, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to bool right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(string_t *pDest) + { + if(m_type == FIELD_STRING) + { + *pDest = *this; + return true; + } + else if(m_type == FIELD_CSTRING) + { + if(m_pszString) + { + *pDest = MAKE_STRING(m_pszString); + return true; + } + } + else + { + Warning("No conversion from %s to string_t right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(Vector *pDest) + { + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_VECTOR: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToVector(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToVector(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to Vector right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(Vector2D *pDest) + { + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_VECTOR2D: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToVector2D(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToVector2D(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to Vector2D right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(Vector4D *pDest) + { + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_VECTOR4D: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToVector4D(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToVector4D(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to Vector4D right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(Quaternion *pDest) + { + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_QUATERNION: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToQuaternion(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToQuaternion(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to Quaternion right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(QAngle *pDest) + { + switch(m_type) + { + case FIELD_VOID: return false; + case FIELD_QANGLE: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToQAngle(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToQAngle(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to QAngle right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(Color *pDest) + { + switch(m_type) + { + case FIELD_COLOR32: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0] != '\0') + { + bool successful = false; + V_StringToColor(m_pszString, *pDest, &successful); + return successful; + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + bool successful = false; + V_StringToColor(m_stringt.ToCStr(), *pDest, &successful); + return successful; + } + } + + default: Warning("No conversion from %s to Color right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(ResourceHandle_t *pDest) + { + if(m_type == FIELD_RESOURCE) + { + *pDest = *this; + return true; + } + else + { + Warning("No conversion from %s to ResourceHandle_t right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(HSCRIPT *pDest) + { + if(m_type == FIELD_HSCRIPT) + { + *pDest = *this; + return true; + } + else + { + Warning("No conversion from %s to HSCRIPT right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(CUtlStringToken *pDest) + { + if(m_type == FIELD_UTLSTRINGTOKEN) + { + *pDest = *this; + return true; + } + else + { + Warning("No conversion from %s to CUtlStringToken right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(CEntityHandle *pDest) + { + switch(m_type) + { + case FIELD_EHANDLE: *pDest = *this; return true; + case FIELD_CSTRING: + { + if(m_pszString && m_pszString[0]) + { + // TODO: Perform actual entity handle lookup via CEntitySystem::FindFirstEntityHandleByName() + Assert(false); + } + } + case FIELD_STRING: + { + if(m_stringt.ToCStr()[0]) + { + // TODO: Perform actual entity handle lookup via CEntitySystem::FindFirstEntityHandleByName() + Assert(false); + } + } + + default: Warning("No conversion from %s to EHANDLE2 right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + bool AssignTo(CEntityInstance *pDest) + { + if(m_type == FIELD_EHANDLE) + { + // TODO: Perform actual CEntityInstance lookup via CEntityHandle + Assert(false); + + return true; + } + else + { + Warning("No conversion from %s to CEntityInstance right now\n", VariantFieldTypeName(m_type)); + } + + return false; + } + + // Copies the contents of the value into a pDest, also converts the content when possible + template + bool AssignTo(CVariantBase *pDest) + { + switch(m_type) + { + case FIELD_VECTOR: pDest->CopyData(*m_pVector, true); return true; + case FIELD_VECTOR2D: pDest->CopyData(*m_pVector2D, true); return true; + case FIELD_VECTOR4D: pDest->CopyData(*m_pVector4D, true); return true; + case FIELD_QUATERNION: pDest->CopyData(*m_pQuaternion, true); return true; + case FIELD_QANGLE: pDest->CopyData(*m_pQAngle, true); return true; + case FIELD_COLOR32: pDest->CopyData(*m_pColor, true); return true; + case FIELD_CSTRING: pDest->CopyData(m_pszString, true); return true; + default: + { + pDest->Free(); + pDest->m_type = m_type; + pDest->m_pData = m_pData; + return true; + } + } + } + + template + bool AssignTo(T *pDest) + { + int16 destType = VariantDeduceType(T); + if(destType == FIELD_VOID) + { + return false; + } + + if(destType == m_type) + { + *pDest = *this; + return true; + } + + if(destType != FIELD_VECTOR && destType != FIELD_QUATERNION && destType != FIELD_VECTOR2D && + destType != FIELD_VECTOR4D && destType != FIELD_CSTRING && destType != FIELD_QANGLE) + { + switch(m_type) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_INTEGER64: *pDest = m_int64; return true; + case FIELD_UINT: *pDest = m_uint; return true; + case FIELD_UINT64: *pDest = m_uint64; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_FLOAT64: *pDest = m_float64; return true; + case FIELD_CHARACTER: *pDest = m_char; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + } + } + else + { + Warning("No free conversion of %s variant to %s right now\n", VariantFieldTypeName(m_type), VariantFieldTypeName()); + *pDest = 0; + } + + return false; + } + + // Allocates own buffers and copies the internal value when needed, if silent = false, emits a global warning + void ConvertToCopiedData(bool silent = true) + { + switch(m_type) + { + case FIELD_VECTOR: CopyData(*m_pVector, true); break; + case FIELD_VECTOR2D: CopyData(*m_pVector2D, true); break; + case FIELD_VECTOR4D: CopyData(*m_pVector4D, true); break; + case FIELD_QUATERNION: CopyData(*m_pQuaternion, true); break; + case FIELD_QANGLE: CopyData(*m_pQAngle, true); break; + case FIELD_COLOR32: CopyData(*m_pColor, true); break; + case FIELD_CSTRING: CopyData(m_pszString, true); break; + default: + { + if(!silent) + { + Warning("Attempted to ConvertToCopiedData for unsupported type (%d)\n", m_type); + } + } + } + } + + template + T Get() + { + T value = {}; + AssignTo(&value); + return value; + } + + // Sets the internal value to the pData content, doesn't allocate memory nor copies the content. + // Be sure to call ConvertToCopiedData() when required + void Set(fieldtype_t ftype, void *pData) + { + switch(ftype) + { + case FIELD_VOID: Free(); m_type = FIELD_VOID; m_pData = NULL; return; + case FIELD_FLOAT: CopyData(*(float *)pData, false); return; + case FIELD_FLOAT64: CopyData(*(float64 *)pData, false); return; + case FIELD_INTEGER: CopyData(*(int *)pData, false); return; + case FIELD_UINT: CopyData(*(uint *)pData, false); return; + case FIELD_INTEGER64: CopyData(*(int64 *)pData, false); return; + case FIELD_UINT64: CopyData(*(uint64 *)pData, false); return; + case FIELD_BOOLEAN: CopyData(*(bool *)pData, false); return; + case FIELD_CHARACTER: CopyData(*(char *)pData, false); return; + case FIELD_STRING: CopyData(*(string_t *)pData, false); return; + case FIELD_CSTRING: CopyData(*(const char **)pData, false); return; + case FIELD_VECTOR: CopyData((Vector *)pData, false); return; + case FIELD_VECTOR2D: CopyData((Vector2D *)pData, false); return; + case FIELD_VECTOR4D: CopyData((Vector4D *)pData, false); return; + case FIELD_COLOR32: CopyData((Color *)pData, false); return; + case FIELD_QANGLE: CopyData((QAngle *)pData, false); return; + case FIELD_QUATERNION: CopyData((Quaternion *)pData, false); return; + case FIELD_HSCRIPT: CopyData(*(HSCRIPT *)pData, false); return; + case FIELD_EHANDLE: CopyData(*(CEntityHandle *)pData, false); return; + case FIELD_RESOURCE: CopyData(*(ResourceHandle_t *)pData, false); return; + case FIELD_UTLSTRINGTOKEN: CopyData(*(CUtlStringToken *)pData, false); return; + } + } + + // Converts underlying value into a different type + bool Convert(fieldtype_t newType) + { + if(newType == m_type) + { + return true; + } + + bool successful = false; + void *pData = NULL; + switch(newType) + { + case FIELD_VOID: successful = true; Free(); m_type = FIELD_VOID; m_pData = NULL; break; + case FIELD_FLOAT: if(successful = AssignTo((float *)&pData)) { Set(newType, &pData); } break; + case FIELD_FLOAT64: if(successful = AssignTo((float64 *)&pData)) { Set(newType, &pData); } break; + case FIELD_INTEGER: if(successful = AssignTo((int *)&pData)) { Set(newType, &pData); } break; + case FIELD_UINT: if(successful = AssignTo((uint *)&pData)) { Set(newType, &pData); } break; + case FIELD_INTEGER64: if(successful = AssignTo((int64 *)&pData)) { Set(newType, &pData); } break; + case FIELD_UINT64: if(successful = AssignTo((uint64 *)&pData)) { Set(newType, &pData); } break; + case FIELD_BOOLEAN: if(successful = AssignTo((bool *)&pData)) { Set(newType, &pData); } break; + case FIELD_CHARACTER: if(successful = AssignTo((char *)&pData)) { Set(newType, &pData); } break; + case FIELD_STRING: if(successful = AssignTo((string_t *)&pData)) { Set(newType, &pData); } break; + case FIELD_CSTRING: successful = true; CopyData(ToString(), true); break; + case FIELD_HSCRIPT: if(successful = AssignTo((HSCRIPT *)&pData)) { Set(newType, &pData); } break; + case FIELD_EHANDLE: if(successful = AssignTo((CEntityHandle *)&pData)) { Set(newType, &pData); } break; + case FIELD_RESOURCE: if(successful = AssignTo((ResourceHandle_t *)&pData)) { Set(newType, &pData); } break; + case FIELD_UTLSTRINGTOKEN: if(successful = AssignTo((CUtlStringToken *)&pData)) { Set(newType, &pData); } break; + case FIELD_VECTOR: { Vector vec; if(successful = AssignTo(&vec)) { CopyData(vec, true); } break; } + case FIELD_VECTOR2D: { Vector2D vec; if(successful = AssignTo(&vec)) { CopyData(vec, true); } break; } + case FIELD_VECTOR4D: { Vector4D vec; if(successful = AssignTo(&vec)) { CopyData(vec, true); } break; } + case FIELD_COLOR32: { Color clr; if(successful = AssignTo(&clr)) { CopyData(clr, true); } break; } + case FIELD_QANGLE: { QAngle ang; if(successful = AssignTo(&ang)) { CopyData(ang, true); } break; } + case FIELD_QUATERNION: { Quaternion quat; if(successful = AssignTo(&quat)) { CopyData(quat, true); } break; } + } + + if(successful) + { + m_type = newType; + } + + return successful; + } + + const char *ToString() + { + static CBufferStringGrowable<200> szBuf; + AssignTo(szBuf); + return szBuf.Get(); + } + +public: + union + { + int m_int; + uint m_uint; + float m_float; + const char *m_pszString; + const Vector *m_pVector; + const QAngle *m_pQAngle; + const Vector2D *m_pVector2D; + const Vector4D *m_pVector4D; + const Quaternion *m_pQuaternion; + const Color *m_pColor; + void *m_pData; + char m_char; + bool m_bool; + HSCRIPT m_hScript; + CEntityHandle m_hEntity; + uint64 m_uint64; + int64 m_int64; + float64 m_float64; + string_t m_stringt; + CUtlStringToken m_utlStringToken; + ResourceHandle_t m_hResource; + }; + + // fieldtype_t + int16 m_type; + + // CVFlags_t flags + uint16 m_flags; +}; + +typedef CVariantBase CVariant; +typedef CVariantBase CEntityVariant; + +#endif // CVARIANT_H \ No newline at end of file diff --git a/public/vscript/ivscript.h b/public/vscript/ivscript.h index 8e26d62b..21ce4296 100644 --- a/public/vscript/ivscript.h +++ b/public/vscript/ivscript.h @@ -117,7 +117,7 @@ class CUtlBuffer; class CCommand; -struct CCommandContext; +class CCommandContext; //----------------------------------------------------------------------------- // @@ -164,75 +164,12 @@ DECLARE_POINTER_HANDLE( HSCRIPT ); // //----------------------------------------------------------------------------- +#include "variant.h" + typedef uint8 ScriptDataType_t; -struct ScriptVariant_t; +typedef CVariant ScriptVariant_t; -template struct ScriptDeducer { /*enum { FIELD_TYPE = FIELD_TYPEUNKNOWN };*/ }; -#define DECLARE_DEDUCE_FIELDTYPE( fieldType, type ) template<> struct ScriptDeducer { enum { FIELD_TYPE = fieldType }; }; - -DECLARE_DEDUCE_FIELDTYPE( FIELD_VOID, void ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT, float ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, const char * ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, char * ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, Vector ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const Vector &); -DECLARE_DEDUCE_FIELDTYPE( FIELD_INTEGER, int ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_BOOLEAN, bool ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_CHARACTER, char ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT, HSCRIPT ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_VARIANT, ScriptVariant_t ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_UINT64, uint64 ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT64, float64 ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_UINT, uint ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_QANGLE, QAngle ); -DECLARE_DEDUCE_FIELDTYPE( FIELD_QANGLE, const QAngle &); - -#define ScriptDeduceType( T ) ScriptDeducer::FIELD_TYPE - -template -inline const char * ScriptFieldTypeName() -{ - return T::using_unknown_script_type(); -} - -#define DECLARE_NAMED_FIELDTYPE( fieldType, strName ) template <> inline const char * ScriptFieldTypeName() { return strName; } -DECLARE_NAMED_FIELDTYPE( void, "void" ); -DECLARE_NAMED_FIELDTYPE( float, "float" ); -DECLARE_NAMED_FIELDTYPE( const char *, "cstring" ); -DECLARE_NAMED_FIELDTYPE( char *, "cstring" ); -DECLARE_NAMED_FIELDTYPE( Vector, "vector" ); -DECLARE_NAMED_FIELDTYPE( const Vector&, "vector" ); -DECLARE_NAMED_FIELDTYPE( int, "integer" ); -DECLARE_NAMED_FIELDTYPE( bool, "boolean" ); -DECLARE_NAMED_FIELDTYPE( char, "character" ); -DECLARE_NAMED_FIELDTYPE( HSCRIPT, "hscript" ); -DECLARE_NAMED_FIELDTYPE( ScriptVariant_t, "variant" ); -DECLARE_NAMED_FIELDTYPE( uint64, "uint64" ); -DECLARE_NAMED_FIELDTYPE( float64, "float64" ); -DECLARE_NAMED_FIELDTYPE( uint, "unsigned" ); -DECLARE_NAMED_FIELDTYPE( QAngle, "qangle" ); -DECLARE_NAMED_FIELDTYPE( const QAngle&, "qangle" ); - -inline const char * ScriptFieldTypeName( int16 eType) -{ - switch( eType ) - { - case FIELD_VOID: return "void"; - case FIELD_FLOAT: return "float"; - case FIELD_CSTRING: return "cstring"; - case FIELD_VECTOR: return "vector"; - case FIELD_INTEGER: return "integer"; - case FIELD_BOOLEAN: return "boolean"; - case FIELD_CHARACTER: return "character"; - case FIELD_HSCRIPT: return "hscript"; - case FIELD_VARIANT: return "variant"; - case FIELD_UINT64: return "uint64"; - case FIELD_FLOAT64: return "float64"; - case FIELD_UINT: return "unsigned"; - case FIELD_QANGLE: return "qangle"; - default: return "unknown_variant_type"; - } -} +#define SCRIPT_VARIANT_NULL ScriptVariant_t() //--------------------------------------------------------- @@ -317,235 +254,6 @@ struct ScriptClassDesc_t IScriptInstanceHelper * pHelper; // optional helper }; -//--------------------------------------------------------- -// A simple variant type. Intentionally not full featured (no implicit conversion, no memory management) -//--------------------------------------------------------- - -enum SVFlags_t -{ - SV_FREE = 0x01, -}; - -#pragma warning(push) -#pragma warning(disable:4800) -struct ScriptVariant_t -{ - ScriptVariant_t() : m_type( FIELD_VOID ), m_flags( 0 ) { m_pVector = 0; } - ScriptVariant_t( int val ) : m_type( FIELD_INTEGER ), m_flags( 0 ) { m_int = val;} - ScriptVariant_t( uint val) : m_type( FIELD_UINT ), m_flags( 0 ) { m_uint = val; } - ScriptVariant_t( float val ) : m_type( FIELD_FLOAT ), m_flags( 0 ) { m_float = val; } - ScriptVariant_t( float64 val ) : m_type( FIELD_FLOAT64 ), m_flags( 0 ) { m_float64 = val; } - ScriptVariant_t( char val ) : m_type( FIELD_CHARACTER ), m_flags( 0 ) { m_char = val; } - ScriptVariant_t( bool val ) : m_type( FIELD_BOOLEAN ), m_flags( 0 ) { m_bool = val; } - ScriptVariant_t( HSCRIPT val ) : m_type( FIELD_HSCRIPT ), m_flags( 0 ) { m_hScript = val; } - ScriptVariant_t( int64 val) : m_type( FIELD_INTEGER64 ), m_flags( 0 ) { m_int64 = val; } - ScriptVariant_t( uint64 val) : m_type( FIELD_UINT64), m_flags( 0 ) { m_uint64 = val; } - - ScriptVariant_t( const Vector &val, bool bCopy = false ) : m_type( FIELD_VECTOR ), m_flags( 0 ) { if ( !bCopy ) { m_pVector = &val; } else { m_pVector = new Vector( val ); m_flags |= SV_FREE; } } - ScriptVariant_t( const Vector *val, bool bCopy = false ) : m_type( FIELD_VECTOR ), m_flags( 0 ) { if ( !bCopy ) { m_pVector = val; } else { m_pVector = new Vector( *val ); m_flags |= SV_FREE; } } - ScriptVariant_t( const QAngle &val, bool bCopy = false) : m_type( FIELD_QANGLE ), m_flags( 0 ) { if ( !bCopy ) { m_pQAngle = &val; } else { m_pQAngle = new QAngle(val); m_flags |= SV_FREE; } } - ScriptVariant_t( const QAngle *val, bool bCopy = false) : m_type( FIELD_QANGLE ), m_flags( 0 ) { if ( !bCopy ) { m_pQAngle = val; } else { m_pQAngle = new QAngle(*val); m_flags |= SV_FREE; } } - ScriptVariant_t( const char *val , bool bCopy = false ) : m_type( FIELD_CSTRING ), m_flags( 0 ) { if ( !bCopy ) { m_pszString = val; } else { m_pszString = strdup( val ); m_flags |= SV_FREE; } } - - bool IsNull() const { return (m_type == FIELD_VOID ); } - - operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; } - operator uint() const { Assert( m_type == FIELD_UINT ); return m_uint; } - operator int64() const { Assert( m_type == FIELD_INTEGER64); return m_int64; } - operator uint64() const { Assert( m_type == FIELD_UINT64); return m_uint64; } - operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; } - operator float64() const { Assert( m_type == FIELD_FLOAT64 ); return m_float64; } - operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; } - operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; } - operator const QAngle &() const { Assert( m_type == FIELD_QANGLE); static QAngle angNull(0, 0, 0); return (m_pQAngle) ? *m_pQAngle : angNull; } - operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; } - operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; } - operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; } - - void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; } - void operator=( uint u ) { m_type = FIELD_UINT; m_uint = u; } - void operator=( int64 i ) { m_type = FIELD_INTEGER64; m_int64 = i; } - void operator=( uint64 u ) { m_type = FIELD_UINT64; m_uint64 = u; } - void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; } - void operator=( float64 d ) { m_type = FIELD_FLOAT64; m_float64 = d; } - void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_pVector = &vec; } - void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; } - void operator=( const QAngle &ang) { m_type = FIELD_QANGLE; m_pQAngle = ∠ } - void operator=( const QAngle *ang) { m_type = FIELD_QANGLE; m_pQAngle = ang; } - void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; } - void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; } - void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; } - void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; } - - void Free() { if ( ( m_flags & SV_FREE ) && ( m_type == FIELD_HSCRIPT || m_type == FIELD_VECTOR || m_type == FIELD_QANGLE || m_type == FIELD_CSTRING ) ) delete m_pszString; } // Generally only needed for return results - - template - T Get() - { - T value; - AssignTo( &value ); - return value; - } - - template - bool AssignTo( T *pDest ) - { - ScriptDataType_t destType = ScriptDeduceType( T ); - if ( destType == FIELD_TYPEUNKNOWN ) - { - DevWarning( "Unable to convert script variant to unknown type\n" ); - } - if ( destType == m_type ) - { - *pDest = *this; - return true; - } - - if ( m_type != FIELD_VECTOR && m_type != FIELD_QANGLE && m_type != FIELD_CSTRING && destType != FIELD_VECTOR && destType != FIELD_QANGLE && destType != FIELD_CSTRING ) - { - switch ( m_type ) - { - case FIELD_VOID: *pDest = 0; break; - case FIELD_INTEGER: *pDest = m_int; return true; - case FIELD_INTEGER64: *pDest = m_int64; return true; - case FIELD_UINT: *pDest = m_uint; return true; - case FIELD_UINT64: *pDest = m_uint64; return true; - case FIELD_FLOAT: *pDest = m_float; return true; - case FIELD_FLOAT64: *pDest = m_float64; return true; - case FIELD_CHARACTER: *pDest = m_char; return true; - case FIELD_BOOLEAN: *pDest = m_bool; return true; - case FIELD_HSCRIPT: *pDest = m_hScript; return true; - } - } - else - { - DevWarning( "No free conversion of %s script variant to %s right now\n", - ScriptFieldTypeName( m_type ), ScriptFieldTypeName() ); - if ( destType != FIELD_VECTOR && destType != FIELD_QANGLE ) - { - *pDest = 0; - } - } - return false; - } - - bool AssignTo( float *pDest ) - { - switch( m_type ) - { - case FIELD_VOID: *pDest = 0; return false; - case FIELD_INTEGER: *pDest = m_int; return true; - case FIELD_INTEGER64: *pDest = m_int64; return true; - case FIELD_UINT: *pDest = m_uint; return true; - case FIELD_UINT64: *pDest = m_uint64; return true; - case FIELD_FLOAT: *pDest = m_float; return true; - case FIELD_FLOAT64: *pDest = m_float64; return true; - case FIELD_BOOLEAN: *pDest = m_bool; return true; - default: - DevWarning( "No conversion from %s to float now\n", ScriptFieldTypeName( m_type ) ); - return false; - } - } - - bool AssignTo( int *pDest ) - { - switch( m_type ) - { - case FIELD_VOID: *pDest = 0; return false; - case FIELD_INTEGER: *pDest = m_int; return true; - case FIELD_INTEGER64: *pDest = m_int64; return true; - case FIELD_UINT: *pDest = m_uint; return true; - case FIELD_UINT64: *pDest = m_uint64; return true; - case FIELD_FLOAT: *pDest = m_float; return true; - case FIELD_FLOAT64: *pDest = m_float64; return true; - case FIELD_BOOLEAN: *pDest = m_bool; return true; - default: - DevWarning( "No conversion from %s to int now\n", ScriptFieldTypeName( m_type ) ); - return false; - } - } - - bool AssignTo( bool *pDest ) - { - switch( m_type ) - { - case FIELD_VOID: *pDest = 0; return false; - case FIELD_INTEGER: *pDest = m_int; return true; - case FIELD_INTEGER64: *pDest = m_int64; return true; - case FIELD_UINT: *pDest = m_uint; return true; - case FIELD_UINT64: *pDest = m_uint64; return true; - case FIELD_FLOAT: *pDest = m_float; return true; - case FIELD_FLOAT64: *pDest = m_float64; return true; - case FIELD_BOOLEAN: *pDest = m_bool; return true; - default: - DevWarning( "No conversion from %s to bool now\n", ScriptFieldTypeName( m_type ) ); - return false; - } - } - - bool AssignTo( char **pDest ) - { - DevWarning( "No free conversion of string or vector script variant right now\n" ); - // If want to support this, probably need to malloc string and require free on other side [3/24/2008 tom] - *pDest = (char *)""; - return false; - } - - bool AssignTo( ScriptVariant_t *pDest ) - { - pDest->m_type = m_type; - if ( m_type == FIELD_VECTOR ) - { - pDest->m_pVector = new Vector; - ((Vector *)(pDest->m_pVector))->Init( m_pVector->x, m_pVector->y, m_pVector->z ); - pDest->m_flags |= SV_FREE; - } - else if (m_type == FIELD_QANGLE) - { - pDest->m_pQAngle = new QAngle; - ((QAngle *) (pDest->m_pQAngle))->Init(m_pQAngle->x, m_pQAngle->y, m_pQAngle->z); - pDest->m_flags |= SV_FREE; - } - else if ( m_type == FIELD_CSTRING ) - { - pDest->m_pszString = strdup( m_pszString ); - pDest->m_flags |= SV_FREE; - } - else - { - pDest->m_int64 = m_int64; - } - return false; - } - - union - { - int m_int; - uint m_uint; - int64 m_int64; - uint64 m_uint64; - float m_float; - float64 m_float64; - const char * m_pszString; - const Vector * m_pVector; - const QAngle * m_pQAngle; - char m_char; - bool m_bool; - HSCRIPT m_hScript; - }; - - int16 m_type; - int16 m_flags; - -private: -}; - -#define SCRIPT_VARIANT_NULL ScriptVariant_t() - -#pragma warning(pop) - - - //----------------------------------------------------------------------------- // //-----------------------------------------------------------------------------