2021-12-25 22:36:38 +01:00
|
|
|
#pragma once
|
2022-05-28 16:31:38 +02:00
|
|
|
#include "mathlib/color.h"
|
2022-11-22 09:04:28 +01:00
|
|
|
#include "tier1/utlbuffer.h"
|
2024-04-05 17:42:05 +02:00
|
|
|
#include "tier1/exprevaluator.h"
|
2022-11-22 09:04:28 +01:00
|
|
|
#include "public/ifilesystem.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
|
2024-04-05 17:42:05 +02:00
|
|
|
#define KEYVALUES_TOKEN_SIZE (1024 * 32)
|
2022-05-28 16:31:38 +02:00
|
|
|
|
2024-04-05 17:42:05 +02:00
|
|
|
// single byte identifies a xbox kv file in binary format
|
|
|
|
// strings are pooled from a searchpath/zip mounted symbol table
|
|
|
|
#define KV_BINARY_POOLED_FORMAT 0xAA
|
2022-08-29 11:55:58 +02:00
|
|
|
|
2022-04-09 06:05:47 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Forward declarations
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
class KeyValues;
|
2022-08-13 11:24:55 +02:00
|
|
|
class CFileSystem_Stdio;
|
2022-11-22 09:04:28 +01:00
|
|
|
class IBaseFileSystem;
|
2024-04-05 17:42:05 +02:00
|
|
|
class CKeyValuesTokenReader;
|
2022-11-23 10:34:11 +01:00
|
|
|
|
2022-05-28 16:31:38 +02:00
|
|
|
enum KeyValuesTypes_t : char
|
2022-04-09 06:05:47 +02:00
|
|
|
{
|
|
|
|
TYPE_NONE = 0x0,
|
|
|
|
TYPE_STRING = 0x1,
|
|
|
|
TYPE_INT = 0x2,
|
|
|
|
TYPE_FLOAT = 0x3,
|
|
|
|
TYPE_PTR = 0x4,
|
|
|
|
TYPE_WSTRING = 0x5,
|
|
|
|
TYPE_COLOR = 0x6,
|
|
|
|
TYPE_UINT64 = 0x7,
|
|
|
|
TYPE_COMPILED_INT_BYTE = 0x8,
|
|
|
|
TYPE_COMPILED_INT_0 = 0x9,
|
|
|
|
TYPE_COMPILED_INT_1 = 0xA,
|
|
|
|
TYPE_NUMTYPES = 0xB,
|
|
|
|
};
|
2022-05-28 16:31:38 +02:00
|
|
|
enum MergeKeyValuesOp_t
|
|
|
|
{
|
|
|
|
MERGE_KV_ALL,
|
|
|
|
MERGE_KV_UPDATE, // update values are copied into storage, adding new keys to storage or updating existing ones
|
|
|
|
MERGE_KV_DELETE, // update values specify keys that get deleted from storage
|
|
|
|
MERGE_KV_BORROW, // update values only update existing keys in storage, keys in update that do not exist in storage are discarded
|
|
|
|
};
|
2022-04-09 06:05:47 +02:00
|
|
|
|
2024-04-05 17:42:05 +02:00
|
|
|
#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
|
|
|
|
for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
|
|
|
|
|
|
|
|
#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
|
|
|
|
for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
|
|
|
|
|
|
|
|
#define FOR_EACH_VALUE( kvRoot, kvValue ) \
|
|
|
|
for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
|
2022-05-28 16:31:38 +02:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: Simple recursive data access class
|
|
|
|
// Used in vgui for message parameters and resource files
|
|
|
|
// Destructor deletes all child KeyValues nodes
|
|
|
|
// Data is stored in key (string names) - (string/int/float)value pairs called nodes.
|
|
|
|
//
|
|
|
|
// About KeyValues Text File Format:
|
|
|
|
|
|
|
|
// It has 3 control characters '{', '}' and '"'. Names and values may be quoted or
|
|
|
|
// not. The quote '"' character must not be used within name or values, only for
|
|
|
|
// quoting whole tokens. You may use escape sequences wile parsing and add within a
|
|
|
|
// quoted token a \" to add quotes within your name or token. When using Escape
|
|
|
|
// Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ),
|
|
|
|
// which it's off by default. Non-quoted tokens ends with a whitespace, '{', '}' and '"'.
|
|
|
|
// So you may use '{' and '}' within quoted tokens, but not for non-quoted tokens.
|
|
|
|
// An open bracket '{' after a key name indicates a list of subkeys which is finished
|
|
|
|
// with a closing bracket '}'. Subkeys use the same definitions recursively.
|
|
|
|
// Whitespaces are space, return, newline and tabulator. Allowed Escape sequences
|
|
|
|
// are \n, \t, \\, \n and \". The number character '#' is used for macro purposes
|
|
|
|
// (eg #include), don't use it as first character in key names.
|
|
|
|
//-----------------------------------------------------------------------------
|
2021-12-25 22:36:38 +01:00
|
|
|
class KeyValues
|
|
|
|
{
|
|
|
|
public:
|
2022-05-28 16:31:38 +02:00
|
|
|
// Constructors/destructors
|
|
|
|
KeyValues(const char* pszSetName);
|
|
|
|
KeyValues(const char* pszSetName, const char* pszFirstKey, const char* pszFirstValue);
|
|
|
|
KeyValues(const char* pszSetName, const char* pszFirstKey, const wchar_t* pwszFirstValue);
|
|
|
|
KeyValues(const char* pszSetName, const char* pszFirstKey, int iFirstValue);
|
|
|
|
KeyValues(const char* pszSetName, const char* pszFirstKey, const char* pszFirstValue, const char* pszSecondKey, const char* pszSecondValue);
|
|
|
|
KeyValues(const char* pszSetName, const char* pszFirstKey, int iFirstValue, const char* pszSecondKey, int iSecondValue);
|
|
|
|
~KeyValues(void);
|
|
|
|
|
|
|
|
void Init(void);
|
|
|
|
void Clear(void);
|
|
|
|
void DeleteThis(void);
|
|
|
|
void RemoveEverything();
|
|
|
|
|
2024-04-05 17:42:05 +02:00
|
|
|
KeyValues* FindKey(int keySymbol) const;
|
2022-05-28 16:31:38 +02:00
|
|
|
KeyValues* FindKey(const char* pKeyName, bool bCreate = false);
|
|
|
|
KeyValues* FindLastSubKey(void) const;
|
|
|
|
|
|
|
|
void AddSubKey(KeyValues* pSubkey);
|
|
|
|
void RemoveSubKey(KeyValues* pSubKey);
|
|
|
|
void InsertSubKey(int nIndex, KeyValues* pSubKey);
|
|
|
|
bool ContainsSubKey(KeyValues* pSubKey);
|
|
|
|
void SwapSubKey(KeyValues* pExistingSubkey, KeyValues* pNewSubKey);
|
|
|
|
void ElideSubKey(KeyValues* pSubKey);
|
|
|
|
|
|
|
|
// Data access
|
|
|
|
bool IsEmpty(const char* pszKeyName);
|
|
|
|
KeyValues* GetFirstTrueSubKey(void) const;
|
|
|
|
KeyValues* GetNextTrueSubKey(void) const;
|
|
|
|
KeyValues* GetFirstValue(void) const;
|
|
|
|
KeyValues* GetNextValue(void) const;
|
|
|
|
KeyValues* GetFirstSubKey() const;
|
|
|
|
KeyValues* GetNextKey() const;
|
2022-04-09 16:16:40 +02:00
|
|
|
const char* GetName(void) const;
|
2024-04-05 17:42:05 +02:00
|
|
|
int GetNameSymbol() const;
|
|
|
|
int GetNameSymbolCaseSensitive() const;
|
2022-05-28 16:31:38 +02:00
|
|
|
int GetInt(const char* pszKeyName, int iDefaultValue);
|
|
|
|
uint64_t GetUint64(const char* pszKeyName, uint64_t nDefaultValue);
|
|
|
|
void* GetPtr(const char* pszKeyName, void* pDefaultValue);
|
|
|
|
float GetFloat(const char* pszKeyName, float flDefaultValue);
|
|
|
|
const char* GetString(const char* pszKeyName = nullptr, const char* pszDefaultValue = "");
|
|
|
|
const wchar_t* GetWString(const char* pszKeyName = nullptr, const wchar_t* pwszDefaultValue = L"");
|
|
|
|
Color GetColor(const char* pszKeyName, const Color& defaultColor);
|
2022-11-23 10:34:11 +01:00
|
|
|
bool GetBool(const char* pszKeyName = nullptr, bool nDefaultValue = false) { return GetInt(pszKeyName, nDefaultValue ? 1 : 0) ? true : false; }
|
2022-05-28 16:31:38 +02:00
|
|
|
KeyValuesTypes_t GetDataType(const char* pszKeyName);
|
|
|
|
KeyValuesTypes_t GetDataType(void) const;
|
|
|
|
|
|
|
|
// Key writing
|
|
|
|
void SetInt(const char* pszKeyName, int iValue);
|
|
|
|
void SetUint64(const char* pszKeyName, uint64_t nValue);
|
|
|
|
void SetPtr(const char* pszKeyName, void* pValue);
|
|
|
|
void SetNextKey(KeyValues* pDat);
|
|
|
|
void SetName(const char* pszName);
|
|
|
|
void SetString(const char* pszKeyName, const char* pszValue);
|
|
|
|
void SetWString(const char* pszKeyName, const wchar_t* pwszValue);
|
|
|
|
void SetStringValue(char const* pszValue);
|
|
|
|
void SetColor(const char* pszKeyName, Color color);
|
|
|
|
void SetFloat(const char* pszKeyName, float flValue);
|
2022-11-22 09:04:28 +01:00
|
|
|
void SetBool(const char* pszKeyName, bool bValue) { SetInt(pszKeyName, bValue ? 1 : 0); }
|
2022-11-23 10:34:11 +01:00
|
|
|
void UsesEscapeSequences(bool bState);
|
2022-05-28 16:31:38 +02:00
|
|
|
|
2022-11-22 09:04:28 +01:00
|
|
|
void RecursiveSaveToFile(CUtlBuffer& buf, int nIndentLevel);
|
2024-04-05 17:42:05 +02:00
|
|
|
|
|
|
|
bool LoadFromFile(IBaseFileSystem* filesystem, const char* resourceName, const char* pathID, GetSymbolProc_t pfnEvaluateSymbolProc = nullptr);
|
|
|
|
|
|
|
|
bool LoadFromBuffer(char const* resourceName, CUtlBuffer& buf, IBaseFileSystem* pFileSystem, const char* pPathID, GetSymbolProc_t pfnEvaluateSymbolProc = nullptr);
|
|
|
|
bool LoadFromBuffer(char const* resourceName, const char* pBuffer, IBaseFileSystem* pFileSystem, const char* pPathID, GetSymbolProc_t pfnEvaluateSymbolProc = nullptr);
|
|
|
|
|
|
|
|
// for handling #include "filename"
|
|
|
|
void AppendIncludedKeys(CUtlVector< KeyValues* >& includedKeys);
|
|
|
|
void ParseIncludedKeys(char const* resourceName, const char* filetoinclude,
|
|
|
|
IBaseFileSystem* pFileSystem, const char* pPathID, CUtlVector< KeyValues* >& includedKeys, GetSymbolProc_t pfnEvaluateSymbolProc);
|
|
|
|
|
|
|
|
// For handling #base "filename"
|
|
|
|
void MergeBaseKeys(CUtlVector< KeyValues* >& baseKeys);
|
|
|
|
void RecursiveMergeKeyValues(KeyValues* baseKV);
|
2022-11-22 09:04:28 +01:00
|
|
|
|
2022-05-28 16:31:38 +02:00
|
|
|
void CopySubkeys(KeyValues* pParent) const;
|
|
|
|
KeyValues* MakeCopy(void) const;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
2024-04-05 17:42:05 +02:00
|
|
|
KeyValues* CreateKeyUsingKnownLastChild(const char* keyName, KeyValues* pLastChild);
|
|
|
|
void AddSubkeyUsingKnownLastChild(KeyValues* pSubKey, KeyValues* pLastChild);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void RecursiveSaveToFile(IBaseFileSystem* pFileSystem, FileHandle_t pHandle, CUtlBuffer* pBuf, int nIndentLevel);
|
|
|
|
void RecursiveLoadFromBuffer(char const* resourceName, CKeyValuesTokenReader& tokenReader, GetSymbolProc_t pfnEvaluateSymbolProc);
|
|
|
|
|
|
|
|
void RecursiveCopyKeyValues(KeyValues& src);
|
|
|
|
|
|
|
|
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
|
|
|
|
// If filesystem is null, it'll ignore f.
|
|
|
|
void InternalWrite(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, const void* pData, ssize_t len);
|
|
|
|
void WriteIndents(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, int indentLevel);
|
|
|
|
void WriteConvertedString(IBaseFileSystem* pFileSystem, FileHandle_t pHandle, CUtlBuffer* pBuf, const char* pszString);
|
|
|
|
|
|
|
|
bool EvaluateConditional(const char* pExpressionString, GetSymbolProc_t pfnEvaluateSymbolProc);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
public:
|
2022-11-23 17:32:24 +01:00
|
|
|
uint32_t m_iKeyName : 24;// 0x0000
|
|
|
|
uint32_t m_iKeyNameCaseSensitive1 : 8; // 0x0003
|
2021-12-25 22:36:38 +01:00
|
|
|
char* m_sValue; // 0x0008
|
|
|
|
wchar_t* m_wsValue; // 0x0010
|
2022-05-27 02:08:51 +02:00
|
|
|
union // 0x0018
|
|
|
|
{
|
2022-05-28 16:31:38 +02:00
|
|
|
int m_iValue;
|
|
|
|
float m_flValue;
|
|
|
|
void* m_pValue;
|
2022-05-27 02:08:51 +02:00
|
|
|
unsigned char m_Color[4];
|
|
|
|
};
|
|
|
|
char m_szShortName[8]; // 0x0020
|
2021-12-25 22:36:38 +01:00
|
|
|
char m_iDataType; // 0x0028
|
2022-05-28 16:31:38 +02:00
|
|
|
char m_bHasEscapeSequences; // 0x0029
|
2021-12-25 22:36:38 +01:00
|
|
|
uint16_t m_iKeyNameCaseSensitive2; // 0x002A
|
|
|
|
KeyValues* m_pPeer; // 0x0030
|
|
|
|
KeyValues* m_pSub; // 0x0038
|
|
|
|
KeyValues* m_pChain; // 0x0040
|
|
|
|
};
|