mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-01-11 11:22:09 +08:00
1028 lines
36 KiB
C++
1028 lines
36 KiB
C++
#ifndef KEYVALUES3_H
|
|
#define KEYVALUES3_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "tier0/platform.h"
|
|
#include "tier0/dbg.h"
|
|
#include "tier1/bufferstring.h"
|
|
#include "tier1/generichash.h"
|
|
#include "tier1/strtools.h"
|
|
#include "tier1/utlbuffer.h"
|
|
#include "tier1/utlhashtable.h"
|
|
#include "tier1/utlleanvector.h"
|
|
#include "tier1/utlmap.h"
|
|
#include "tier1/utlstring.h"
|
|
#include "tier1/utlsymbollarge.h"
|
|
#include "mathlib/vector4d.h"
|
|
#include "Color.h"
|
|
#include "entityhandle.h"
|
|
|
|
#include "tier0/memdbgon.h"
|
|
|
|
class KeyValues3;
|
|
class CKeyValues3Array;
|
|
class CKeyValues3Table;
|
|
class CKeyValues3Cluster;
|
|
class CKeyValues3ArrayCluster;
|
|
class CKeyValues3TableCluster;
|
|
class CKeyValues3Context;
|
|
struct KV1ToKV3Translation_t;
|
|
struct KV3ToKV1Translation_t;
|
|
|
|
/*
|
|
KeyValues3 is a data storage format. See https://developer.valvesoftware.com/wiki/KeyValues3
|
|
Supports various specific data types targeted at the Source2.
|
|
Each specific type corresponds to one of the basic types.
|
|
|
|
There are 2 ways to create KeyValues3:
|
|
|
|
1. Via CKeyValues3Context:
|
|
- KV's, arrays and tables are stored in fixed memory blocks (clusters) and therefore memory is allocated only when clusters are created.
|
|
- Supports metadata and some other things.
|
|
|
|
2. Directly through the constructor.
|
|
*/
|
|
|
|
struct KV3ID_t
|
|
{
|
|
const char* m_name;
|
|
uint64 m_data1;
|
|
uint64 m_data2;
|
|
};
|
|
|
|
const KV3ID_t g_KV3Encoding_Text =
|
|
{
|
|
"text",
|
|
0x41C58A33E21C7F3Cull,
|
|
0xDAA323A6DA77799ull
|
|
};
|
|
|
|
const KV3ID_t g_KV3Format_Generic =
|
|
{
|
|
"generic",
|
|
0x469806E97412167Cull,
|
|
0xE73790B53EE6F2AFull
|
|
};
|
|
|
|
enum KV1TextEscapeBehavior_t
|
|
{
|
|
KV1TEXT_ESC_BEHAVIOR_UNK1 = 0,
|
|
KV1TEXT_ESC_BEHAVIOR_UNK2 = 1,
|
|
};
|
|
|
|
enum KV3SaveTextFlags_t
|
|
{
|
|
KV3_SAVE_TEXT_NONE = 0,
|
|
KV3_SAVE_TEXT_TAGGED = (1 << 0), // adds subtype name before value
|
|
};
|
|
|
|
PLATFORM_OVERLOAD void DebugPrintKV3( const KeyValues3* kv );
|
|
|
|
// When using some LoadKV3/SaveKV3 functions, KV3ID_t structures must be filled in, which specify the format or encoding of the data.
|
|
|
|
PLATFORM_OVERLOAD bool LoadKV3( CKeyValues3Context* context, CUtlString* error, CUtlBuffer* input, const KV3ID_t& format, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3( KeyValues3* kv, CUtlString* error, CUtlBuffer* input, const KV3ID_t& format, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3( KeyValues3* kv, CUtlString* error, const char* input, const KV3ID_t& format, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromFile( CKeyValues3Context* context, CUtlString* error, const char* filename, const char* path, const KV3ID_t& format );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromFile( KeyValues3* kv, CUtlString* error, const char* filename, const char* path, const KV3ID_t& format );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromJSON( KeyValues3* kv, CUtlString* error, const char* input, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromJSONFile( KeyValues3* kv, CUtlString* error, const char* path, const char* filename );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromKV1File( KeyValues3* kv, CUtlString* error, const char* path, const char* filename, KV1TextEscapeBehavior_t esc_behavior );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromKV1Text( KeyValues3* kv, CUtlString* error, const char* input, KV1TextEscapeBehavior_t esc_behavior, const char* kv_name, bool unk );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromKV1Text_Translated( KeyValues3* kv, CUtlString* error, const char* input, KV1TextEscapeBehavior_t esc_behavior, const KV1ToKV3Translation_t* translation, int unk1, const char* kv_name, bool unk2 );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromKV3OrKV1( KeyValues3* kv, CUtlString* error, CUtlBuffer* input, const KV3ID_t& format, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3FromOldSchemaText( KeyValues3* kv, CUtlString* error, CUtlBuffer* input, const KV3ID_t& format, const char* kv_name );
|
|
PLATFORM_OVERLOAD bool LoadKV3Text_NoHeader( KeyValues3* kv, CUtlString* error, const char* input, const KV3ID_t& format, const char* kv_name );
|
|
|
|
PLATFORM_OVERLOAD bool SaveKV3( const KV3ID_t& encoding, const KV3ID_t& format, const KeyValues3* kv, CUtlString* error, CUtlBuffer* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3AsJSON( const KeyValues3* kv, CUtlString* error, CUtlBuffer* output );
|
|
PLATFORM_OVERLOAD bool SaveKV3AsJSON( const KeyValues3* kv, CUtlString* error, CUtlString* output );
|
|
PLATFORM_OVERLOAD bool SaveKV3AsKV1Text( const KeyValues3* kv, CUtlString* error, CUtlBuffer* output, KV1TextEscapeBehavior_t esc_behavior );
|
|
PLATFORM_OVERLOAD bool SaveKV3AsKV1Text_Translated( const KeyValues3* kv, CUtlString* error, CUtlBuffer* output, KV1TextEscapeBehavior_t esc_behavior, const KV3ToKV1Translation_t* translation, int unk );
|
|
PLATFORM_OVERLOAD bool SaveKV3Text_NoHeader( const KeyValues3* kv, CUtlString* error, CBufferString* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3Text_NoHeader( const KeyValues3* kv, CUtlString* error, CUtlBuffer* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3Text_NoHeader( const KeyValues3* kv, CUtlString* error, CUtlString* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3Text_ToString( const KV3ID_t& format, const KeyValues3* kv, CUtlString* error, CBufferString* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3Text_ToString( const KV3ID_t& format, const KeyValues3* kv, CUtlString* error, CUtlString* output, uint flags = KV3_SAVE_TEXT_NONE );
|
|
PLATFORM_OVERLOAD bool SaveKV3ToFile( const KV3ID_t& encoding, const KV3ID_t& format, const KeyValues3* kv, CUtlString* error, const char* filename, const char* path, uint flags = KV3_SAVE_TEXT_NONE );
|
|
|
|
typedef int32 KV3MemberId_t;
|
|
#define KV3_INVALID_MEMBER ((KV3MemberId_t)-1)
|
|
|
|
enum
|
|
{
|
|
KV3_CONTEXT_SIZE = 1584
|
|
};
|
|
|
|
enum
|
|
{
|
|
KV3_CLUSTER_MAX_ELEMENTS = 63
|
|
};
|
|
|
|
enum KV3Type_t : uint8
|
|
{
|
|
KV3_TYPE_INVALID = 0,
|
|
KV3_TYPE_NULL,
|
|
KV3_TYPE_BOOL,
|
|
KV3_TYPE_INT,
|
|
KV3_TYPE_UINT,
|
|
KV3_TYPE_DOUBLE,
|
|
KV3_TYPE_STRING,
|
|
KV3_TYPE_BINARY_BLOB,
|
|
KV3_TYPE_ARRAY,
|
|
KV3_TYPE_TABLE,
|
|
};
|
|
|
|
enum KV3TypeOpt_t : uint8
|
|
{
|
|
KV3_TYPEOPT_NONE = 0,
|
|
|
|
KV3_TYPEOPT_STRING_SHORT,
|
|
KV3_TYPEOPT_STRING_EXTERN,
|
|
|
|
KV3_TYPEOPT_BINARY_BLOB_EXTERN,
|
|
|
|
KV3_TYPEOPT_ARRAY_FLOAT32,
|
|
KV3_TYPEOPT_ARRAY_FLOAT64,
|
|
KV3_TYPEOPT_ARRAY_INT16,
|
|
KV3_TYPEOPT_ARRAY_INT32,
|
|
KV3_TYPEOPT_ARRAY_UINT8_SHORT,
|
|
KV3_TYPEOPT_ARRAY_INT16_SHORT,
|
|
};
|
|
|
|
enum KV3TypeEx_t : uint8
|
|
{
|
|
KV3_TYPEEX_INVALID = 0,
|
|
KV3_TYPEEX_NULL,
|
|
KV3_TYPEEX_BOOL,
|
|
KV3_TYPEEX_INT,
|
|
KV3_TYPEEX_UINT,
|
|
KV3_TYPEEX_DOUBLE,
|
|
|
|
KV3_TYPEEX_STRING = KV3_TYPE_STRING,
|
|
KV3_TYPEEX_STRING_SHORT = (KV3_TYPEEX_STRING|(KV3_TYPEOPT_STRING_SHORT << 4)),
|
|
KV3_TYPEEX_STRING_EXTERN = (KV3_TYPEEX_STRING|(KV3_TYPEOPT_STRING_EXTERN << 4)),
|
|
|
|
KV3_TYPEEX_BINARY_BLOB = KV3_TYPE_BINARY_BLOB,
|
|
KV3_TYPEEX_BINARY_BLOB_EXTERN = (KV3_TYPEEX_BINARY_BLOB|(KV3_TYPEOPT_BINARY_BLOB_EXTERN << 4)),
|
|
|
|
KV3_TYPEEX_ARRAY = KV3_TYPE_ARRAY,
|
|
KV3_TYPEEX_ARRAY_FLOAT32 = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_FLOAT32 << 4)),
|
|
KV3_TYPEEX_ARRAY_FLOAT64 = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_FLOAT64 << 4)),
|
|
KV3_TYPEEX_ARRAY_INT16 = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_INT16 << 4)),
|
|
KV3_TYPEEX_ARRAY_INT32 = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_INT32 << 4)),
|
|
KV3_TYPEEX_ARRAY_UINT8_SHORT = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_UINT8_SHORT << 4)),
|
|
KV3_TYPEEX_ARRAY_INT16_SHORT = (KV3_TYPEEX_ARRAY|(KV3_TYPEOPT_ARRAY_INT16_SHORT << 4)),
|
|
|
|
KV3_TYPEEX_TABLE = KV3_TYPE_TABLE,
|
|
};
|
|
|
|
enum KV3SubType_t : uint8
|
|
{
|
|
KV3_SUBTYPE_INVALID = 0,
|
|
|
|
// string types
|
|
KV3_SUBTYPE_RESOURCE,
|
|
KV3_SUBTYPE_RESOURCE_NAME,
|
|
KV3_SUBTYPE_PANORAMA,
|
|
KV3_SUBTYPE_SOUNDEVENT,
|
|
|
|
KV3_SUBTYPE_SUBCLASS, // table type
|
|
KV3_SUBTYPE_ENTITY_NAME, // string type
|
|
KV3_SUBTYPE_UNSPECIFIED,
|
|
KV3_SUBTYPE_NULL,
|
|
KV3_SUBTYPE_BINARY_BLOB,
|
|
KV3_SUBTYPE_ARRAY,
|
|
KV3_SUBTYPE_TABLE,
|
|
KV3_SUBTYPE_BOOL8,
|
|
KV3_SUBTYPE_CHAR8,
|
|
KV3_SUBTYPE_UCHAR32,
|
|
KV3_SUBTYPE_INT8,
|
|
KV3_SUBTYPE_UINT8,
|
|
KV3_SUBTYPE_INT16,
|
|
KV3_SUBTYPE_UINT16,
|
|
KV3_SUBTYPE_INT32,
|
|
KV3_SUBTYPE_UINT32,
|
|
KV3_SUBTYPE_INT64,
|
|
KV3_SUBTYPE_UINT64,
|
|
KV3_SUBTYPE_FLOAT32,
|
|
KV3_SUBTYPE_FLOAT64,
|
|
KV3_SUBTYPE_STRING,
|
|
KV3_SUBTYPE_POINTER,
|
|
KV3_SUBTYPE_COLOR32,
|
|
|
|
// vector types
|
|
KV3_SUBTYPE_VECTOR,
|
|
KV3_SUBTYPE_VECTOR2D,
|
|
KV3_SUBTYPE_VECTOR4D,
|
|
KV3_SUBTYPE_ROTATION_VECTOR,
|
|
KV3_SUBTYPE_QUATERNION,
|
|
KV3_SUBTYPE_QANGLE,
|
|
KV3_SUBTYPE_MATRIX3X4,
|
|
KV3_SUBTYPE_TRANSFORM,
|
|
|
|
KV3_SUBTYPE_STRING_TOKEN,
|
|
KV3_SUBTYPE_EHANDLE,
|
|
};
|
|
|
|
enum KV3ArrayAllocType_t
|
|
{
|
|
KV3_ARRAY_ALLOC_EXTERN = 0,
|
|
KV3_ARRAY_ALLOC_NORMAL = 1,
|
|
KV3_ARRAY_ALLOC_EXTERN_FREE = 2,
|
|
};
|
|
|
|
enum KV3MetaDataFlags_t
|
|
{
|
|
KV3_METADATA_MULTILINE_STRING = (1 << 0),
|
|
KV3_METADATA_SINGLE_QUOTED_STRING = (1 << 1),
|
|
};
|
|
|
|
struct KV3MetaData_t
|
|
{
|
|
KV3MetaData_t() : m_nLine( 0 ), m_nColumn( 0 ), m_nFlags( 0 ) {}
|
|
~KV3MetaData_t() {}
|
|
|
|
void Clear()
|
|
{
|
|
m_nLine = 0;
|
|
m_nColumn = 0;
|
|
m_nFlags = 0;
|
|
m_sName = CUtlSymbolLarge();
|
|
m_Comments.RemoveAll();
|
|
}
|
|
|
|
void Purge()
|
|
{
|
|
m_nLine = 0;
|
|
m_nColumn = 0;
|
|
m_nFlags = 0;
|
|
m_sName = CUtlSymbolLarge();
|
|
m_Comments.Purge();
|
|
}
|
|
|
|
typedef CUtlMap<int, CBufferStringGrowable<8>, int, CDefLess<int>> CommentsMap_t;
|
|
|
|
int m_nLine;
|
|
int m_nColumn;
|
|
uint m_nFlags;
|
|
CUtlSymbolLarge m_sName;
|
|
CommentsMap_t m_Comments;
|
|
};
|
|
|
|
struct KV3BinaryBlob_t
|
|
{
|
|
size_t m_nSize;
|
|
union
|
|
{
|
|
const byte* m_pubData;
|
|
byte m_ubData[1];
|
|
};
|
|
bool m_bFreeMemory;
|
|
};
|
|
|
|
class CKV3MemberName
|
|
{
|
|
public:
|
|
inline CKV3MemberName(const char* pszString): m_nHashCode(0), m_pszString("")
|
|
{
|
|
if (!pszString || !pszString[0])
|
|
return;
|
|
|
|
CUtlString buf( pszString );
|
|
buf.ToLowerFast();
|
|
|
|
m_nHashCode = MurmurHash2(buf.Get(), strlen(pszString), 0x31415926);
|
|
m_pszString = pszString;
|
|
|
|
#if 0
|
|
if (g_bUpdateStringTokenDatabase)
|
|
{
|
|
RegisterStringToken(m_nHashCode, pszString, 0, true);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
inline CKV3MemberName(): m_nHashCode(0), m_pszString("") {}
|
|
inline CKV3MemberName(unsigned int nHashCode, const char* pszString): m_nHashCode(nHashCode), m_pszString(pszString) {}
|
|
inline CKV3MemberName(const CKV3MemberName& other): m_nHashCode(other.m_nHashCode), m_pszString(other.m_pszString) {}
|
|
inline CKV3MemberName& operator=(const CKV3MemberName& src)
|
|
{
|
|
m_nHashCode = src.m_nHashCode;
|
|
m_pszString = src.m_pszString;
|
|
return *this;
|
|
}
|
|
|
|
inline unsigned int GetHashCode() const { return m_nHashCode; }
|
|
inline const char* GetString() const { return m_pszString; }
|
|
|
|
private:
|
|
unsigned int m_nHashCode;
|
|
const char* m_pszString;
|
|
};
|
|
|
|
class KeyValues3
|
|
{
|
|
public:
|
|
KeyValues3( KV3TypeEx_t type = KV3_TYPEEX_NULL, KV3SubType_t subtype = KV3_SUBTYPE_UNSPECIFIED );
|
|
~KeyValues3();
|
|
|
|
CKeyValues3Context* GetContext() const;
|
|
KV3MetaData_t* GetMetaData( CKeyValues3Context** ppCtx = NULL ) const;
|
|
|
|
KV3Type_t GetType() const { return ( KV3Type_t )( m_TypeEx & 0xF ); }
|
|
KV3TypeEx_t GetTypeEx() const { return ( KV3TypeEx_t )m_TypeEx; }
|
|
KV3SubType_t GetSubType() const { return ( KV3SubType_t )m_SubType; }
|
|
|
|
void SetToNull() { PrepareForType( KV3_TYPEEX_NULL, KV3_SUBTYPE_NULL ); }
|
|
|
|
bool GetBool( bool defaultValue = false ) const { return GetValue<bool>( defaultValue ); }
|
|
char8 GetChar( char8 defaultValue = 0 ) const { return GetValue<char8>( defaultValue ); }
|
|
uchar32 GetUChar32( uchar32 defaultValue = 0 ) const { return GetValue<uint32>( defaultValue ); }
|
|
int8 GetInt8( int8 defaultValue = 0 ) const { return GetValue<int8>( defaultValue ); }
|
|
uint8 GetUInt8( uint8 defaultValue = 0 ) const { return GetValue<uint8>( defaultValue ); }
|
|
int16 GetShort( int16 defaultValue = 0 ) const { return GetValue<int16>( defaultValue ); }
|
|
uint16 GetUShort( uint16 defaultValue = 0 ) const { return GetValue<uint16>( defaultValue ); }
|
|
int32 GetInt( int32 defaultValue = 0 ) const { return GetValue<int32>( defaultValue ); }
|
|
uint32 GetUInt( uint32 defaultValue = 0 ) const { return GetValue<uint32>( defaultValue ); }
|
|
int64 GetInt64( int64 defaultValue = 0 ) const { return GetValue<int64>( defaultValue ); }
|
|
uint64 GetUInt64( uint64 defaultValue = 0 ) const { return GetValue<uint64>( defaultValue ); }
|
|
float32 GetFloat( float32 defaultValue = 0.0f ) const { return GetValue<float32>( defaultValue ); }
|
|
float64 GetDouble( float64 defaultValue = 0.0 ) const { return GetValue<float64>( defaultValue ); }
|
|
|
|
void SetBool( bool value ) { SetValue<bool>( value, KV3_TYPEEX_BOOL, KV3_SUBTYPE_BOOL8 ); }
|
|
void SetChar( char8 value ) { SetValue<char8>( value, KV3_TYPEEX_INT, KV3_SUBTYPE_CHAR8 ); }
|
|
void SetUChar32( uchar32 value ){ SetValue<uint32>( value, KV3_TYPEEX_UINT, KV3_SUBTYPE_UCHAR32 ); }
|
|
void SetInt8( int8 value ) { SetValue<int8>( value, KV3_TYPEEX_INT, KV3_SUBTYPE_INT8 ); }
|
|
void SetUInt8( uint8 value ) { SetValue<uint8>( value, KV3_TYPEEX_UINT, KV3_SUBTYPE_UINT8 ); }
|
|
void SetShort( int16 value ) { SetValue<int16>( value, KV3_TYPEEX_INT, KV3_SUBTYPE_INT16 ); }
|
|
void SetUShort( uint16 value ) { SetValue<uint16>( value, KV3_TYPEEX_UINT, KV3_SUBTYPE_UINT16 ); }
|
|
void SetInt( int32 value ) { SetValue<int32>( value, KV3_TYPEEX_INT, KV3_SUBTYPE_INT32 ); }
|
|
void SetUInt( uint32 value ) { SetValue<uint32>( value, KV3_TYPEEX_UINT, KV3_SUBTYPE_UINT32 ); }
|
|
void SetInt64( int64 value ) { SetValue<int64>( value, KV3_TYPEEX_INT, KV3_SUBTYPE_INT64 ); }
|
|
void SetUInt64( uint64 value ) { SetValue<uint64>( value, KV3_TYPEEX_UINT, KV3_SUBTYPE_UINT64 ); }
|
|
void SetFloat( float32 value ) { SetValue<float32>( value, KV3_TYPEEX_DOUBLE, KV3_SUBTYPE_FLOAT32 ); }
|
|
void SetDouble( float64 value ) { SetValue<float64>( value, KV3_TYPEEX_DOUBLE, KV3_SUBTYPE_FLOAT64 ); }
|
|
|
|
void* GetPointer( void *defaultValue = ( void* )0 ) const { return ( GetSubType() == KV3_SUBTYPE_POINTER ) ? ( void* )m_UInt : defaultValue; }
|
|
void SetPointer( void* ptr ) { SetValue<uint64>( ( uint64 )ptr, KV3_TYPEEX_UINT, KV3_SUBTYPE_POINTER ); }
|
|
|
|
CUtlStringToken GetStringToken( CUtlStringToken defaultValue = CUtlStringToken() ) const { return ( GetSubType() == KV3_SUBTYPE_STRING_TOKEN ) ? CUtlStringToken( ( uint32 )m_UInt ) : defaultValue; }
|
|
void SetStringToken( const CUtlStringToken& token ) { SetValue<uint32>( token.m_nHashCode, KV3_TYPEEX_UINT, KV3_SUBTYPE_STRING_TOKEN ); }
|
|
|
|
CEntityHandle GetEHandle( CEntityHandle defaultValue = CEntityHandle() ) const { return ( GetSubType() == KV3_SUBTYPE_EHANDLE ) ? CEntityHandle( ( uint32 )m_UInt ) : defaultValue; }
|
|
void SetEHandle( const CEntityHandle& ehandle ) { SetValue<uint32>( ehandle.ToInt(), KV3_TYPEEX_UINT, KV3_SUBTYPE_EHANDLE ); }
|
|
|
|
const char* GetString( const char *defaultValue = "" ) const;
|
|
void SetString( const char* pString, KV3SubType_t subtype = KV3_SUBTYPE_STRING );
|
|
void SetStringExternal( const char* pString, KV3SubType_t subtype = KV3_SUBTYPE_STRING );
|
|
|
|
const byte* GetBinaryBlob() const;
|
|
int GetBinaryBlobSize() const;
|
|
void SetToBinaryBlob( const byte* blob, int size );
|
|
void SetToBinaryBlobExternal( const byte* blob, int size, bool free_mem );
|
|
|
|
Color GetColor( Color defaultValue = Color( 0, 0, 0, 255 ) ) const;
|
|
void SetColor( const Color &color );
|
|
|
|
Vector GetVector( Vector defaultValue = Vector( 0.0f, 0.0f, 0.0f ) ) const { return GetVecBasedObj<Vector>( 3, defaultValue ); }
|
|
Vector2D GetVector2D( Vector2D defaultValue = Vector2D( 0.0f, 0.0f ) ) const { return GetVecBasedObj<Vector2D>( 2, defaultValue ); }
|
|
Vector4D GetVector4D( Vector4D defaultValue = Vector4D( 0.0f, 0.0f, 0.0f, 0.0f ) ) const { return GetVecBasedObj<Vector4D>( 4, defaultValue ); }
|
|
Quaternion GetQuaternion( Quaternion defaultValue = Quaternion( 0.0f, 0.0f, 0.0f, 0.0f ) ) const { return GetVecBasedObj<Quaternion>( 4, defaultValue ); }
|
|
QAngle GetQAngle( QAngle defaultValue = QAngle( 0.0f, 0.0f, 0.0f ) ) const { return GetVecBasedObj<QAngle>( 3, defaultValue ); }
|
|
|
|
void SetVector( const Vector &vec ) { SetVecBasedObj<Vector>( vec, 3, KV3_SUBTYPE_VECTOR ); }
|
|
void SetVector2D( const Vector2D &vec2d ) { SetVecBasedObj<Vector2D>( vec2d, 2, KV3_SUBTYPE_VECTOR2D ); }
|
|
void SetVector4D( const Vector4D &vec4d ) { SetVecBasedObj<Vector4D>( vec4d, 4, KV3_SUBTYPE_VECTOR4D ); }
|
|
void SetQuaternion( const Quaternion &quat ) { SetVecBasedObj<Quaternion>( quat, 4, KV3_SUBTYPE_QUATERNION ); }
|
|
void SetQAngle( const QAngle &ang ) { SetVecBasedObj<QAngle>( ang, 3, KV3_SUBTYPE_QANGLE ); }
|
|
|
|
int GetArrayElementCount() const;
|
|
KeyValues3** GetArrayBase();
|
|
KeyValues3* GetArrayElement( int elem );
|
|
KeyValues3* InsertArrayElementBefore( int elem );
|
|
KeyValues3* InsertArrayElementAfter( int elem ) { return InsertArrayElementBefore( elem + 1 ); }
|
|
KeyValues3* AddArrayElementToTail();
|
|
void SetArrayElementCount( int count, KV3TypeEx_t type = KV3_TYPEEX_NULL, KV3SubType_t subtype = KV3_SUBTYPE_UNSPECIFIED );
|
|
void SetToEmptyArray() { SetArrayElementCount( 0 ); }
|
|
void RemoveArrayElements( int elem, int num );
|
|
void RemoveArrayElement( int elem ) { RemoveArrayElements( elem, 1 ); }
|
|
|
|
int GetMemberCount() const;
|
|
KeyValues3* GetMember( KV3MemberId_t id ) const;
|
|
const char* GetMemberName( KV3MemberId_t id ) const;
|
|
CKV3MemberName GetMemberNameEx( KV3MemberId_t id ) const;
|
|
unsigned int GetMemberHash( KV3MemberId_t id ) const;
|
|
KeyValues3* FindMember( const CKV3MemberName &name, KeyValues3* defaultValue = NULL ) const;
|
|
KeyValues3* FindOrCreateMember( const CKV3MemberName &name, bool *pCreated = NULL );
|
|
void SetToEmptyTable();
|
|
bool RemoveMember( KV3MemberId_t id );
|
|
bool RemoveMember( const KeyValues3* kv );
|
|
bool RemoveMember( const CKV3MemberName &name );
|
|
|
|
KeyValues3& operator=( const KeyValues3& src );
|
|
|
|
private:
|
|
KeyValues3( int cluster_elem, KV3TypeEx_t type, KV3SubType_t subtype );
|
|
KeyValues3( const KeyValues3& other );
|
|
|
|
void Alloc();
|
|
void Free( bool bClearingContext = false );
|
|
void ResolveUnspecified();
|
|
void PrepareForType( KV3TypeEx_t type, KV3SubType_t subtype );
|
|
void OnClearContext();
|
|
void CopyFrom( const KeyValues3* pSrc );
|
|
|
|
int GetClusterElement() const { return m_nClusterElement; }
|
|
CKeyValues3Cluster* GetCluster() const;
|
|
|
|
template < typename T > T FromString( T defaultValue ) const;
|
|
template < typename T > void SetDirect( T value );
|
|
|
|
template < typename T > T GetValue( T defaultValue ) const;
|
|
template < typename T > void SetValue( T value, KV3TypeEx_t type, KV3SubType_t subtype );
|
|
|
|
template < typename T > T GetVecBasedObj( int size, T defaultValue ) const;
|
|
template < typename T > void SetVecBasedObj( const T &obj, int size, KV3SubType_t subtype );
|
|
|
|
template< typename T >
|
|
void NormalizeArray( KV3TypeEx_t type, KV3SubType_t subtype, int size, const T* data, bool bFree );
|
|
void NormalizeArray();
|
|
|
|
template < typename T >
|
|
void AllocArray( int size, const T* data, KV3ArrayAllocType_t alloc_type, KV3TypeEx_t type_short, KV3TypeEx_t type_ptr, KV3SubType_t subtype, KV3TypeEx_t type_elem, KV3SubType_t subtype_elem );
|
|
|
|
bool ReadArrayInt32( int size, int32* data ) const;
|
|
bool ReadArrayFloat32( int size, float32* data ) const;
|
|
|
|
private:
|
|
uint64 m_bExternalStorage : 1;
|
|
uint64 m_bFreeArrayMemory : 1;
|
|
uint64 m_TypeEx : 8;
|
|
uint64 m_SubType : 8;
|
|
uint64 m_nFlags : 8;
|
|
uint64 m_nClusterElement : 6;
|
|
uint64 m_nNumArrayElements : 5;
|
|
uint64 m_nReserved : 27;
|
|
|
|
union
|
|
{
|
|
bool m_Bool;
|
|
int64 m_Int;
|
|
uint64 m_UInt;
|
|
float64 m_Double;
|
|
|
|
const char* m_pString;
|
|
char m_szStringShort[8];
|
|
|
|
KV3BinaryBlob_t* m_pBinaryBlob;
|
|
|
|
CKeyValues3Array* m_pArray;
|
|
float32* m_f32Array;
|
|
float64* m_f64Array;
|
|
int16* m_i16Array;
|
|
int32* m_i32Array;
|
|
uint8 m_u8ArrayShort[8];
|
|
int16 m_i16ArrayShort[4];
|
|
|
|
CKeyValues3Table* m_pTable;
|
|
|
|
uint64 m_Value;
|
|
void* m_pData;
|
|
char m_Data[1];
|
|
};
|
|
|
|
friend class CKeyValues3Cluster;
|
|
friend class CKeyValues3Context;
|
|
};
|
|
COMPILE_TIME_ASSERT(sizeof(KeyValues3) == 16);
|
|
|
|
class CKeyValues3Array
|
|
{
|
|
public:
|
|
CKeyValues3Array( int cluster_elem = -1 ) : m_nClusterElement( cluster_elem ) {}
|
|
~CKeyValues3Array() {}
|
|
|
|
int GetClusterElement() const { return m_nClusterElement; }
|
|
CKeyValues3ArrayCluster* GetCluster() const;
|
|
CKeyValues3Context* GetContext() const;
|
|
|
|
KeyValues3** Base() { return m_Elements.Base(); }
|
|
KeyValues3* const * Base() const { return m_Elements.Base(); }
|
|
|
|
KeyValues3* Element( int i ) { return m_Elements[ i ]; }
|
|
const KeyValues3* Element( int i ) const { return m_Elements[ i ]; }
|
|
|
|
int Count() const { return m_Elements.Count(); }
|
|
void SetCount( int count, KV3TypeEx_t type = KV3_TYPEEX_NULL, KV3SubType_t subtype = KV3_SUBTYPE_UNSPECIFIED );
|
|
KeyValues3** InsertBeforeGetPtr( int elem, int num );
|
|
void CopyFrom( const CKeyValues3Array* pSrc );
|
|
void RemoveMultiple( int elem, int num );
|
|
void Purge( bool bClearingContext );
|
|
|
|
private:
|
|
typedef CUtlLeanVectorFixedGrowable<KeyValues3*, 4, int> ElementsVec_t;
|
|
|
|
int m_nClusterElement;
|
|
ElementsVec_t m_Elements;
|
|
};
|
|
|
|
class CKeyValues3Table
|
|
{
|
|
public:
|
|
CKeyValues3Table( int cluster_elem = -1 ) :
|
|
m_nClusterElement( cluster_elem ),
|
|
m_pFastSearch( NULL ),
|
|
m_bHasBadNames( false ) {}
|
|
|
|
~CKeyValues3Table() {}
|
|
|
|
int GetClusterElement() const { return m_nClusterElement; }
|
|
CKeyValues3TableCluster* GetCluster() const;
|
|
CKeyValues3Context* GetContext() const;
|
|
|
|
int GetMemberCount() const { return m_Hashes.Count(); }
|
|
KeyValues3* GetMember( KV3MemberId_t id ) const { return m_Members[ id ]; }
|
|
const char* GetMemberName( KV3MemberId_t id ) const { return m_Names[ id ]; }
|
|
unsigned int GetMemberHash( KV3MemberId_t id ) const { return m_Hashes[ id ]; }
|
|
void EnableFastSearch();
|
|
KV3MemberId_t FindMember( const KeyValues3* kv ) const;
|
|
KV3MemberId_t FindMember( const CKV3MemberName &name );
|
|
KV3MemberId_t CreateMember( const CKV3MemberName &name );
|
|
void CopyFrom( const CKeyValues3Table* pSrc );
|
|
void RemoveMember( KV3MemberId_t id );
|
|
void RemoveAll( int nAllocSize = 0 );
|
|
void Purge( bool bClearingContext );
|
|
|
|
private:
|
|
typedef CUtlLeanVectorFixedGrowable<unsigned int, 8, int> HashesVec_t;
|
|
typedef CUtlLeanVectorFixedGrowable<KeyValues3*, 8, int> MembersVec_t;
|
|
typedef CUtlLeanVectorFixedGrowable<const char*, 8, int> NamesVec_t;
|
|
typedef CUtlLeanVectorFixedGrowable<bool, 8, int> IsExternalNameVec_t;
|
|
|
|
int m_nClusterElement;
|
|
|
|
struct kv3tablefastsearch_t {
|
|
kv3tablefastsearch_t() : m_ignore( false ), m_ignores_counter( 0 ) {}
|
|
~kv3tablefastsearch_t() {}
|
|
|
|
void Clear()
|
|
{
|
|
m_ignore = false;
|
|
m_ignores_counter = 0;
|
|
m_member_ids.RemoveAll();
|
|
}
|
|
|
|
struct EmptyHashFunctor { unsigned int operator()( uint32 n ) const { return n; } };
|
|
typedef CUtlHashtable<unsigned int, KV3MemberId_t, EmptyHashFunctor> Hashtable_t;
|
|
|
|
bool m_ignore;
|
|
int8 m_ignores_counter;
|
|
Hashtable_t m_member_ids;
|
|
} *m_pFastSearch;
|
|
|
|
HashesVec_t m_Hashes;
|
|
MembersVec_t m_Members;
|
|
NamesVec_t m_Names;
|
|
IsExternalNameVec_t m_IsExternalName; // didn't find this used when deleting a table
|
|
bool m_bHasBadNames;
|
|
};
|
|
|
|
class CKeyValues3Cluster
|
|
{
|
|
public:
|
|
CKeyValues3Cluster( CKeyValues3Context* context ) :
|
|
m_pContext( context ),
|
|
m_nAllocatedElements( 0 ),
|
|
m_pMetaData( NULL ),
|
|
m_pNextFree( NULL )
|
|
{
|
|
memset( &m_KeyValues, 0, sizeof( m_KeyValues ) );
|
|
}
|
|
|
|
~CKeyValues3Cluster()
|
|
{
|
|
FreeMetaData();
|
|
}
|
|
|
|
KeyValues3* Alloc( KV3TypeEx_t type = KV3_TYPEEX_NULL, KV3SubType_t subtype = KV3_SUBTYPE_UNSPECIFIED );
|
|
void Free( int element );
|
|
void Clear();
|
|
void PurgeElements();
|
|
void Purge();
|
|
|
|
void EnableMetaData( bool bEnable );
|
|
void FreeMetaData();
|
|
KV3MetaData_t* GetMetaData( int element ) const;
|
|
|
|
CKeyValues3Context* GetContext() const { return m_pContext; }
|
|
int NumAllocated() const;
|
|
bool IsFree() const { return (m_nAllocatedElements != 0x7fffffffffffffffull); }
|
|
CKeyValues3Cluster* GetNextFree() const { return m_pNextFree; }
|
|
void SetNextFree( CKeyValues3Cluster* free ) { m_pNextFree = free; }
|
|
|
|
KeyValues3* Head() { return &m_KeyValues[ 0 ]; }
|
|
const KeyValues3* Head() const { return &m_KeyValues[ 0 ]; }
|
|
|
|
private:
|
|
CKeyValues3Context* m_pContext;
|
|
uint64 m_nAllocatedElements;
|
|
KeyValues3 m_KeyValues[KV3_CLUSTER_MAX_ELEMENTS];
|
|
|
|
struct kv3metadata_t {
|
|
KV3MetaData_t m_elements[KV3_CLUSTER_MAX_ELEMENTS];
|
|
} *m_pMetaData;
|
|
|
|
CKeyValues3Cluster* m_pNextFree;
|
|
|
|
friend CKeyValues3Cluster* KeyValues3::GetCluster() const;
|
|
};
|
|
|
|
class CKeyValues3ArrayCluster
|
|
{
|
|
public:
|
|
CKeyValues3ArrayCluster( CKeyValues3Context* context ) :
|
|
m_pContext( context ),
|
|
m_nAllocatedElements( 0 ),
|
|
m_pNextFree( NULL )
|
|
{
|
|
memset( &m_Arrays, 0, sizeof( m_Arrays ) );
|
|
}
|
|
|
|
~CKeyValues3ArrayCluster() {}
|
|
|
|
CKeyValues3Array* Alloc();
|
|
void Free( int element );
|
|
void Clear() { Purge(); };
|
|
void Purge();
|
|
|
|
CKeyValues3Context* GetContext() const { return m_pContext; }
|
|
int NumAllocated() const;
|
|
bool IsFree() const { return (m_nAllocatedElements != 0x7fffffffffffffffull); }
|
|
CKeyValues3ArrayCluster* GetNextFree() const { return m_pNextFree; }
|
|
void SetNextFree( CKeyValues3ArrayCluster* free ) { m_pNextFree = free; }
|
|
|
|
private:
|
|
CKeyValues3Context* m_pContext;
|
|
uint64 m_nAllocatedElements;
|
|
CKeyValues3Array m_Arrays[KV3_CLUSTER_MAX_ELEMENTS];
|
|
CKeyValues3ArrayCluster* m_pNextFree;
|
|
|
|
friend CKeyValues3ArrayCluster* CKeyValues3Array::GetCluster() const;
|
|
};
|
|
|
|
class CKeyValues3TableCluster
|
|
{
|
|
public:
|
|
CKeyValues3TableCluster( CKeyValues3Context* context ) :
|
|
m_pContext( context ),
|
|
m_nAllocatedElements( 0 ),
|
|
m_pNextFree( NULL )
|
|
{
|
|
memset( &m_Tables, 0, sizeof( m_Tables ) );
|
|
}
|
|
|
|
~CKeyValues3TableCluster() {}
|
|
|
|
CKeyValues3Table* Alloc();
|
|
void Free( int element );
|
|
void Clear() { Purge(); };
|
|
void Purge();
|
|
|
|
CKeyValues3Context* GetContext() const { return m_pContext; }
|
|
int NumAllocated() const;
|
|
bool IsFree() const { return (m_nAllocatedElements != 0x7fffffffffffffffull); }
|
|
CKeyValues3TableCluster* GetNextFree() const { return m_pNextFree; }
|
|
void SetNextFree( CKeyValues3TableCluster* free ) { m_pNextFree = free; }
|
|
|
|
private:
|
|
CKeyValues3Context* m_pContext;
|
|
uint64 m_nAllocatedElements;
|
|
CKeyValues3Table m_Tables[KV3_CLUSTER_MAX_ELEMENTS];
|
|
CKeyValues3TableCluster* m_pNextFree;
|
|
|
|
friend CKeyValues3TableCluster* CKeyValues3Table::GetCluster() const;
|
|
};
|
|
|
|
class CKeyValues3ContextBase
|
|
{
|
|
public:
|
|
CKeyValues3ContextBase( CKeyValues3Context* context );
|
|
~CKeyValues3ContextBase();
|
|
|
|
void Clear();
|
|
void Purge();
|
|
|
|
protected:
|
|
typedef CUtlLeanVectorFixedGrowable<CKeyValues3Cluster*, 8, int> KV3ClustersVec_t;
|
|
typedef CUtlLeanVectorFixedGrowable<CKeyValues3ArrayCluster*, 4, int> ArrayClustersVec_t;
|
|
typedef CUtlLeanVectorFixedGrowable<CKeyValues3TableCluster*, 4, int> TableClustersVec_t;
|
|
|
|
CKeyValues3Context* m_pContext;
|
|
CUtlBuffer m_BinaryData;
|
|
|
|
CKeyValues3Cluster m_KV3BaseCluster;
|
|
KV3ClustersVec_t m_KV3Clusters;
|
|
CKeyValues3Cluster* m_pKV3FreeCluster;
|
|
|
|
ArrayClustersVec_t m_ArrayClusters;
|
|
CKeyValues3ArrayCluster* m_pArrayFreeCluster;
|
|
|
|
TableClustersVec_t m_TableClusters;
|
|
CKeyValues3TableCluster* m_pTableFreeCluster;
|
|
|
|
CUtlSymbolTableLarge m_Symbols;
|
|
|
|
bool m_bMetaDataEnabled : 1;
|
|
bool m_bFormatConverted : 1;
|
|
bool m_bRootAvailabe : 1;
|
|
|
|
IParsingErrorListener* m_pParsingErrorListener;
|
|
};
|
|
|
|
class CKeyValues3Context : public CKeyValues3ContextBase
|
|
{
|
|
typedef CKeyValues3ContextBase BaseClass;
|
|
|
|
public:
|
|
CKeyValues3Context( bool bNoRoot = false );
|
|
~CKeyValues3Context();
|
|
|
|
KeyValues3* AllocKV( KV3TypeEx_t type = KV3_TYPEEX_NULL, KV3SubType_t subtype = KV3_SUBTYPE_UNSPECIFIED );
|
|
// WARNING: kv must belong to this context!!!
|
|
void FreeKV( KeyValues3* kv );
|
|
|
|
// gets the pre-allocated kv if we indicated its existence when creating the context
|
|
KeyValues3* Root();
|
|
|
|
bool IsMetaDataEnabled() const { return m_bMetaDataEnabled; };
|
|
// returns true if the desired format was converted to another after loading via LoadKV3*
|
|
bool IsFormatConverted() const { return m_bFormatConverted; };
|
|
bool IsRootAvailabe() const { return m_bRootAvailabe; };
|
|
|
|
// filled in after loading via LoadKV3* in binary encoding
|
|
const CUtlBuffer& GetBinaryData() const { return m_BinaryData; }
|
|
|
|
IParsingErrorListener* GetParsingErrorListener() const { return m_pParsingErrorListener; };
|
|
void SetParsingErrorListener( IParsingErrorListener* listener ) { m_pParsingErrorListener = listener; }
|
|
|
|
const char* AllocString( const char* pString );
|
|
|
|
void EnableMetaData( bool bEnable );
|
|
void CopyMetaData( KV3MetaData_t* pDest, const KV3MetaData_t* pSrc );
|
|
|
|
void Clear();
|
|
void Purge();
|
|
|
|
private:
|
|
template< class ELEMENT_TYPE, class CLUSTER_TYPE, class VECTOR_TYPE >
|
|
ELEMENT_TYPE* Alloc( CLUSTER_TYPE *&head, VECTOR_TYPE &vec );
|
|
|
|
template< class ELEMENT_TYPE, class CLUSTER_TYPE, class VECTOR_TYPE >
|
|
void Free( ELEMENT_TYPE *element, CLUSTER_TYPE *base, CLUSTER_TYPE *&head, VECTOR_TYPE &vec );
|
|
|
|
CKeyValues3Array* AllocArray() { return Alloc<CKeyValues3Array, CKeyValues3ArrayCluster, ArrayClustersVec_t>( m_pArrayFreeCluster, m_ArrayClusters ); }
|
|
CKeyValues3Table* AllocTable() { return Alloc<CKeyValues3Table, CKeyValues3TableCluster, TableClustersVec_t>( m_pTableFreeCluster, m_TableClusters ); }
|
|
|
|
void FreeArray( CKeyValues3Array* arr ) { Free<CKeyValues3Array, CKeyValues3ArrayCluster, ArrayClustersVec_t>( arr, NULL, m_pArrayFreeCluster, m_ArrayClusters ); }
|
|
void FreeTable( CKeyValues3Table* table ) { Free<CKeyValues3Table, CKeyValues3TableCluster, TableClustersVec_t>( table, NULL, m_pTableFreeCluster, m_TableClusters ); }
|
|
|
|
private:
|
|
uint8 pad[ KV3_CONTEXT_SIZE - ( sizeof( BaseClass ) % KV3_CONTEXT_SIZE ) ];
|
|
|
|
friend class KeyValues3;
|
|
};
|
|
COMPILE_TIME_ASSERT(sizeof(CKeyValues3Context) == KV3_CONTEXT_SIZE);
|
|
|
|
template < typename T > inline T KeyValues3::FromString( T defaultValue ) const { Assert( 0 ); return defaultValue; }
|
|
template <> inline bool KeyValues3::FromString( bool defaultValue ) const { return V_StringToBool( GetString(), defaultValue ); }
|
|
template <> inline char8 KeyValues3::FromString( char8 defaultValue ) const { return V_StringToInt8( GetString(), defaultValue ); }
|
|
template <> inline int8 KeyValues3::FromString( int8 defaultValue ) const { return V_StringToInt8( GetString(), defaultValue ); }
|
|
template <> inline uint8 KeyValues3::FromString( uint8 defaultValue ) const { return V_StringToUint8( GetString(), defaultValue ); }
|
|
template <> inline int16 KeyValues3::FromString( int16 defaultValue ) const { return V_StringToInt16( GetString(), defaultValue ); }
|
|
template <> inline uint16 KeyValues3::FromString( uint16 defaultValue ) const { return V_StringToUint16( GetString(), defaultValue ); }
|
|
template <> inline int32 KeyValues3::FromString( int32 defaultValue ) const { return V_StringToInt32( GetString(), defaultValue ); }
|
|
template <> inline uint32 KeyValues3::FromString( uint32 defaultValue ) const { return V_StringToUint32( GetString(), defaultValue ); }
|
|
template <> inline int64 KeyValues3::FromString( int64 defaultValue ) const { return V_StringToInt64( GetString(), defaultValue ); }
|
|
template <> inline uint64 KeyValues3::FromString( uint64 defaultValue ) const { return V_StringToUint64( GetString(), defaultValue ); }
|
|
template <> inline float32 KeyValues3::FromString( float32 defaultValue ) const { return V_StringToFloat32( GetString(), defaultValue ); }
|
|
template <> inline float64 KeyValues3::FromString( float64 defaultValue ) const { return V_StringToFloat64( GetString(), defaultValue ); }
|
|
|
|
template < typename T > inline void KeyValues3::SetDirect( T value ) { Assert( 0 ); }
|
|
template <> inline void KeyValues3::SetDirect( bool value ) { m_Bool = value; }
|
|
template <> inline void KeyValues3::SetDirect( char8 value ) { m_Int = ( int64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( int8 value ) { m_Int = ( int64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( uint8 value ) { m_UInt = ( uint64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( int16 value ) { m_Int = ( int64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( uint16 value ) { m_UInt = ( uint64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( int32 value ) { m_Int = ( int64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( uint32 value ) { m_UInt = ( uint64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( int64 value ) { m_Int = value; }
|
|
template <> inline void KeyValues3::SetDirect( uint64 value ) { m_UInt = value; }
|
|
template <> inline void KeyValues3::SetDirect( float32 value ) { m_Double = ( float64 )value; }
|
|
template <> inline void KeyValues3::SetDirect( float64 value ) { m_Double = value; }
|
|
|
|
template < typename T >
|
|
T KeyValues3::GetVecBasedObj( int size, T defaultValue ) const
|
|
{
|
|
T obj;
|
|
if ( !ReadArrayFloat32( size, obj.Base() ) )
|
|
obj = defaultValue;
|
|
return obj;
|
|
}
|
|
|
|
template < typename T >
|
|
void KeyValues3::SetVecBasedObj( const T &obj, int size, KV3SubType_t subtype )
|
|
{
|
|
AllocArray<float32>( size, obj.Base(), KV3_ARRAY_ALLOC_NORMAL, KV3_TYPEEX_INVALID, KV3_TYPEEX_ARRAY_FLOAT32, subtype, KV3_TYPEEX_DOUBLE, KV3_SUBTYPE_FLOAT32 );
|
|
}
|
|
|
|
template < typename T >
|
|
T KeyValues3::GetValue( T defaultValue ) const
|
|
{
|
|
switch ( GetType() )
|
|
{
|
|
case KV3_TYPE_BOOL:
|
|
return ( T )m_Bool;
|
|
case KV3_TYPE_INT:
|
|
return ( T )m_Int;
|
|
case KV3_TYPE_UINT:
|
|
return ( GetSubType() != KV3_SUBTYPE_POINTER ) ? ( T )m_UInt : defaultValue;
|
|
case KV3_TYPE_DOUBLE:
|
|
return ( T )m_Double;
|
|
case KV3_TYPE_STRING:
|
|
return FromString<T>( defaultValue );
|
|
default:
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
template < typename T >
|
|
void KeyValues3::SetValue( T value, KV3TypeEx_t type, KV3SubType_t subtype )
|
|
{
|
|
PrepareForType( type, subtype );
|
|
SetDirect<T>( value );
|
|
}
|
|
|
|
template< typename T >
|
|
void KeyValues3::NormalizeArray( KV3TypeEx_t type, KV3SubType_t subtype, int size, const T* data, bool bFree )
|
|
{
|
|
m_TypeEx = KV3_TYPEEX_ARRAY;
|
|
m_Value = 0;
|
|
Alloc();
|
|
|
|
m_pArray->SetCount( size, type, subtype );
|
|
|
|
KeyValues3** arr = m_pArray->Base();
|
|
for ( int i = 0; i < m_pArray->Count(); ++i )
|
|
arr[ i ]->SetDirect( data[ i ] );
|
|
|
|
if ( bFree )
|
|
free( (void*)data );
|
|
}
|
|
|
|
template < typename T >
|
|
void KeyValues3::AllocArray( int size, const T* data, KV3ArrayAllocType_t alloc_type, KV3TypeEx_t type_short, KV3TypeEx_t type_ptr, KV3SubType_t subtype, KV3TypeEx_t type_elem, KV3SubType_t subtype_elem )
|
|
{
|
|
int nMaxSizeShort = sizeof( uint64 ) / sizeof( T );
|
|
|
|
if ( type_short != KV3_TYPEEX_INVALID && size <= nMaxSizeShort )
|
|
{
|
|
if ( alloc_type == KV3_ARRAY_ALLOC_EXTERN && type_ptr != KV3_TYPEEX_INVALID )
|
|
{
|
|
PrepareForType( type_ptr, subtype );
|
|
|
|
m_bFreeArrayMemory = false;
|
|
m_nNumArrayElements = size;
|
|
m_pData = (void*)data;
|
|
}
|
|
else
|
|
{
|
|
PrepareForType( type_short, subtype );
|
|
|
|
m_bFreeArrayMemory = false;
|
|
m_nNumArrayElements = size;
|
|
m_Value = 0;
|
|
memcpy( m_Data, data, size * sizeof( T ) );
|
|
|
|
if ( alloc_type == KV3_ARRAY_ALLOC_EXTERN_FREE )
|
|
free( (void*)data );
|
|
}
|
|
}
|
|
else if ( type_ptr != KV3_TYPEEX_INVALID && size <= 31 )
|
|
{
|
|
PrepareForType( type_ptr, subtype );
|
|
|
|
m_nNumArrayElements = size;
|
|
|
|
if ( alloc_type == KV3_ARRAY_ALLOC_EXTERN )
|
|
{
|
|
m_pData = (void*)data;
|
|
m_bFreeArrayMemory = false;
|
|
}
|
|
else if ( alloc_type == KV3_ARRAY_ALLOC_EXTERN_FREE )
|
|
{
|
|
m_pData = (void*)data;
|
|
m_bFreeArrayMemory = true;
|
|
}
|
|
else
|
|
{
|
|
m_pData = malloc( size * sizeof( T ) );
|
|
memcpy( m_pData, data, size * sizeof( T ) );
|
|
m_bFreeArrayMemory = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrepareForType( KV3_TYPEEX_ARRAY, subtype );
|
|
|
|
m_pArray->SetCount( size, type_elem, subtype_elem );
|
|
|
|
KeyValues3** arr = m_pArray->Base();
|
|
for ( int i = 0; i < m_pArray->Count(); ++i )
|
|
arr[ i ]->SetValue<T>( data[ i ], type_elem, subtype_elem );
|
|
|
|
if ( alloc_type == KV3_ARRAY_ALLOC_EXTERN_FREE )
|
|
free( (void*)data );
|
|
}
|
|
}
|
|
|
|
template< class ELEMENT_TYPE, class CLUSTER_TYPE, class VECTOR_TYPE >
|
|
ELEMENT_TYPE* CKeyValues3Context::Alloc( CLUSTER_TYPE *&head, VECTOR_TYPE &vec )
|
|
{
|
|
ELEMENT_TYPE* element;
|
|
|
|
if ( head )
|
|
{
|
|
element = head->Alloc();
|
|
|
|
if ( !head->IsFree() )
|
|
{
|
|
CLUSTER_TYPE* cluster = head->GetNextFree();
|
|
head->SetNextFree( NULL );
|
|
head = cluster;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CLUSTER_TYPE* cluster = new CLUSTER_TYPE( m_pContext );
|
|
*vec.AddToTailGetPtr() = cluster;
|
|
head = cluster;
|
|
element = cluster->Alloc();
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
template< class ELEMENT_TYPE, class CLUSTER_TYPE, class VECTOR_TYPE >
|
|
void CKeyValues3Context::Free( ELEMENT_TYPE *element, CLUSTER_TYPE *base, CLUSTER_TYPE *&head, VECTOR_TYPE &vec )
|
|
{
|
|
CLUSTER_TYPE* cluster = element->GetCluster();
|
|
|
|
cluster->Free( element->GetClusterElement() );
|
|
|
|
int num_allocated = cluster->NumAllocated();
|
|
|
|
if ( !num_allocated )
|
|
{
|
|
if ( cluster == base )
|
|
return;
|
|
|
|
vec.FindAndFastRemove( cluster );
|
|
|
|
if ( head != cluster )
|
|
{
|
|
CLUSTER_TYPE* cur = head;
|
|
|
|
while ( cur )
|
|
{
|
|
CLUSTER_TYPE* next = cur->GetNextFree();
|
|
if ( next == cluster )
|
|
break;
|
|
cur = next;
|
|
}
|
|
|
|
if ( cur )
|
|
cur->SetNextFree( cluster->GetNextFree() );
|
|
}
|
|
else
|
|
{
|
|
head = cluster->GetNextFree();
|
|
}
|
|
|
|
delete cluster;
|
|
}
|
|
else if ( num_allocated == ( KV3_CLUSTER_MAX_ELEMENTS - 1 ) )
|
|
{
|
|
cluster->SetNextFree( head );
|
|
head = cluster;
|
|
}
|
|
}
|
|
|
|
#include "tier0/memdbgoff.h"
|
|
|
|
#endif // KEYVALUES3_H
|