//========== Copyright � 2008, Valve Corporation, All rights reserved. ======== // // Purpose: Variants // // Overview // -------- // Variants are structures which may contain a number of different data types // You can query which data type is currently being used // //============================================================================= #ifndef VARIANT_H #define VARIANT_H #if defined( COMPILER_MSVC ) #pragma once #endif #include "datamap.h" #include "basehandle.h" #include "tier1/strtools.h" #include "tier1/utlstring.h" #include "../../game/shared/ehandle.h" //#include "tier1/utlstringtoken.h" //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- FORWARD_DECLARE_HANDLE( HSCRIPT ); //----------------------------------------------------------------------------- // Types not supported in datamap.h //----------------------------------------------------------------------------- enum ExtendedFieldType_t { FIELD_TYPEUNKNOWN = FIELD_TYPECOUNT, FIELD_CSTRING, FIELD_HSCRIPT, FIELD_VARIANT, FIELD_UINT64, FIELD_FLOAT64, FIELD_POSITIVEINTEGER_OR_NULL, FIELD_HSCRIPT_NEW_INSTANCE, FIELD_UINT, // Unsigned integer - it's not declared in fieldtype_t FIELD_UTLSTRINGTOKEN, FIELD_QANGLE, }; DECLARE_FIELD_SIZE( FIELD_UINT64, sizeof(uint64) ) DECLARE_FIELD_SIZE( FIELD_FLOAT64, sizeof(float64) ) DECLARE_FIELD_SIZE( FIELD_POSITIVEINTEGER_OR_NULL, sizeof(int) ) DECLARE_FIELD_SIZE( FIELD_UINT, sizeof( uint ) ) DECLARE_FIELD_SIZE( FIELD_UTLSTRINGTOKEN, sizeof( uint32 ) ) DECLARE_FIELD_SIZE( FIELD_QANGLE, sizeof( QAngle ) ) typedef int VariantDataType_t; //--------------------------------------------------------- // 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) class CVariantDefaultAllocator { public: enum { ALWAYS_COPY = 0 }; static void* Allocate( uint nSize ) { return malloc( nSize ); } static void Free( void *pMemory ) { free( pMemory ); } }; template< class CValueAllocator = CVariantDefaultAllocator > class CVariantBase { public: CVariantBase() : m_flags( 0 ), m_type( FIELD_VOID ) { m_pVector = 0; } CVariantBase( int val ) : m_flags( 0 ), m_type( FIELD_INTEGER ) { m_int = val; } CVariantBase( uint32 val ) : m_flags( 0 ), m_type( FIELD_UINT ) { m_uint = val; } // CVariantBase( int64 val ) : m_flags( 0 ), m_type( FIELD_INTEGER64 ) { m_int64 = val; } CVariantBase( uint64 val ) : m_flags( 0 ), m_type( FIELD_UINT64 ) { m_uint64 = val; } CVariantBase( float val ) : m_flags( 0 ), m_type( FIELD_FLOAT ) { m_float = val; } CVariantBase( float64 val ) : m_flags( 0 ), m_type( FIELD_FLOAT64 ) { m_float64 = val; } CVariantBase( char val ) : m_flags( 0 ), m_type( FIELD_CHARACTER ) { m_char = val; } CVariantBase( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; } CVariantBase( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; } CVariantBase( CBaseHandle val ) : m_flags( 0 ), m_type( FIELD_EHANDLE ) { m_hEntity = val.ToInt(); } // CVariantBase( CUtlStringToken val ) : m_flags( 0 ), m_type( FIELD_UTLSTRINGTOKEN ) { m_utlStringToken = val.m_nHashCode; } CVariantBase( const Vector &val, bool bCopy = false ); CVariantBase( const Vector2D &val, bool bCopy = false ); // CVariantBase( const Vector4D &val, bool bCopy = false ); CVariantBase( const Vector *val, bool bCopy = false ); CVariantBase( const char *val , bool bCopy = false ); CVariantBase( const Quaternion &val, bool bCopy = false ); CVariantBase( const CVariantBase &variant ) :m_flags( 0 ), m_type( FIELD_VOID ) { variant.AssignTo( this ); } void operator=( const CVariantBase &variant ) { variant.AssignTo( this ); } bool IsNull() const { return (m_type == FIELD_VOID ); } operator int() const { Assert( m_type == FIELD_INTEGER || m_type == FIELD_FLOAT ); return ( m_type == FIELD_INTEGER ) ? m_int : (int)m_float; } 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 { ( m_type == FIELD_INTEGER || m_type == FIELD_FLOAT ); return ( m_type == FIELD_FLOAT ) ? m_float : (float)m_int; } operator float64() const { Assert( m_type == FIELD_FLOAT64 ); return m_float64; } operator const char *() const { Assert( m_type == FIELD_CSTRING ); return m_pszString; } operator const Vector2D &() const { Assert( m_type == FIELD_VECTOR2D ); return m_pData ? *(Vector2D*)m_pData : vec2_origin; } operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); return (m_pVector) ? *m_pVector : vec3_origin; } // operator const Vector4D &() const { Assert( m_type == FIELD_VECTOR4D ); return m_pData ? *(Vector4D*)m_pData : vec4_origin; } operator const QAngle &() const { Assert( m_type == FIELD_QANGLE ); return m_pData ? *(QAngle*)m_pData : vec3_angle; } 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 CBaseHandle() const { Assert( m_type == FIELD_EHANDLE ); return CBaseHandle( m_hEntity ); } operator CBaseEntity*() const { Assert( m_type == FIELD_EHANDLE ); return CHandle(CBaseHandle( m_hEntity )); } operator const Quaternion &() const { Assert( m_type == FIELD_QUATERNION ); return m_pData ? *(Quaternion*)m_pData : quat_identity; } // operator CUtlStringToken() const { Assert( m_type == FIELD_UTLSTRINGTOKEN ); CUtlStringToken t; t.m_nHashCode = m_utlStringToken; return t; } void operator=( int i ) { Free(); m_type = FIELD_INTEGER; m_int = i; } void operator=( uint i ) { Free(); m_type = FIELD_UINT; m_uint = i; } // void operator=( int64 i ) { Free(); m_type = FIELD_INTEGER64; m_int64 = i; } void operator=( uint64 i ) { Free(); m_type = FIELD_UINT64; m_uint64 = i; } void operator=( float f ) { Free(); m_type = FIELD_FLOAT; m_float = f; } void operator=( float64 f ) { Free(); m_type = FIELD_FLOAT64; m_float64 = f; } void operator=( const Vector2D &vec ) { CopyData( vec ); } void operator=( const Vector &vec ) { CopyData( vec ); } // void operator=( const Vector4D &vec ) { CopyData( vec ); } void operator=( const QAngle &vec ) { CopyData( vec ); } void operator=( const Quaternion &q ) { CopyData( q ); } void operator=( const Vector2D *vec ) { CopyData( *vec ); } void operator=( QAngle *a ) { CopyData( *a ); } void operator=( const QAngle *a ) { CopyData( *a ); } void operator=( Vector2D *vec ) { CopyData( *vec ); } void operator=( const Vector *vec ) { CopyData( *vec ); } void operator=( Vector *vec ) { CopyData( *vec ); } // void operator=( const Vector4D *vec ) { CopyData( *vec ); } // void operator=( Vector4D *vec ) { CopyData( *vec ); } void operator=( const Quaternion *q ) { CopyData( *q ); } void operator=( Quaternion *q ) { CopyData( *q ); } void operator=( const char *psz ) { CopyData( psz ); } void operator=( char c ) { Free(); m_type = FIELD_CHARACTER; m_char = c; } void operator=( bool b ) { Free(); m_type = FIELD_BOOLEAN; m_bool = b; } void operator=( HSCRIPT h ) { Free(); m_type = FIELD_HSCRIPT; m_hScript = h; } void operator=( CBaseHandle h ) { Free(); m_type = FIELD_EHANDLE; m_hEntity = h.ToInt(); } // void operator=( CBaseEntity *pEnt ) { Free(); m_type = FIELD_EHANDLE; CBaseHandle h = pEnt; m_hEntity = h.ToInt(); } // void operator=( CUtlStringToken val ) { Free(); m_type = FIELD_UTLSTRINGTOKEN; m_utlStringToken = val.m_nHashCode; } void Free(); template T Get() const; template bool AssignTo( T *pDest ) const; bool AssignTo( float *pDest ) const; bool AssignTo( uint *pDest ) const; bool AssignTo( int *pDest ) const; bool AssignTo( bool *pDest ) const; bool AssignTo( Vector2D *pDest ) const; bool AssignTo( Vector *pDest ) const; // bool AssignTo( Vector4D *pDest ) const; bool AssignTo( QAngle *pDest ) const; bool AssignTo( Quaternion *pDest ) const; bool AssignTo( QuaternionAligned *pDest ) const { return AssignTo( (Quaternion*)pDest ); } bool AssignTo( VectorAligned *pDest ) const { return AssignTo( (Vector*)pDest ); } bool AssignTo( char *pDest, uint nBufLen ) const; bool AssignTo( CUtlString *pString ) const; bool AssignTo( const char **pszString ) const; bool AssignTo( HSCRIPT *pDest ) const; bool AssignTo( CBaseHandle *pDest ) const; bool AssignTo( CBaseEntity **pDest ) const; // bool AssignTo( CUtlStringToken *pDest ) const; template< typename T > bool AssignTo( CVariantBase *pDest ) const; int GetType() const { return m_type; } uint16 GetFlags() const { return m_flags; } void ConvertToCopiedData(bool silent = false ); private: void *Allocate( uint nSize ); template< typename T > T* Allocate(); void Free( void* pMemory ); template< typename T > void CopyData( const T &src, bool bForceCopy = false ); void CopyData( const char *pString, bool bForceCopy = false ); void CopyData( const Vector2D *src, bool bForceCopy = false ); void CopyData( const Vector *src, bool bForceCopy = false ); // void CopyData( const Vector4D *src, bool bForceCopy = false ); void CopyData( const QAngle *src, bool bForceCopy = false ); // This is not implemented. Use AssignTo( char *pDest, uint nBufLen ) instead. // Declaring this private to produce more sensible error messages. bool AssignTo( char **pDest ) const; union { int m_int; uint m_uint; float m_float; const char * m_pszString; const Vector * m_pVector; void * m_pData; char m_char; bool m_bool; HSCRIPT m_hScript; uint32 m_hEntity; // Can't use CBasEHANDLE in union because it has a nonempty constructor uint64 m_uint64; int64 m_int64; float64 m_float64; // uint32 m_utlStringToken; // Can't use CUtlStringToken in union because it has a nonempty constructor }; int16 m_type; uint16 m_flags; friend class CLuaVM; friend class CPythonVM; friend class CSquirrelVM; }; typedef CVariantBase<> CVariant; template struct VariantDeducer_t { enum { FIELD_TYPE = FIELD_TYPEUNKNOWN }; }; #define DECLARE_DEDUCE_FIELDTYPE( fieldType, type ) template<> struct VariantDeducer_t { enum { FIELD_TYPE = fieldType }; }; DECLARE_DEDUCE_FIELDTYPE( FIELD_VOID, void ); DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT, float ); //DECLARE_DEDUCE_FIELDTYPE( FIELD_INTEGER64, int64 ); DECLARE_DEDUCE_FIELDTYPE( FIELD_UINT64, uint64 ); DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT64, float64 ); DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, const char * ); DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, char * ); DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR2D, Vector2D ); DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR2D, const Vector2D & ); DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, Vector ); DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const Vector & ); // DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR4D, Vector4D ); // DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR4D, const Vector4D & ); DECLARE_DEDUCE_FIELDTYPE( FIELD_QANGLE, QAngle ); DECLARE_DEDUCE_FIELDTYPE( FIELD_QANGLE, const QAngle & ); DECLARE_DEDUCE_FIELDTYPE( FIELD_INTEGER, int ); DECLARE_DEDUCE_FIELDTYPE( FIELD_UINT, uint ); DECLARE_DEDUCE_FIELDTYPE( FIELD_BOOLEAN, bool ); DECLARE_DEDUCE_FIELDTYPE( FIELD_CHARACTER, char ); DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT, HSCRIPT ); DECLARE_DEDUCE_FIELDTYPE( FIELD_VARIANT, CVariant ); DECLARE_DEDUCE_FIELDTYPE( FIELD_EHANDLE, CBaseHandle ); DECLARE_DEDUCE_FIELDTYPE( FIELD_QUATERNION, Quaternion ); DECLARE_DEDUCE_FIELDTYPE( FIELD_QUATERNION, const Quaternion & ); //DECLARE_DEDUCE_FIELDTYPE( FIELD_UTLSTRINGTOKEN, CUtlStringToken ); #define VariantDeduceType( T ) ((fieldtype_t)VariantDeducer_t::FIELD_TYPE) template inline const char * VariantFieldTypeName() { return T::using_unknown_variant_type(); } #define DECLARE_NAMED_FIELDTYPE( fieldType, strName ) template <> inline const char * VariantFieldTypeName() { 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( Vector2D, "vector2d" ); DECLARE_NAMED_FIELDTYPE( const Vector2D&, "vector2d" ); DECLARE_NAMED_FIELDTYPE( Vector, "vector" ); DECLARE_NAMED_FIELDTYPE( const Vector&, "vector" ); // DECLARE_NAMED_FIELDTYPE( Vector4D, "vector4d" ); // DECLARE_NAMED_FIELDTYPE( const Vector4D&, "vector4d" ); DECLARE_NAMED_FIELDTYPE( int, "integer" ); DECLARE_NAMED_FIELDTYPE( int64, "int64" ); DECLARE_NAMED_FIELDTYPE( uint64,"uint64" ); DECLARE_NAMED_FIELDTYPE( float64, "float64" ); DECLARE_NAMED_FIELDTYPE( bool, "boolean" ); DECLARE_NAMED_FIELDTYPE( char, "character" ); DECLARE_NAMED_FIELDTYPE( HSCRIPT, "hscript" ); DECLARE_NAMED_FIELDTYPE( CVariant, "variant" ); DECLARE_NAMED_FIELDTYPE( CBaseHandle, "ehandle" ); DECLARE_NAMED_FIELDTYPE( Quaternion, "quaternion" ); //DECLARE_NAMED_FIELDTYPE( CUtlStringToken, "utlstringtoken" ); inline const char * VariantFieldTypeName( int16 eType ) { switch( eType ) { case FIELD_VOID: return "void"; case FIELD_FLOAT: return "float"; case FIELD_CSTRING: return "cstring"; case FIELD_VECTOR2D:return "vector2d"; case FIELD_VECTOR: return "vector"; // case FIELD_VECTOR4D:return "vector4d"; case FIELD_QANGLE: return "qangle"; case FIELD_INTEGER: return "integer"; case FIELD_UINT: return "unsigned"; // case FIELD_INTEGER64: return "int64"; case FIELD_UINT64: return "uint64"; case FIELD_FLOAT64: return "float64"; case FIELD_BOOLEAN: return "boolean"; case FIELD_CHARACTER: return "character"; case FIELD_HSCRIPT: return "hscript"; case FIELD_VARIANT: return "variant"; case FIELD_EHANDLE: return "ehandle"; case FIELD_QUATERNION: return "quaternion"; case FIELD_UTLSTRINGTOKEN: return "utlstringtoken"; default: return "unknown_variant_type"; } } typedef CVariantBase<> CVariant; #define VARIANT_NULL CVariant() #pragma warning(pop) //----------------------------------------------------------------------------- // Default allocator //----------------------------------------------------------------------------- template< class CValueAllocator > inline void *CVariantBase::Allocate( uint nSize ) { return CValueAllocator::Allocate( nSize ); } template< class CValueAllocator > template< typename T > inline T* CVariantBase::Allocate() { // ASSERT_MEMALLOC_WILL_ALIGN( T ); return (T*)CValueAllocator::Allocate( sizeof(T) ); } template< class CValueAllocator > inline void CVariantBase::Free( void* pMemory ) { return CValueAllocator::Free( pMemory ); } //----------------------------------------------------------------------------- // Constructors //----------------------------------------------------------------------------- template< class CValueAllocator > inline CVariantBase::CVariantBase( const Vector &val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) { CopyData( val, true ); } template< class CValueAllocator > inline CVariantBase::CVariantBase( const Vector *val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) { CopyData( *val, bCopy ); } template< class CValueAllocator > inline CVariantBase::CVariantBase( const Vector2D &val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) { CopyData( val, bCopy ); } // template< class CValueAllocator > // inline CVariantBase::CVariantBase( const Vector4D &val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) // { // CopyData( val, bCopy ); // } template< class CValueAllocator > inline CVariantBase::CVariantBase( const char *val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) { CopyData( val, bCopy ); } template< class CValueAllocator > inline CVariantBase::CVariantBase( const Quaternion &val, bool bCopy ) : m_flags( 0 ), m_type( FIELD_VOID ) { CopyData( val, bCopy ); } //----------------------------------------------------------------------------- // Data freeing //----------------------------------------------------------------------------- template< class CValueAllocator > inline void CVariantBase::Free() { if ( m_flags & SV_FREE ) { Free( m_pData ); m_flags &= ~SV_FREE; } m_int64 = 0LL; m_type = FIELD_VOID; } //----------------------------------------------------------------------------- // Copy helper //----------------------------------------------------------------------------- template< class CValueAllocator > template< typename T > inline void CVariantBase::CopyData( const T &src, bool bForceCopy ) { COMPILE_TIME_ASSERT( ( ExtendedFieldType_t )VariantDeduceType( T ) != FIELD_TYPEUNKNOWN ); Free(); m_type = VariantDeduceType( T ); if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) { m_pData = Allocate(); *(T*)m_pData = src; m_flags |= SV_FREE; } else { m_pData = const_cast< T* >( &src ); } } template< class CValueAllocator > inline void CVariantBase::CopyData( const Vector2D *src, bool bForceCopy ) { Free(); m_type = FIELD_VECTOR2D; if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) { m_pData = Allocate(); *(Vector2D*)m_pData = *src; m_flags |= SV_FREE; } else { m_pData = (void *)src; } } template< class CValueAllocator > inline void CVariantBase::CopyData( const Vector *src, bool bForceCopy ) { Free(); m_type = FIELD_VECTOR; if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) { m_pData = Allocate(); *(Vector*)m_pData = *src; m_flags |= SV_FREE; } else { m_pData = (void *)src; } } // template< class CValueAllocator > // inline void CVariantBase::CopyData( const Vector4D *src, bool bForceCopy ) // { // Free(); // m_type = FIELD_VECTOR4D; // if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) // { // m_pData = Allocate(); // *(Vector4D*)m_pData = *src; // m_flags |= SV_FREE; // } // else // { // m_pData = (void *)src; // } // } template< class CValueAllocator > inline void CVariantBase::CopyData( const QAngle *src, bool bForceCopy ) { Free(); m_type = FIELD_QANGLE; if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) { m_pData = Allocate(); *(QAngle*)m_pData = *src; m_flags |= SV_FREE; } else { m_pData = (void *)src; } } template< class CValueAllocator > inline void CVariantBase::CopyData( const char *pString, bool bForceCopy ) { Free(); m_type = FIELD_CSTRING; if ( CValueAllocator::ALWAYS_COPY || bForceCopy ) { int nLen = V_strlen( pString ) + 1; m_pszString = (char *)Allocate( nLen ); memcpy( const_cast< char* >( m_pszString ), pString, nLen ); m_flags |= SV_FREE; } else { m_pszString = pString; } } template< class CValueAllocator > void CVariantBase::ConvertToCopiedData( bool silent ) { if ( ( m_flags & SV_FREE ) == 0 ) { switch( m_type ) { case FIELD_CSTRING: CopyData( m_pszString, true ); break; case FIELD_VECTOR2D: CopyData( *(Vector2D*)m_pData, true ); break; case FIELD_VECTOR: CopyData( *m_pVector, true ); break; // case FIELD_VECTOR4D: CopyData( *(Vector4D*)m_pData, true ); break; case FIELD_QANGLE: CopyData( *(QAngle*)m_pData, true ); break; case FIELD_QUATERNION: CopyData( *(Quaternion*)m_pData, true ); break; default: if (!silent) Warning( "Attempted to ConvertToCopiedData for unsupported type (%d)\n", m_type); break; } } } //----------------------------------------------------------------------------- // Type converting get operations //----------------------------------------------------------------------------- template< class CValueAllocator > template inline T CVariantBase::Get() const { T value{}; AssignTo( &value ); return value; } template< class CValueAllocator > template inline bool CVariantBase::AssignTo( T *pDest ) const { VariantDataType_t destType = VariantDeduceType( T ); if ( destType == FIELD_TYPEUNKNOWN ) { Warning( "Unable to convert variant to unknown type\n" ); } if ( destType == m_type ) { *pDest = *this; return true; } if ( m_type != FIELD_VECTOR2D && m_type != FIELD_VECTOR && /*m_type != FIELD_VECTOR4D &&*/ m_type != FIELD_QANGLE &&m_type != FIELD_QUATERNION && m_type != FIELD_CSTRING && destType != FIELD_VECTOR2D && destType != FIELD_VECTOR && /*destType != FIELD_VECTOR4D &&*/ destType != FIELD_QANGLE && destType != FIELD_QUATERNION && destType != FIELD_CSTRING ) { switch ( m_type ) { case FIELD_VOID: *pDest = 0; break; case FIELD_INTEGER: *pDest = m_int; return true; case FIELD_UINT: *pDest = m_uint; return true; case FIELD_FLOAT: *pDest = m_float; 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 { Warning( "No free conversion of %s variant to %s right now\n", VariantFieldTypeName( m_type ), VariantFieldTypeName() ); if ( destType != FIELD_VECTOR ) { *pDest = 0; } } return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( HSCRIPT *pDest ) const { switch( m_type ) { case FIELD_HSCRIPT: *pDest = m_hScript; return true; default: Warning( "No free conversion of %s variant to HSCRIPT right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } // we _could_ do crazy string conversions here, but probably shouldnt template< class CValueAllocator > inline bool CVariantBase::AssignTo( CBaseHandle *pDest ) const { switch( m_type ) { case FIELD_EHANDLE: *pDest = CHandle< CBaseEntity >(m_hEntity); return true; default: Warning( "No free conversion of %s variant to EHANDLE right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( CBaseEntity **pDest ) const { switch( m_type ) { case FIELD_EHANDLE: *pDest = CHandle< CBaseEntity >(m_hEntity); return true; default: Warning( "No free conversion of %s variant to CBaseEntity * right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } // template< class CValueAllocator > // inline bool CVariantBase::AssignTo( CUtlStringToken *pDest ) const // { // switch( m_type ) // { // case FIELD_UTLSTRINGTOKEN: pDest->m_nHashCode = m_utlStringToken; return true; // case FIELD_CSTRING: *pDest = MakeStringToken( m_pszString ); return true; // default: // Warning( "No free conversion of %s variant to CUtlStringToken right now\n", VariantFieldTypeName( m_type ) ); // break; // } // return false; // } template< class CValueAllocator > inline bool CVariantBase::AssignTo( Vector2D *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = vec2_origin; return false; case FIELD_VECTOR2D:*pDest = *(Vector2D*)m_pData; return true; case FIELD_CSTRING: { int nParsed = sscanf( m_pszString, "%f %f", &pDest->x, &pDest->y ); if ( nParsed == 2 ) return true; *pDest = vec2_origin; return false; } break; default: Warning( "No free conversion of %s variant to Vector2D right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( Vector *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = vec3_origin; return false; case FIELD_QANGLE: *pDest = *(Vector*)m_pData; return true; // Should we allow this free assignment? case FIELD_VECTOR: *pDest = *m_pVector; return true; case FIELD_CSTRING: { int nParsed = sscanf( m_pszString, "%f %f %f", &pDest->x, &pDest->y, &pDest->z ); if ( nParsed == 3 ) return true; *pDest = vec3_origin; return false; } break; default: Warning( "No free conversion of %s variant to Vector right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( QAngle *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = vec3_angle; return false; case FIELD_VECTOR: *pDest = *(QAngle*)m_pVector; return true; // Should we allow this free assignment? case FIELD_QANGLE: *pDest = *(QAngle*)m_pData; return true; case FIELD_CSTRING: { int nParsed = sscanf( m_pszString, "%f %f %f", &pDest->x, &pDest->y, &pDest->z ); if ( nParsed == 3 ) return true; *pDest = vec3_angle; return false; } break; case FIELD_QUATERNION: QuaternionAngles( *(Quaternion*)m_pData, *pDest ); return true; default: Warning( "No free conversion of %s variant to QAngle right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } // template< class CValueAllocator > // inline bool CVariantBase::AssignTo( Vector4D *pDest ) const // { // switch( m_type ) // { // case FIELD_VOID: *pDest = vec4_origin; return false; // case FIELD_VECTOR4D:*pDest = *(Vector4D*)m_pData; return true; // case FIELD_CSTRING: // { // int nParsed = sscanf( m_pszString, "%f %f %f %f", &pDest->x, &pDest->y, &pDest->z, &pDest->w ); // if ( nParsed == 4 ) // return true; // *pDest = vec4_origin; // return false; // } // break; // // default: // Warning( "No free conversion of %s variant to Vector4D right now\n", VariantFieldTypeName( m_type ) ); // break; // } // return false; // } template< class CValueAllocator > inline bool CVariantBase::AssignTo( Quaternion *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = quat_identity; return false; case FIELD_QUATERNION: *pDest = *(Quaternion*)m_pData; return true; case FIELD_CSTRING: { int nParsed = sscanf( m_pszString, "%f %f %f %f", &pDest->x, &pDest->y, &pDest->z, &pDest->w ); if ( nParsed == 4 ) return true; *pDest = quat_identity; return false; } break; case FIELD_QANGLE: AngleQuaternion( *(QAngle*)m_pData, *pDest ); return true; default: Warning( "No free conversion of %s variant to Quaternion right now\n", VariantFieldTypeName( m_type ) ); break; } return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( float *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = 0; return false; case FIELD_INTEGER: *pDest = m_int; return true; case FIELD_UINT: *pDest = m_uint; 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: Warning( "No conversion from %s to float now\n", VariantFieldTypeName( m_type ) ); return false; } } template< class CValueAllocator > inline bool CVariantBase::AssignTo( int *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = 0; return false; case FIELD_INTEGER: *pDest = m_int; return true; case FIELD_UINT: *pDest = m_uint; return true; case FIELD_FLOAT: *pDest = m_float; return true; case FIELD_BOOLEAN: *pDest = m_bool; return true; case FIELD_CSTRING: *pDest = atoi( m_pszString ); return true; default: Warning( "No conversion from %s to int now\n", VariantFieldTypeName( m_type ) ); return false; } } template< class CValueAllocator > inline bool CVariantBase::AssignTo( uint *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = 0; return false; // case FIELD_INTEGER64: *pDest = (uint)clamp( m_int, UINT_MIN, UINT_MAX ); return true; case FIELD_UINT64: *pDest = (uint)clamp( m_uint64, 0/*UINT_MIN*/, UINT_MAX ); return true; case FIELD_BOOLEAN: *pDest = m_bool; return true; case FIELD_INTEGER: if ( m_int < 0 ) return false; *pDest = (uint)clamp( m_int, 0, UINT_MAX ); return true; case FIELD_UINT: *pDest = m_uint; return true; default: Warning( "No conversion from %s to int now\n", VariantFieldTypeName( m_type ) ); return false; } } template< class CValueAllocator > inline bool CVariantBase::AssignTo( bool *pDest ) const { switch( m_type ) { case FIELD_VOID: *pDest = 0; return false; case FIELD_INTEGER: *pDest = (m_int != 0); return true; case FIELD_UINT: *pDest = (m_uint != 0); return true; case FIELD_FLOAT: *pDest = (m_float != 0.0f); return true; case FIELD_BOOLEAN: *pDest = m_bool; return true; case FIELD_CSTRING: if( !V_strcmp( m_pszString, "0" ) || !V_strcmp( m_pszString, "false" ) || !V_strcmp( m_pszString, "no" ) ) { *pDest = false; return true; } else if( !V_strcmp( m_pszString, "1" ) || !V_strcmp( m_pszString, "true" ) || !V_strcmp( m_pszString, "yes" ) ) { *pDest = true; return true; } else { Warning("Invalid conversion : CString '%s' to bool\n", m_pszString ); return false; } default: Warning( "No conversion from %s to bool now\n", VariantFieldTypeName( m_type ) ); return false; } } template< class CValueAllocator > inline bool CVariantBase::AssignTo( char *pDest, uint nBufLen ) const { switch( m_type ) { case FIELD_VOID: *pDest = 0; return false; case FIELD_INTEGER: V_snprintf( pDest, nBufLen, "%d", m_int ); return true; case FIELD_UINT: V_snprintf( pDest, nBufLen, "%u", m_uint ); return true; case FIELD_FLOAT: V_snprintf( pDest, nBufLen, "%f", m_float ); return true; case FIELD_FLOAT64: V_snprintf( pDest, nBufLen, "%f", m_float64 ); return true; case FIELD_BOOLEAN: V_snprintf( pDest, nBufLen, "%s", m_bool ? "true" : "false" ); return true; case FIELD_CHARACTER: V_snprintf( pDest, nBufLen, "%c", m_char ); return true; case FIELD_CSTRING: V_strncpy( pDest, m_pszString, nBufLen ); return true; case FIELD_VECTOR2D: { Vector2D *q = (Vector2D*)m_pData; V_snprintf( pDest, nBufLen, "%f %f", q->x, q->y ); return true; } case FIELD_VECTOR: V_snprintf( pDest, nBufLen, "%f %f %f", m_pVector->x, m_pVector->y, m_pVector->z ); return true; case FIELD_QANGLE: { QAngle *q = (QAngle*)m_pData; V_snprintf( pDest, nBufLen, "%f %f %f", q->x, q->y, q->z ); return true; } // case FIELD_VECTOR4D: // { // Vector4D *q = (Vector4D*)m_pData; // V_snprintf( pDest, nBufLen, "%f %f %f %f", q->x, q->y, q->z, q->w ); // return true; // } case FIELD_QUATERNION: { Quaternion *q = (Quaternion*)m_pData; V_snprintf( pDest, nBufLen, "%f %f %f %f", q->x, q->y, q->z, q->w ); return true; } } Warning( "No conversion from %s to string at the moment!\n", VariantFieldTypeName( m_type ) ); *pDest = 0; return false; } template< class CValueAllocator > inline bool CVariantBase::AssignTo( CUtlString *pString ) const { int nLen = ( m_type != FIELD_CSTRING ) ? 256 : V_strlen( m_pszString ) + 1; pString->SetLength( nLen ); return AssignTo( pString->GetForModify(), uint( nLen ) ); } template< class CValueAllocator > inline bool CVariantBase::AssignTo( const char **pszString ) const { if ( m_type != FIELD_CSTRING ) { Warning( "CVariantBase::AssignTo: Using const char * but type was not FIELD_CSTRING. You might want to use CUtlString instead or the script passed an invalid param to a string param/table. Returning NULL.\n" ); return NULL; } return m_pszString; } template< class CValueAllocator > template< class T > inline bool CVariantBase::AssignTo( CVariantBase *pDest ) const { pDest->Free(); switch ( m_type ) { case FIELD_CSTRING: pDest->CopyData( m_pszString, true ); return true; case FIELD_VECTOR2D: pDest->CopyData( *(Vector2D*)m_pData, true ); return true; case FIELD_VECTOR: pDest->CopyData( m_pVector, true ); return true; // case FIELD_VECTOR4D: // pDest->CopyData( *(Vector4D*)m_pData, true ); // return true; case FIELD_QANGLE: pDest->CopyData( *(QAngle*)m_pData, true ); return true; case FIELD_QUATERNION: pDest->CopyData( *(Quaternion*)m_pData, true ); return true; default: pDest->m_type = m_type; memcpy( &pDest->m_int64, &m_int64, sizeof( m_int64 ) ); return true; } } // overloading == as an external function template< class CValueAllocator1, class CValueAllocator2 > inline bool operator ==( const CVariantBase & v1, const CVariantBase& v2) { if ( v1.m_type != v2.m_type ) return false; switch ( v1.m_type ) { case FIELD_INTEGER: { return v1.m_int == v2.m_int; } case FIELD_UINT: { return v1.m_uint == v2.m_uint; } case FIELD_FLOAT: { return v1.m_float == v2.m_float; } case FIELD_CHARACTER: { return v1.m_char == v2.m_char; } case FIELD_BOOLEAN: { return v1.m_bool == v2.m_bool; } case FIELD_HSCRIPT: { return v1.m_hScript == v2.m_hScript; } case FIELD_UTLSTRINGTOKEN: { return v1.m_utlStringToken == v2.m_utlStringToken; } } return false; } // overloading != as an external function template< class CValueAllocator1, class CValueAllocator2 > inline bool operator !=( const CVariantBase & v1, const CVariantBase& v2) { return !( v1 == v2 ); } #endif // VARIANT_H