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

549 lines
23 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef KEYVALUES_H
  8. #define KEYVALUES_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #ifndef NULL
  13. #ifdef __cplusplus
  14. #define NULL 0
  15. #else
  16. #define NULL ((void *)0)
  17. #endif
  18. #endif
  19. #include "utlvector.h"
  20. #include "color.h"
  21. #include "exprevaluator.h"
  22. #define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
  23. for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
  24. #define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
  25. for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
  26. #define FOR_EACH_VALUE( kvRoot, kvValue ) \
  27. for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
  28. class IBaseFileSystem;
  29. class CUtlBuffer;
  30. class Color;
  31. class CKeyValuesTokenReader;
  32. class KeyValues;
  33. class IKeyValuesDumpContext;
  34. typedef void * FileHandle_t;
  35. class CKeyValuesGrowableStringTable;
  36. // single byte identifies a xbox kv file in binary format
  37. // strings are pooled from a searchpath/zip mounted symbol table
  38. #define KV_BINARY_POOLED_FORMAT 0xAA
  39. #define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
  40. for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
  41. #define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
  42. for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
  43. #define FOR_EACH_VALUE( kvRoot, kvValue ) \
  44. for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
  45. //-----------------------------------------------------------------------------
  46. // Purpose: Simple recursive data access class
  47. // Used in vgui for message parameters and resource files
  48. // Destructor deletes all child KeyValues nodes
  49. // Data is stored in key (string names) - (string/int/float)value pairs called nodes.
  50. //
  51. // About KeyValues Text File Format:
  52. // It has 3 control characters '{', '}' and '"'. Names and values may be quoted or
  53. // not. The quote '"' character must not be used within name or values, only for
  54. // quoting whole tokens. You may use escape sequences wile parsing and add within a
  55. // quoted token a \" to add quotes within your name or token. When using Escape
  56. // Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ),
  57. // which it's off by default. Non-quoted tokens ends with a whitespace, '{', '}' and '"'.
  58. // So you may use '{' and '}' within quoted tokens, but not for non-quoted tokens.
  59. // An open bracket '{' after a key name indicates a list of subkeys which is finished
  60. // with a closing bracket '}'. Subkeys use the same definitions recursively.
  61. // Whitespaces are space, return, newline and tabulator. Allowed Escape sequences
  62. // are \n, \t, \\, \n and \". The number character '#' is used for macro purposes
  63. // (eg #include), don't use it as first character in key names.
  64. //-----------------------------------------------------------------------------
  65. class KeyValues
  66. {
  67. friend class CKeyValuesTokenReader;
  68. public:
  69. // By default, the KeyValues class uses a string table for the key names that is
  70. // limited to 4MB. The game will exit in error if this space is exhausted. In
  71. // general this is preferable for game code for performance and memory fragmentation
  72. // reasons.
  73. //
  74. // If this is not acceptable, you can use this call to switch to a table that can grow
  75. // arbitrarily. This call must be made before any KeyValues objects are allocated or it
  76. // will result in undefined behavior. If you use the growable string table, you cannot
  77. // share KeyValues pointers directly with any other module. You can serialize them across
  78. // module boundaries. These limitations are acceptable in the Steam backend code
  79. // this option was written for, but may not be in other situations. Make sure to
  80. // understand the implications before using this.
  81. static void SetUseGrowableStringTable( bool bUseGrowableTable );
  82. explicit KeyValues( const char *setName );
  83. //
  84. // AutoDelete class to automatically free the keyvalues.
  85. // Simply construct it with the keyvalues you allocated and it will free them when falls out of scope.
  86. // When you decide that keyvalues shouldn't be deleted call Assign(NULL) on it.
  87. // If you constructed AutoDelete(NULL) you can later assign the keyvalues to be deleted with Assign(pKeyValues).
  88. //
  89. class AutoDelete
  90. {
  91. public:
  92. explicit inline AutoDelete( KeyValues *pKeyValues ) : m_pKeyValues( pKeyValues ) {}
  93. explicit inline AutoDelete( const char *pchKVName ) : m_pKeyValues( new KeyValues( pchKVName ) ) {}
  94. inline ~AutoDelete( void ) { delete m_pKeyValues; }
  95. inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = pKeyValues; }
  96. /// behaves more like an auto pointer detach ( flags itself to not delete the contained object, and returns a pointer to it)
  97. inline KeyValues * Detach() { KeyValues *retval = m_pKeyValues; Assign( NULL ); return retval; }
  98. KeyValues *operator->() { return m_pKeyValues; }
  99. operator KeyValues *() { return m_pKeyValues; }
  100. private:
  101. AutoDelete( AutoDelete const &x ); // forbid
  102. AutoDelete & operator= ( AutoDelete const &x ); // forbid
  103. protected:
  104. KeyValues *m_pKeyValues;
  105. };
  106. //
  107. // AutoDeleteInline is useful when you want to hold your keyvalues object inside
  108. // and delete it right after using.
  109. // You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDeleteInline
  110. // instance: call_my_function( KeyValues::AutoDeleteInline( new KeyValues( "test" ) ) )
  111. //
  112. class AutoDeleteInline : public AutoDelete
  113. {
  114. public:
  115. explicit inline AutoDeleteInline( KeyValues *pKeyValues ) : AutoDelete( pKeyValues ) {}
  116. inline operator KeyValues *() const { return m_pKeyValues; }
  117. inline KeyValues * Get() const { return m_pKeyValues; }
  118. };
  119. // Quick setup constructors
  120. KeyValues( const char *setName, const char *firstKey, const char *firstValue );
  121. KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue );
  122. KeyValues( const char *setName, const char *firstKey, int firstValue );
  123. KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue );
  124. KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue );
  125. // destruct
  126. ~KeyValues();
  127. // Section name
  128. const char *GetName() const;
  129. void SetName( const char *setName);
  130. // gets the name as a unique int
  131. int GetNameSymbol() const;
  132. int GetNameSymbolCaseSensitive() const;
  133. // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
  134. void UsesEscapeSequences(bool state); // default false
  135. bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL);
  136. bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool bWriteEmptySubkeys = false);
  137. // Read from a buffer... Note that the buffer must be null terminated
  138. bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
  139. // Read from a utlbuffer...
  140. bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
  141. // Find a keyValue, create it if it is not found.
  142. // Set bCreate to true to create the key if it doesn't already exist (which ensures a valid pointer will be returned)
  143. KeyValues *FindKey(const char *keyName, bool bCreate = false);
  144. KeyValues *FindKey(int keySymbol) const;
  145. KeyValues *CreateNewKey(); // creates a new key, with an autogenerated name. name is guaranteed to be an integer, of value 1 higher than the highest other integer key name
  146. void AddSubKey( KeyValues *pSubkey ); // Adds a subkey. Make sure the subkey isn't a child of some other keyvalues
  147. void RemoveSubKey(KeyValues *subKey); // removes a subkey from the list, DOES NOT DELETE IT
  148. void InsertSubKey( int nIndex, KeyValues *pSubKey ); // Inserts the given sub-key before the Nth child location
  149. bool ContainsSubKey( KeyValues *pSubKey ); // Returns true if this key values contains the specified sub key, false otherwise.
  150. void SwapSubKey( KeyValues *pExistingSubKey, KeyValues *pNewSubKey ); // Swaps an existing subkey for a new one, DOES NOT DELETE THE OLD ONE but takes ownership of the new one
  151. void ElideSubKey( KeyValues *pSubKey ); // Removes a subkey but inserts all of its children in its place, in-order (flattens a tree, like firing a manager!)
  152. KeyValues* CreateKey( const char *keyName );
  153. KeyValues* CreatePeerKey( const char *keyName );
  154. // Key iteration.
  155. //
  156. // NOTE: GetFirstSubKey/GetNextKey will iterate keys AND values. Use the functions
  157. // below if you want to iterate over just the keys or just the values.
  158. //
  159. KeyValues *GetFirstSubKey() const; // returns the first subkey in the list
  160. KeyValues *GetNextKey() const; // returns the next subkey
  161. void SetNextKey( KeyValues * pDat);
  162. KeyValues *FindLastSubKey(); // returns the LAST subkey in the list. This requires a linked list iteration to find the key. Returns NULL if we don't have any children
  163. bool BInteriorNode() const
  164. {
  165. return GetFirstSubKey() != NULL;
  166. }
  167. bool BLeafNode() const
  168. {
  169. return GetFirstSubKey() == NULL;
  170. }
  171. //
  172. // These functions can be used to treat it like a true key/values tree instead of
  173. // confusing values with keys.
  174. //
  175. // So if you wanted to iterate all subkeys, then all values, it would look like this:
  176. // for ( KeyValues *pKey = pRoot->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
  177. // {
  178. // Msg( "Key name: %s\n", pKey->GetName() );
  179. // }
  180. // for ( KeyValues *pValue = pRoot->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
  181. // {
  182. // Msg( "Int value: %d\n", pValue->GetInt() ); // Assuming pValue->GetDataType() == TYPE_INT...
  183. // }
  184. KeyValues* GetFirstTrueSubKey();
  185. KeyValues* GetNextTrueSubKey();
  186. KeyValues* GetFirstValue(); // When you get a value back, you can use GetX and pass in NULL to get the value.
  187. KeyValues* GetNextValue();
  188. // Data access
  189. int GetInt( const char *keyName = NULL, int defaultValue = 0 );
  190. uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 );
  191. float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f );
  192. const char *GetString( const char *keyName = NULL, const char *defaultValue = "" );
  193. const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" );
  194. void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 );
  195. Color GetColor( const char *keyName = NULL , const Color &defaultColor = Color( 0, 0, 0, 0 ) );
  196. bool GetBool( const char *keyName = NULL, bool defaultValue = false ) { return GetInt( keyName, defaultValue ? 1 : 0 ) ? true : false; }
  197. bool IsEmpty(const char *keyName = NULL);
  198. // Data access
  199. int GetInt( int keySymbol, int defaultValue = 0 );
  200. uint64 GetUint64( int keySymbol, uint64 defaultValue = 0 );
  201. float GetFloat( int keySymbol, float defaultValue = 0.0f );
  202. const char *GetString( int keySymbol, const char *defaultValue = "" );
  203. const wchar_t *GetWString( int keySymbol, const wchar_t *defaultValue = L"" );
  204. void *GetPtr( int keySymbol, void *defaultValue = (void*)0 );
  205. Color GetColor( int keySymbol /* default value is all black */);
  206. bool GetBool( int keySymbol, bool defaultValue = false ) { return GetInt( keySymbol, defaultValue ? 1 : 0 ) ? true : false; }
  207. bool IsEmpty( int keySymbol );
  208. // Key writing
  209. void SetWString( const char *keyName, const wchar_t *value );
  210. void SetString( const char *keyName, const char *value );
  211. void SetInt( const char *keyName, int value );
  212. void SetUint64( const char *keyName, uint64 value );
  213. void SetFloat( const char *keyName, float value );
  214. void SetPtr( const char *keyName, void *value );
  215. void SetColor( const char *keyName, Color value);
  216. void SetBool( const char *keyName, bool value ) { SetInt( keyName, value ? 1 : 0 ); }
  217. // Memory allocation (optimized)
  218. void *operator new( size_t iAllocSize );
  219. void *operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine );
  220. void operator delete( void *pMem );
  221. void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine );
  222. KeyValues& operator=( KeyValues& src );
  223. bool IsEqual( KeyValues *pRHS );
  224. // Adds a chain... if we don't find stuff in this keyvalue, we'll look
  225. // in the one we're chained to.
  226. void ChainKeyValue( KeyValues* pChain );
  227. void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel );
  228. bool WriteAsBinary( CUtlBuffer &buffer ) const;
  229. bool ReadAsBinary( CUtlBuffer &buffer, int nStackDepth = 0 );
  230. // Same as the other binary functions, but filter out and remove empty keys (like when seralizing to a file )
  231. bool WriteAsBinaryFiltered( CUtlBuffer &buffer );
  232. bool ReadAsBinaryFiltered( CUtlBuffer &buffer, int nStackDepth = 0 );
  233. // Allocate & create a new copy of the keys
  234. KeyValues *MakeCopy( void ) const;
  235. // Make a new copy of all subkeys, add them all to the passed-in keyvalues
  236. void CopySubkeys( KeyValues *pParent ) const;
  237. // Clear out all subkeys, and the current value
  238. void Clear( void );
  239. // Data type
  240. enum types_t
  241. {
  242. TYPE_NONE = 0,
  243. TYPE_STRING,
  244. TYPE_INT,
  245. TYPE_FLOAT,
  246. TYPE_PTR,
  247. TYPE_WSTRING,
  248. TYPE_COLOR,
  249. TYPE_UINT64,
  250. TYPE_COMPILED_INT_BYTE, // hack to collapse 1 byte ints in the compiled format
  251. TYPE_COMPILED_INT_0, // hack to collapse 0 in the compiled format
  252. TYPE_COMPILED_INT_1, // hack to collapse 1 in the compiled format
  253. TYPE_NUMTYPES,
  254. };
  255. types_t GetDataType(const char *keyName = NULL);
  256. types_t GetDataType() const;
  257. // for backward compat
  258. void deleteThis();
  259. void SetStringValue( char const *strValue );
  260. // unpack a key values list into a structure
  261. void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest );
  262. // Process conditional keys for widescreen support.
  263. bool ProcessResolutionKeys( const char *pResString );
  264. // Dump keyvalues recursively into a dump context
  265. bool Dump( IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
  266. // Merge operations describing how two keyvalues can be combined
  267. enum MergeKeyValuesOp_t
  268. {
  269. MERGE_KV_ALL,
  270. MERGE_KV_UPDATE, // update values are copied into storage, adding new keys to storage or updating existing ones
  271. MERGE_KV_DELETE, // update values specify keys that get deleted from storage
  272. MERGE_KV_BORROW, // update values only update existing keys in storage, keys in update that do not exist in storage are discarded
  273. };
  274. void MergeFrom( KeyValues *kvMerge, MergeKeyValuesOp_t eOp = MERGE_KV_ALL );
  275. // Assign keyvalues from a string
  276. static KeyValues * FromString( char const *szName, char const *szStringVal, char const **ppEndOfParse = NULL );
  277. /// Create a child key, given that we know which child is currently the last child.
  278. /// This avoids the O(N^2) behaviour when adding children in sequence to KV,
  279. /// when CreateKey() wil have to re-locate the end of the list each time. This happens,
  280. /// for example, every time we load any KV file whatsoever.
  281. KeyValues* CreateKeyUsingKnownLastChild( const char *keyName, KeyValues *pLastChild );
  282. void AddSubkeyUsingKnownLastChild( KeyValues *pSubKey, KeyValues *pLastChild );
  283. private:
  284. KeyValues( KeyValues& ); // prevent copy constructor being used
  285. void RecursiveCopyKeyValues( KeyValues& src );
  286. void RemoveEverything();
  287. // void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel );
  288. // void WriteConvertedString( CUtlBuffer &buffer, const char *pszString );
  289. // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
  290. // If filesystem is null, it'll ignore f.
  291. void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel, bool bWriteEmptySubkeys = false );
  292. void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
  293. void RecursiveLoadFromBuffer( char const *resourceName, CKeyValuesTokenReader &buf, GetSymbolProc_t pfnEvaluateSymbolProc );
  294. // for handling #include "filename"
  295. void AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys );
  296. void ParseIncludedKeys( char const *resourceName, const char *filetoinclude,
  297. IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys, GetSymbolProc_t pfnEvaluateSymbolProc );
  298. // For handling #base "filename"
  299. void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
  300. void RecursiveMergeKeyValues( KeyValues *baseKV );
  301. // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
  302. // If filesystem is null, it'll ignore f.
  303. void InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len );
  304. void Init();
  305. void WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
  306. void FreeAllocatedValue();
  307. void AllocateValueBlock(int size);
  308. bool ReadAsBinaryPooledFormat( CUtlBuffer &buf, IBaseFileSystem *pFileSystem, unsigned int poolKey, GetSymbolProc_t pfnEvaluateSymbolProc );
  309. bool EvaluateConditional( const char *pExpressionString, GetSymbolProc_t pfnEvaluateSymbolProc );
  310. uint32 m_iKeyName : 24; // keyname is a symbol defined in KeyValuesSystem
  311. uint32 m_iKeyNameCaseSensitive1 : 8; // 1st part of case sensitive symbol defined in KeyValueSystem
  312. // These are needed out of the union because the API returns string pointers
  313. char *m_sValue;
  314. wchar_t *m_wsValue;
  315. // we don't delete these
  316. union
  317. {
  318. int m_iValue;
  319. float m_flValue;
  320. void *m_pValue;
  321. unsigned char m_Color[4];
  322. };
  323. char m_iDataType;
  324. char m_bHasEscapeSequences; // true, if while parsing this KeyValue, Escape Sequences are used (default false)
  325. uint16 m_iKeyNameCaseSensitive2; // 2nd part of case sensitive symbol defined in KeyValueSystem;
  326. KeyValues *m_pPeer; // pointer to next key in list
  327. KeyValues *m_pSub; // pointer to Start of a new sub key list
  328. KeyValues *m_pChain;// Search here if it's not in our list
  329. GetSymbolProc_t m_pExpressionGetSymbolProc;
  330. private:
  331. // Statics to implement the optional growable string table
  332. // Function pointers that will determine which mode we are in
  333. static int (*s_pfGetSymbolForString)( const char *name, bool bCreate );
  334. static const char *(*s_pfGetStringForSymbol)( int symbol );
  335. static CKeyValuesGrowableStringTable *s_pGrowableStringTable;
  336. public:
  337. // Functions that invoke the default behavior
  338. static int GetSymbolForStringClassic( const char *name, bool bCreate = true );
  339. static const char *GetStringForSymbolClassic( int symbol );
  340. // Functions that use the growable string table
  341. static int GetSymbolForStringGrowable( const char *name, bool bCreate = true );
  342. static const char *GetStringForSymbolGrowable( int symbol );
  343. };
  344. typedef KeyValues::AutoDelete KeyValuesAD;
  345. enum KeyValuesUnpackDestinationTypes_t
  346. {
  347. UNPACK_TYPE_FLOAT, // dest is a float
  348. UNPACK_TYPE_VECTOR, // dest is a Vector
  349. UNPACK_TYPE_VECTOR_COLOR, // dest is a vector, src is a color
  350. UNPACK_TYPE_STRING, // dest is a char *. unpacker will allocate.
  351. UNPACK_TYPE_INT, // dest is an int
  352. UNPACK_TYPE_FOUR_FLOATS, // dest is an array of 4 floats. source is a string like "1 2 3 4"
  353. UNPACK_TYPE_TWO_FLOATS, // dest is an array of 2 floats. source is a string like "1 2"
  354. };
  355. #define UNPACK_FIXED( kname, kdefault, dtype, ofs ) { kname, kdefault, dtype, ofs, 0 }
  356. #define UNPACK_VARIABLE( kname, kdefault, dtype, ofs, sz ) { kname, kdefault, dtype, ofs, sz }
  357. #define UNPACK_END_MARKER { NULL, NULL, UNPACK_TYPE_FLOAT, 0 }
  358. struct KeyValuesUnpackStructure
  359. {
  360. char const *m_pKeyName; // null to terminate tbl
  361. char const *m_pKeyDefault; // null ok
  362. KeyValuesUnpackDestinationTypes_t m_eDataType; // UNPACK_TYPE_INT, ..
  363. size_t m_nFieldOffset; // use offsetof to set
  364. size_t m_nFieldSize; // for strings or other variable length
  365. };
  366. //-----------------------------------------------------------------------------
  367. // inline methods
  368. //-----------------------------------------------------------------------------
  369. inline int KeyValues::GetInt( int keySymbol, int defaultValue )
  370. {
  371. KeyValues *dat = FindKey( keySymbol );
  372. return dat ? dat->GetInt( (const char *)NULL, defaultValue ) : defaultValue;
  373. }
  374. inline uint64 KeyValues::GetUint64( int keySymbol, uint64 defaultValue )
  375. {
  376. KeyValues *dat = FindKey( keySymbol );
  377. return dat ? dat->GetUint64( (const char *)NULL, defaultValue ) : defaultValue;
  378. }
  379. inline float KeyValues::GetFloat( int keySymbol, float defaultValue )
  380. {
  381. KeyValues *dat = FindKey( keySymbol );
  382. return dat ? dat->GetFloat( (const char *)NULL, defaultValue ) : defaultValue;
  383. }
  384. inline const char *KeyValues::GetString( int keySymbol, const char *defaultValue )
  385. {
  386. KeyValues *dat = FindKey( keySymbol );
  387. return dat ? dat->GetString( (const char *)NULL, defaultValue ) : defaultValue;
  388. }
  389. inline const wchar_t *KeyValues::GetWString( int keySymbol, const wchar_t *defaultValue )
  390. {
  391. KeyValues *dat = FindKey( keySymbol );
  392. return dat ? dat->GetWString( (const char *)NULL, defaultValue ) : defaultValue;
  393. }
  394. inline void *KeyValues::GetPtr( int keySymbol, void *defaultValue )
  395. {
  396. KeyValues *dat = FindKey( keySymbol );
  397. return dat ? dat->GetPtr( (const char *)NULL, defaultValue ) : defaultValue;
  398. }
  399. inline Color KeyValues::GetColor( int keySymbol )
  400. {
  401. Color defaultValue( 0, 0, 0, 0 );
  402. KeyValues *dat = FindKey( keySymbol );
  403. return dat ? dat->GetColor( ) : defaultValue;
  404. }
  405. inline bool KeyValues::IsEmpty( int keySymbol )
  406. {
  407. KeyValues *dat = FindKey( keySymbol );
  408. return dat ? dat->IsEmpty( ) : true;
  409. }
  410. //
  411. // KeyValuesDumpContext and generic implementations
  412. //
  413. class IKeyValuesDumpContext
  414. {
  415. public:
  416. virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel ) = 0;
  417. virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel ) = 0;
  418. virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel ) = 0;
  419. };
  420. class IKeyValuesDumpContextAsText : public IKeyValuesDumpContext
  421. {
  422. public:
  423. virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
  424. virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel );
  425. virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel );
  426. public:
  427. virtual bool KvWriteIndent( int nIndentLevel );
  428. virtual bool KvWriteText( char const *szText ) = 0;
  429. };
  430. class CKeyValuesDumpContextAsDevMsg : public IKeyValuesDumpContextAsText
  431. {
  432. public:
  433. // Overrides developer level to dump in DevMsg, zero to dump as Msg
  434. CKeyValuesDumpContextAsDevMsg( int nDeveloperLevel = 1 ) : m_nDeveloperLevel( nDeveloperLevel ) {}
  435. public:
  436. virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
  437. virtual bool KvWriteText( char const *szText );
  438. protected:
  439. int m_nDeveloperLevel;
  440. };
  441. inline bool KeyValuesDumpAsDevMsg( KeyValues *pKeyValues, int nIndentLevel = 0, int nDeveloperLevel = 1 )
  442. {
  443. CKeyValuesDumpContextAsDevMsg ctx( nDeveloperLevel );
  444. return pKeyValues->Dump( &ctx, nIndentLevel );
  445. }
  446. #endif // KEYVALUES_H