Team Fortress 2 Source Code as on 22/4/2020
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.

3427 lines
85 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #if defined( _WIN32 ) && !defined( _X360 )
  9. #include <windows.h> // for widechartomultibyte and multibytetowidechar
  10. #elif defined(POSIX)
  11. #include <wchar.h> // wcslen()
  12. #define _alloca alloca
  13. #define _wtoi(arg) wcstol(arg, NULL, 10)
  14. #define _wtoi64(arg) wcstoll(arg, NULL, 10)
  15. #endif
  16. #include <keyvalues.h>
  17. #include "filesystem.h"
  18. #include <vstdlib/ikeyvaluessystem.h>
  19. #include <color.h>
  20. #include <stdlib.h>
  21. #include <ctype.h>
  22. #include "tier1/convar.h"
  23. #include "tier0/dbg.h"
  24. #include "tier0/mem.h"
  25. #include "utlvector.h"
  26. #include "utlbuffer.h"
  27. #include "utlhash.h"
  28. #include <vstdlib/vstrtools.h>
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include <tier0/memdbgon.h>
  31. //////// VPROF? //////////////////
  32. // For an example of how to mark up this file with VPROF nodes, see
  33. // changelist 702984. However, be aware that calls to FindKey and Init
  34. // may occur outside of Vprof's usual hierarchy, which can cause strange
  35. // duplicate KeyValues::FindKey nodes at the root level and other
  36. // confusing effects.
  37. //////////////////////////////////
  38. static char * s_LastFileLoadingFrom = "unknown"; // just needed for error messages
  39. // Statics for the growable string table
  40. int (*KeyValues::s_pfGetSymbolForString)( const char *name, bool bCreate ) = &KeyValues::GetSymbolForStringClassic;
  41. const char *(*KeyValues::s_pfGetStringForSymbol)( int symbol ) = &KeyValues::GetStringForSymbolClassic;
  42. CKeyValuesGrowableStringTable *KeyValues::s_pGrowableStringTable = NULL;
  43. #define KEYVALUES_TOKEN_SIZE 1024
  44. static char s_pTokenBuf[KEYVALUES_TOKEN_SIZE];
  45. #define INTERNALWRITE( pData, len ) InternalWrite( filesystem, f, pBuf, pData, len )
  46. #define MAKE_3_BYTES_FROM_1_AND_2( x1, x2 ) (( (( uint16 )x2) << 8 ) | (uint8)(x1))
  47. #define SPLIT_3_BYTES_INTO_1_AND_2( x1, x2, x3 ) do { x1 = (uint8)(x3); x2 = (uint16)( (x3) >> 8 ); } while( 0 )
  48. CExpressionEvaluator g_ExpressionEvaluator;
  49. // a simple class to keep track of a stack of valid parsed symbols
  50. const int MAX_ERROR_STACK = 64;
  51. class CKeyValuesErrorStack
  52. {
  53. public:
  54. CKeyValuesErrorStack() : m_pFilename("NULL"), m_errorIndex(0), m_maxErrorIndex(0) {}
  55. void SetFilename( const char *pFilename )
  56. {
  57. m_pFilename = pFilename;
  58. m_maxErrorIndex = 0;
  59. }
  60. // entering a new keyvalues block, save state for errors
  61. // Not save symbols instead of pointers because the pointers can move!
  62. int Push( int symName )
  63. {
  64. if ( m_errorIndex < MAX_ERROR_STACK )
  65. {
  66. m_errorStack[m_errorIndex] = symName;
  67. }
  68. m_errorIndex++;
  69. m_maxErrorIndex = MAX( m_maxErrorIndex, (m_errorIndex-1) );
  70. return m_errorIndex-1;
  71. }
  72. // exiting block, error isn't in this block, remove.
  73. void Pop()
  74. {
  75. m_errorIndex--;
  76. Assert(m_errorIndex>=0);
  77. }
  78. // Allows you to keep the same stack level, but change the name as you parse peers
  79. void Reset( int stackLevel, int symName )
  80. {
  81. Assert( stackLevel >= 0 && stackLevel < m_errorIndex );
  82. m_errorStack[stackLevel] = symName;
  83. }
  84. // Hit an error, report it and the parsing stack for context
  85. void ReportError( const char *pError )
  86. {
  87. Warning( "KeyValues Error: %s in file %s\n", pError, m_pFilename );
  88. for ( int i = 0; i < m_maxErrorIndex; i++ )
  89. {
  90. if ( m_errorStack[i] != INVALID_KEY_SYMBOL )
  91. {
  92. if ( i < m_errorIndex )
  93. {
  94. Warning( "%s, ", KeyValuesSystem()->GetStringForSymbol(m_errorStack[i]) );
  95. }
  96. else
  97. {
  98. Warning( "(*%s*), ", KeyValuesSystem()->GetStringForSymbol(m_errorStack[i]) );
  99. }
  100. }
  101. }
  102. Warning( "\n" );
  103. }
  104. private:
  105. int m_errorStack[MAX_ERROR_STACK];
  106. const char *m_pFilename;
  107. int m_errorIndex;
  108. int m_maxErrorIndex;
  109. } g_KeyValuesErrorStack;
  110. // a simple helper that creates stack entries as it goes in & out of scope
  111. class CKeyErrorContext
  112. {
  113. public:
  114. ~CKeyErrorContext()
  115. {
  116. g_KeyValuesErrorStack.Pop();
  117. }
  118. explicit CKeyErrorContext( int symName )
  119. {
  120. Init( symName );
  121. }
  122. void Reset( int symName )
  123. {
  124. g_KeyValuesErrorStack.Reset( m_stackLevel, symName );
  125. }
  126. private:
  127. void Init( int symName )
  128. {
  129. m_stackLevel = g_KeyValuesErrorStack.Push( symName );
  130. }
  131. int m_stackLevel;
  132. };
  133. // Uncomment this line to hit the ~CLeakTrack assert to see what's looking like it's leaking
  134. // #define LEAKTRACK
  135. #ifdef LEAKTRACK
  136. class CLeakTrack
  137. {
  138. public:
  139. CLeakTrack()
  140. {
  141. }
  142. ~CLeakTrack()
  143. {
  144. if ( keys.Count() != 0 )
  145. {
  146. Assert( 0 );
  147. }
  148. }
  149. struct kve
  150. {
  151. KeyValues *kv;
  152. char name[ 256 ];
  153. };
  154. void AddKv( KeyValues *kv, char const *name )
  155. {
  156. kve k;
  157. V_strncpy( k.name, name ? name : "NULL", sizeof( k.name ) );
  158. k.kv = kv;
  159. keys.AddToTail( k );
  160. }
  161. void RemoveKv( KeyValues *kv )
  162. {
  163. int c = keys.Count();
  164. for ( int i = 0; i < c; i++ )
  165. {
  166. if ( keys[i].kv == kv )
  167. {
  168. keys.Remove( i );
  169. break;
  170. }
  171. }
  172. }
  173. CUtlVector< kve > keys;
  174. };
  175. static CLeakTrack track;
  176. #define TRACK_KV_ADD( ptr, name ) track.AddKv( ptr, name )
  177. #define TRACK_KV_REMOVE( ptr ) track.RemoveKv( ptr )
  178. #else
  179. #define TRACK_KV_ADD( ptr, name )
  180. #define TRACK_KV_REMOVE( ptr )
  181. #endif
  182. //-----------------------------------------------------------------------------
  183. // Purpose: An arbitrarily growable string table for KeyValues key names.
  184. // See the comment in the header for more info.
  185. //-----------------------------------------------------------------------------
  186. class CKeyValuesGrowableStringTable
  187. {
  188. public:
  189. // Constructor
  190. CKeyValuesGrowableStringTable() :
  191. m_vecStrings( 0, 512 * 1024 ),
  192. m_hashLookup( 2048, 0, 0, m_Functor, m_Functor )
  193. {
  194. m_vecStrings.AddToTail( '\0' );
  195. }
  196. // Translates a string to an index
  197. int GetSymbolForString( const char *name, bool bCreate = true )
  198. {
  199. AUTO_LOCK( m_mutex );
  200. // Put the current details into our hash functor
  201. m_Functor.SetCurString( name );
  202. m_Functor.SetCurStringBase( (const char *)m_vecStrings.Base() );
  203. if ( bCreate )
  204. {
  205. bool bInserted = false;
  206. UtlHashHandle_t hElement = m_hashLookup.Insert( -1, &bInserted );
  207. if ( bInserted )
  208. {
  209. int iIndex = m_vecStrings.AddMultipleToTail( V_strlen( name ) + 1, name );
  210. m_hashLookup[ hElement ] = iIndex;
  211. }
  212. return m_hashLookup[ hElement ];
  213. }
  214. else
  215. {
  216. UtlHashHandle_t hElement = m_hashLookup.Find( -1 );
  217. if ( m_hashLookup.IsValidHandle( hElement ) )
  218. return m_hashLookup[ hElement ];
  219. else
  220. return -1;
  221. }
  222. }
  223. // Translates an index back to a string
  224. const char *GetStringForSymbol( int symbol )
  225. {
  226. return (const char *)m_vecStrings.Base() + symbol;
  227. }
  228. private:
  229. // A class plugged into CUtlHash that allows us to change the behavior of the table
  230. // and store only the index in the table.
  231. class CLookupFunctor
  232. {
  233. public:
  234. CLookupFunctor() : m_pchCurString( NULL ), m_pchCurBase( NULL ) {}
  235. // Sets what we are currently inserting or looking for.
  236. void SetCurString( const char *pchCurString ) { m_pchCurString = pchCurString; }
  237. void SetCurStringBase( const char *pchCurBase ) { m_pchCurBase = pchCurBase; }
  238. // The compare function.
  239. bool operator()( int nLhs, int nRhs ) const
  240. {
  241. const char *pchLhs = nLhs > 0 ? m_pchCurBase + nLhs : m_pchCurString;
  242. const char *pchRhs = nRhs > 0 ? m_pchCurBase + nRhs : m_pchCurString;
  243. return ( 0 == V_stricmp( pchLhs, pchRhs ) );
  244. }
  245. // The hash function.
  246. unsigned int operator()( int nItem ) const
  247. {
  248. return HashStringCaseless( m_pchCurString );
  249. }
  250. private:
  251. const char *m_pchCurString;
  252. const char *m_pchCurBase;
  253. };
  254. CThreadFastMutex m_mutex;
  255. CLookupFunctor m_Functor;
  256. CUtlHash<int, CLookupFunctor &, CLookupFunctor &> m_hashLookup;
  257. CUtlVector<char> m_vecStrings;
  258. };
  259. //-----------------------------------------------------------------------------
  260. // Purpose: Sets whether the KeyValues system should use an arbitrarily growable
  261. // string table. See the comment in the header for more info.
  262. //-----------------------------------------------------------------------------
  263. void KeyValues::SetUseGrowableStringTable( bool bUseGrowableTable )
  264. {
  265. if ( bUseGrowableTable )
  266. {
  267. s_pfGetStringForSymbol = &(KeyValues::GetStringForSymbolGrowable);
  268. s_pfGetSymbolForString = &(KeyValues::GetSymbolForStringGrowable);
  269. if ( NULL == s_pGrowableStringTable )
  270. {
  271. s_pGrowableStringTable = new CKeyValuesGrowableStringTable;
  272. }
  273. }
  274. else
  275. {
  276. s_pfGetStringForSymbol = &(KeyValues::GetStringForSymbolClassic);
  277. s_pfGetSymbolForString = &(KeyValues::GetSymbolForStringClassic);
  278. }
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: Bodys of the function pointers used for interacting with the key
  282. // name string table
  283. //-----------------------------------------------------------------------------
  284. int KeyValues::GetSymbolForStringClassic( const char *name, bool bCreate )
  285. {
  286. return KeyValuesSystem()->GetSymbolForString( name, bCreate );
  287. }
  288. const char *KeyValues::GetStringForSymbolClassic( int symbol )
  289. {
  290. return KeyValuesSystem()->GetStringForSymbol( symbol );
  291. }
  292. int KeyValues::GetSymbolForStringGrowable( const char *name, bool bCreate )
  293. {
  294. return s_pGrowableStringTable->GetSymbolForString( name, bCreate );
  295. }
  296. const char *KeyValues::GetStringForSymbolGrowable( int symbol )
  297. {
  298. return s_pGrowableStringTable->GetStringForSymbol( symbol );
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: Constructor
  302. //-----------------------------------------------------------------------------
  303. KeyValues::KeyValues( const char *setName )
  304. {
  305. TRACK_KV_ADD( this, setName );
  306. Init();
  307. SetName ( setName );
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Purpose: Constructor
  311. //-----------------------------------------------------------------------------
  312. KeyValues::KeyValues( const char *setName, const char *firstKey, const char *firstValue )
  313. {
  314. TRACK_KV_ADD( this, setName );
  315. Init();
  316. SetName( setName );
  317. SetString( firstKey, firstValue );
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Purpose: Constructor
  321. //-----------------------------------------------------------------------------
  322. KeyValues::KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue )
  323. {
  324. TRACK_KV_ADD( this, setName );
  325. Init();
  326. SetName( setName );
  327. SetWString( firstKey, firstValue );
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose: Constructor
  331. //-----------------------------------------------------------------------------
  332. KeyValues::KeyValues( const char *setName, const char *firstKey, int firstValue )
  333. {
  334. TRACK_KV_ADD( this, setName );
  335. Init();
  336. SetName( setName );
  337. SetInt( firstKey, firstValue );
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Purpose: Constructor
  341. //-----------------------------------------------------------------------------
  342. KeyValues::KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue )
  343. {
  344. TRACK_KV_ADD( this, setName );
  345. Init();
  346. SetName( setName );
  347. SetString( firstKey, firstValue );
  348. SetString( secondKey, secondValue );
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose: Constructor
  352. //-----------------------------------------------------------------------------
  353. KeyValues::KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue )
  354. {
  355. TRACK_KV_ADD( this, setName );
  356. Init();
  357. SetName( setName );
  358. SetInt( firstKey, firstValue );
  359. SetInt( secondKey, secondValue );
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Purpose: Initialize member variables
  363. //-----------------------------------------------------------------------------
  364. void KeyValues::Init()
  365. {
  366. m_iKeyName = 0;
  367. m_iKeyNameCaseSensitive1 = 0;
  368. m_iKeyNameCaseSensitive2 = 0;
  369. m_iDataType = TYPE_NONE;
  370. m_pSub = NULL;
  371. m_pPeer = NULL;
  372. m_pChain = NULL;
  373. m_sValue = NULL;
  374. m_wsValue = NULL;
  375. m_pValue = NULL;
  376. m_bHasEscapeSequences = 0;
  377. }
  378. //-----------------------------------------------------------------------------
  379. // Purpose: Destructor
  380. //-----------------------------------------------------------------------------
  381. KeyValues::~KeyValues()
  382. {
  383. TRACK_KV_REMOVE( this );
  384. RemoveEverything();
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose: remove everything
  388. //-----------------------------------------------------------------------------
  389. void KeyValues::RemoveEverything()
  390. {
  391. KeyValues *dat;
  392. KeyValues *datNext = NULL;
  393. for ( dat = m_pSub; dat != NULL; dat = datNext )
  394. {
  395. datNext = dat->m_pPeer;
  396. dat->m_pPeer = NULL;
  397. delete dat;
  398. }
  399. for ( dat = m_pPeer; dat && dat != this; dat = datNext )
  400. {
  401. datNext = dat->m_pPeer;
  402. dat->m_pPeer = NULL;
  403. delete dat;
  404. }
  405. delete [] m_sValue;
  406. m_sValue = NULL;
  407. delete [] m_wsValue;
  408. m_wsValue = NULL;
  409. }
  410. //-----------------------------------------------------------------------------
  411. // Purpose:
  412. // Input : *f -
  413. //-----------------------------------------------------------------------------
  414. void KeyValues::RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel )
  415. {
  416. RecursiveSaveToFile( NULL, FILESYSTEM_INVALID_HANDLE, &buf, indentLevel );
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Adds a chain... if we don't find stuff in this keyvalue, we'll look
  420. // in the one we're chained to.
  421. //-----------------------------------------------------------------------------
  422. void KeyValues::ChainKeyValue( KeyValues* pChain )
  423. {
  424. m_pChain = pChain;
  425. }
  426. //-----------------------------------------------------------------------------
  427. // Purpose: Get the name of the current key section
  428. //-----------------------------------------------------------------------------
  429. const char *KeyValues::GetName( void ) const
  430. {
  431. return this ? KeyValuesSystem()->GetStringForSymbol( MAKE_3_BYTES_FROM_1_AND_2( m_iKeyNameCaseSensitive1, m_iKeyNameCaseSensitive2 ) ) : "";
  432. }
  433. //-----------------------------------------------------------------------------
  434. // Purpose: Get the symbol name of the current key section
  435. //-----------------------------------------------------------------------------
  436. int KeyValues::GetNameSymbol() const
  437. {
  438. return this ? m_iKeyName : INVALID_KEY_SYMBOL;
  439. }
  440. int KeyValues::GetNameSymbolCaseSensitive() const
  441. {
  442. return this ? MAKE_3_BYTES_FROM_1_AND_2( m_iKeyNameCaseSensitive1, m_iKeyNameCaseSensitive2 ) : INVALID_KEY_SYMBOL;
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose: Read a single token from buffer (0 terminated)
  446. //-----------------------------------------------------------------------------
  447. #pragma warning (disable:4706)
  448. const char *KeyValues::ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional )
  449. {
  450. wasQuoted = false;
  451. wasConditional = false;
  452. if ( !buf.IsValid() )
  453. return NULL;
  454. // eating white spaces and remarks loop
  455. while ( true )
  456. {
  457. buf.EatWhiteSpace();
  458. if ( !buf.IsValid() )
  459. return NULL; // file ends after reading whitespaces
  460. // stop if it's not a comment; a new token starts here
  461. if ( !buf.EatCPPComment() )
  462. break;
  463. }
  464. const char *c = (const char*)buf.PeekGet( sizeof(char), 0 );
  465. if ( !c )
  466. return NULL;
  467. // read quoted strings specially
  468. if ( *c == '\"' )
  469. {
  470. wasQuoted = true;
  471. buf.GetDelimitedString( m_bHasEscapeSequences ? GetCStringCharConversion() : GetNoEscCharConversion(),
  472. s_pTokenBuf, KEYVALUES_TOKEN_SIZE );
  473. return s_pTokenBuf;
  474. }
  475. if ( *c == '{' || *c == '}' )
  476. {
  477. // it's a control char, just add this one char and stop reading
  478. s_pTokenBuf[0] = *c;
  479. s_pTokenBuf[1] = 0;
  480. buf.SeekGet( CUtlBuffer::SEEK_CURRENT, 1 );
  481. return s_pTokenBuf;
  482. }
  483. // read in the token until we hit a whitespace or a control character
  484. bool bReportedError = false;
  485. bool bConditionalStart = false;
  486. int nCount = 0;
  487. while ( c = (const char*)buf.PeekGet( sizeof(char), 0 ) )
  488. {
  489. // end of file
  490. if ( *c == 0 )
  491. break;
  492. // break if any control character appears in non quoted tokens
  493. if ( *c == '"' || *c == '{' || *c == '}' )
  494. break;
  495. if ( *c == '[' )
  496. {
  497. bConditionalStart = true;
  498. }
  499. if ( *c == ']' && bConditionalStart )
  500. {
  501. bConditionalStart = false;
  502. wasConditional = true;
  503. }
  504. // conditionals need to get tokenized as delimited by []
  505. // othwerwise break on whitespace
  506. if ( V_isspace(*c) && !bConditionalStart )
  507. break;
  508. if (nCount < (KEYVALUES_TOKEN_SIZE-1) )
  509. {
  510. s_pTokenBuf[nCount++] = *c; // add char to buffer
  511. }
  512. else if ( !bReportedError )
  513. {
  514. bReportedError = true;
  515. g_KeyValuesErrorStack.ReportError(" ReadToken overflow" );
  516. }
  517. buf.SeekGet( CUtlBuffer::SEEK_CURRENT, 1 );
  518. }
  519. s_pTokenBuf[ nCount ] = 0;
  520. return s_pTokenBuf;
  521. }
  522. #pragma warning (default:4706)
  523. //-----------------------------------------------------------------------------
  524. // Purpose: if parser should translate escape sequences ( /n, /t etc), set to true
  525. //-----------------------------------------------------------------------------
  526. void KeyValues::UsesEscapeSequences(bool state)
  527. {
  528. m_bHasEscapeSequences = state;
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Purpose: Load keyValues from disk
  532. //-----------------------------------------------------------------------------
  533. bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID, GetSymbolProc_t pfnEvaluateSymbolProc )
  534. {
  535. #if defined( _WIN32 )
  536. Assert( IsGameConsole() || ( _heapchk() == _HEAPOK ) );
  537. #endif
  538. FileHandle_t f = filesystem->Open(resourceName, "rb", pathID);
  539. if ( !f )
  540. return false;
  541. s_LastFileLoadingFrom = (char*)resourceName;
  542. // load file into a null-terminated buffer
  543. int fileSize = filesystem->Size( f );
  544. unsigned bufSize = ((IFileSystem *)filesystem)->GetOptimalReadSize( f, fileSize + 2 );
  545. char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize );
  546. Assert( buffer );
  547. // read into local buffer
  548. bool bRetOK = ( ((IFileSystem *)filesystem)->ReadEx( buffer, bufSize, fileSize, f ) != 0 );
  549. filesystem->Close( f ); // close file after reading
  550. if ( bRetOK )
  551. {
  552. buffer[fileSize] = 0; // null terminate file as EOF
  553. buffer[fileSize+1] = 0; // double NULL terminating in case this is a unicode file
  554. CUtlBuffer utlBuffer;
  555. if ( IsGameConsole() && (unsigned int)((unsigned char *)buffer)[0] == KV_BINARY_POOLED_FORMAT )
  556. {
  557. // kv contents are compiled binary
  558. utlBuffer.SetExternalBuffer( buffer, bufSize, fileSize, CUtlBuffer::READ_ONLY );
  559. }
  560. else
  561. {
  562. // kv contents are text
  563. int nLen = V_strlen( buffer );
  564. utlBuffer.SetExternalBuffer( buffer, bufSize, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER );
  565. }
  566. bRetOK = LoadFromBuffer( resourceName, utlBuffer, filesystem, pathID, pfnEvaluateSymbolProc );
  567. }
  568. ((IFileSystem *)filesystem)->FreeOptimalReadBuffer( buffer );
  569. return bRetOK;
  570. }
  571. //-----------------------------------------------------------------------------
  572. // Purpose: Save the keyvalues to disk
  573. // Creates the path to the file if it doesn't exist
  574. //-----------------------------------------------------------------------------
  575. bool KeyValues::SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID )
  576. {
  577. // create a write file
  578. FileHandle_t f = filesystem->Open(resourceName, "wb", pathID);
  579. if ( f == FILESYSTEM_INVALID_HANDLE )
  580. {
  581. DevMsg( "KeyValues::SaveToFile: couldn't open file \"%s\" in path \"%s\".\n",
  582. resourceName?resourceName:"NULL", pathID?pathID:"NULL" );
  583. return false;
  584. }
  585. RecursiveSaveToFile(filesystem, f, NULL, 0);
  586. filesystem->Close(f);
  587. return true;
  588. }
  589. //-----------------------------------------------------------------------------
  590. // Purpose: Write out a set of indenting
  591. //-----------------------------------------------------------------------------
  592. void KeyValues::WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel )
  593. {
  594. for ( int i = 0; i < indentLevel; i++ )
  595. {
  596. INTERNALWRITE( "\t", 1 );
  597. }
  598. }
  599. //-----------------------------------------------------------------------------
  600. // Purpose: Write out a string where we convert the double quotes to backslash double quote
  601. //-----------------------------------------------------------------------------
  602. void KeyValues::WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString )
  603. {
  604. // handle double quote chars within the string
  605. // the worst possible case is that the whole string is quotes
  606. int len = V_strlen(pszString);
  607. char *convertedString = (char *) alloca ((len + 1) * sizeof(char) * 2);
  608. int j=0;
  609. for (int i=0; i <= len; i++)
  610. {
  611. if (pszString[i] == '\"')
  612. {
  613. convertedString[j] = '\\';
  614. j++;
  615. }
  616. else if ( m_bHasEscapeSequences && pszString[i] == '\\' )
  617. {
  618. convertedString[j] = '\\';
  619. j++;
  620. }
  621. convertedString[j] = pszString[i];
  622. j++;
  623. }
  624. INTERNALWRITE(convertedString, strlen(convertedString));
  625. }
  626. void KeyValues::InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len )
  627. {
  628. if ( filesystem )
  629. {
  630. filesystem->Write( pData, len, f );
  631. }
  632. if ( pBuf )
  633. {
  634. pBuf->Put( pData, len );
  635. }
  636. }
  637. //-----------------------------------------------------------------------------
  638. // Purpose: Save keyvalues from disk, if subkey values are detected, calls
  639. // itself to save those
  640. //-----------------------------------------------------------------------------
  641. void KeyValues::RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel )
  642. {
  643. // write header
  644. WriteIndents( filesystem, f, pBuf, indentLevel );
  645. INTERNALWRITE("\"", 1);
  646. WriteConvertedString(filesystem, f, pBuf, GetName());
  647. INTERNALWRITE("\"\n", 2);
  648. WriteIndents( filesystem, f, pBuf, indentLevel );
  649. INTERNALWRITE("{\n", 2);
  650. // loop through all our keys writing them to disk
  651. for ( KeyValues *dat = m_pSub; dat != NULL; dat = dat->m_pPeer )
  652. {
  653. if ( dat->m_pSub )
  654. {
  655. dat->RecursiveSaveToFile( filesystem, f, pBuf, indentLevel + 1 );
  656. }
  657. else
  658. {
  659. // only write non-empty keys
  660. switch (dat->m_iDataType)
  661. {
  662. case TYPE_STRING:
  663. {
  664. if (dat->m_sValue && *(dat->m_sValue))
  665. {
  666. WriteIndents(filesystem, f, pBuf, indentLevel + 1);
  667. INTERNALWRITE("\"", 1);
  668. WriteConvertedString(filesystem, f, pBuf, dat->GetName());
  669. INTERNALWRITE("\"\t\t\"", 4);
  670. WriteConvertedString(filesystem, f, pBuf, dat->m_sValue);
  671. INTERNALWRITE("\"\n", 2);
  672. }
  673. break;
  674. }
  675. case TYPE_WSTRING:
  676. {
  677. if ( dat->m_wsValue )
  678. {
  679. static char buf[KEYVALUES_TOKEN_SIZE];
  680. // make sure we have enough space
  681. int result = V_UnicodeToUTF8( dat->m_wsValue, buf, KEYVALUES_TOKEN_SIZE);
  682. if (result)
  683. {
  684. WriteIndents(filesystem, f, pBuf, indentLevel + 1);
  685. INTERNALWRITE("\"", 1);
  686. INTERNALWRITE(dat->GetName(), V_strlen(dat->GetName()));
  687. INTERNALWRITE("\"\t\t\"", 4);
  688. WriteConvertedString(filesystem, f, pBuf, buf);
  689. INTERNALWRITE("\"\n", 2);
  690. }
  691. }
  692. break;
  693. }
  694. case TYPE_INT:
  695. {
  696. WriteIndents(filesystem, f, pBuf, indentLevel + 1);
  697. INTERNALWRITE("\"", 1);
  698. INTERNALWRITE(dat->GetName(), V_strlen(dat->GetName()));
  699. INTERNALWRITE("\"\t\t\"", 4);
  700. char buf[32];
  701. V_snprintf(buf, sizeof( buf ), "%d", dat->m_iValue);
  702. INTERNALWRITE(buf, V_strlen(buf));
  703. INTERNALWRITE("\"\n", 2);
  704. break;
  705. }
  706. case TYPE_UINT64:
  707. {
  708. WriteIndents(filesystem, f, pBuf, indentLevel + 1);
  709. INTERNALWRITE("\"", 1);
  710. INTERNALWRITE(dat->GetName(), V_strlen(dat->GetName()));
  711. INTERNALWRITE("\"\t\t\"", 4);
  712. char buf[32];
  713. // write "0x" + 16 char 0-padded hex encoded 64 bit value
  714. V_snprintf( buf, sizeof( buf ), "0x%016llX", *( (uint64 *)dat->m_sValue ) );
  715. INTERNALWRITE(buf, V_strlen(buf));
  716. INTERNALWRITE("\"\n", 2);
  717. break;
  718. }
  719. case TYPE_FLOAT:
  720. {
  721. WriteIndents(filesystem, f, pBuf, indentLevel + 1);
  722. INTERNALWRITE("\"", 1);
  723. INTERNALWRITE(dat->GetName(), V_strlen(dat->GetName()));
  724. INTERNALWRITE("\"\t\t\"", 4);
  725. char buf[48];
  726. V_snprintf(buf, sizeof( buf ), "%f", dat->m_flValue);
  727. INTERNALWRITE(buf, V_strlen(buf));
  728. INTERNALWRITE("\"\n", 2);
  729. break;
  730. }
  731. case TYPE_COLOR:
  732. DevMsg( "KeyValues::RecursiveSaveToFile: TODO, missing code for TYPE_COLOR.\n" );
  733. break;
  734. default:
  735. break;
  736. }
  737. }
  738. }
  739. // write tail
  740. WriteIndents(filesystem, f, pBuf, indentLevel);
  741. INTERNALWRITE("}\n", 2);
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose: looks up a key by symbol name
  745. //-----------------------------------------------------------------------------
  746. KeyValues *KeyValues::FindKey(int keySymbol) const
  747. {
  748. for (KeyValues *dat = this ? m_pSub : NULL; dat != NULL; dat = dat->m_pPeer)
  749. {
  750. if ( dat->m_iKeyName == (uint32) keySymbol )
  751. return dat;
  752. }
  753. return NULL;
  754. }
  755. //-----------------------------------------------------------------------------
  756. // Purpose: Find a keyValue, create it if it is not found.
  757. // Set bCreate to true to create the key if it doesn't already exist
  758. // (which ensures a valid pointer will be returned)
  759. //-----------------------------------------------------------------------------
  760. KeyValues *KeyValues::FindKey(const char *keyName, bool bCreate)
  761. {
  762. // Validate NULL == this early out
  763. if ( !this )
  764. {
  765. Assert( !bCreate );
  766. return NULL;
  767. }
  768. // return the current key if a NULL subkey is asked for
  769. if (!keyName || !keyName[0])
  770. return this;
  771. // look for '/' characters deliminating sub fields
  772. char szBuf[256];
  773. const char *subStr = strchr(keyName, '/');
  774. const char *searchStr = keyName;
  775. // pull out the substring if it exists
  776. if (subStr)
  777. {
  778. int size = subStr - keyName;
  779. V_memcpy( szBuf, keyName, size );
  780. szBuf[size] = 0;
  781. searchStr = szBuf;
  782. }
  783. // lookup the symbol for the search string,
  784. // we do not need the case-sensitive symbol at this time
  785. // because if the key is found, then it will be found by case-insensitive lookup
  786. // if the key is not found and needs to be created we will pass the actual searchStr
  787. // and have the new KeyValues constructor get/create the case-sensitive symbol
  788. HKeySymbol iSearchStr = KeyValuesSystem()->GetSymbolForString( searchStr, bCreate );
  789. if ( iSearchStr == INVALID_KEY_SYMBOL )
  790. {
  791. // not found, couldn't possibly be in key value list
  792. return NULL;
  793. }
  794. KeyValues *lastItem = NULL;
  795. KeyValues *dat;
  796. // find the searchStr in the current peer list
  797. for (dat = m_pSub; dat != NULL; dat = dat->m_pPeer)
  798. {
  799. lastItem = dat; // record the last item looked at (for if we need to append to the end of the list)
  800. // symbol compare
  801. if ( dat->m_iKeyName == ( uint32 ) iSearchStr )
  802. {
  803. break;
  804. }
  805. }
  806. if ( !dat && m_pChain )
  807. {
  808. dat = m_pChain->FindKey(keyName, false);
  809. }
  810. // make sure a key was found
  811. if (!dat)
  812. {
  813. if (bCreate)
  814. {
  815. // we need to create a new key
  816. dat = new KeyValues( searchStr );
  817. // Assert(dat != NULL);
  818. // insert new key at end of list
  819. if (lastItem)
  820. {
  821. lastItem->m_pPeer = dat;
  822. }
  823. else
  824. {
  825. m_pSub = dat;
  826. }
  827. dat->m_pPeer = NULL;
  828. // a key graduates to be a submsg as soon as it's m_pSub is set
  829. // this should be the only place m_pSub is set
  830. m_iDataType = TYPE_NONE;
  831. }
  832. else
  833. {
  834. return NULL;
  835. }
  836. }
  837. // if we've still got a subStr we need to keep looking deeper in the tree
  838. if ( subStr )
  839. {
  840. // recursively chain down through the paths in the string
  841. return dat->FindKey(subStr + 1, bCreate);
  842. }
  843. return dat;
  844. }
  845. //-----------------------------------------------------------------------------
  846. // Purpose: Create a new key, with an autogenerated name.
  847. // Name is guaranteed to be an integer, of value 1 higher than the highest
  848. // other integer key name
  849. //-----------------------------------------------------------------------------
  850. KeyValues *KeyValues::CreateNewKey()
  851. {
  852. int newID = 1;
  853. // search for any key with higher values
  854. for (KeyValues *dat = m_pSub; dat != NULL; dat = dat->m_pPeer)
  855. {
  856. // case-insensitive string compare
  857. int val = atoi(dat->GetName());
  858. if (newID <= val)
  859. {
  860. newID = val + 1;
  861. }
  862. }
  863. char buf[12];
  864. V_snprintf( buf, sizeof(buf), "%d", newID );
  865. return CreateKey( buf );
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Create a key
  869. //-----------------------------------------------------------------------------
  870. KeyValues* KeyValues::CreateKey( const char *keyName )
  871. {
  872. // key wasn't found so just create a new one
  873. KeyValues* dat = new KeyValues( keyName );
  874. dat->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // use same format as parent does
  875. // add into subkey list
  876. AddSubKey( dat );
  877. return dat;
  878. }
  879. //-----------------------------------------------------------------------------
  880. // Adds a subkey. Make sure the subkey isn't a child of some other keyvalues
  881. //-----------------------------------------------------------------------------
  882. void KeyValues::AddSubKey( KeyValues *pSubkey )
  883. {
  884. // Make sure the subkey isn't a child of some other keyvalues
  885. Assert( pSubkey->m_pPeer == NULL );
  886. // add into subkey list
  887. if ( m_pSub == NULL )
  888. {
  889. m_pSub = pSubkey;
  890. }
  891. else
  892. {
  893. KeyValues *pTempDat = m_pSub;
  894. while ( pTempDat->GetNextKey() != NULL )
  895. {
  896. pTempDat = pTempDat->GetNextKey();
  897. }
  898. pTempDat->SetNextKey( pSubkey );
  899. }
  900. }
  901. //-----------------------------------------------------------------------------
  902. // Purpose: Remove a subkey from the list
  903. //-----------------------------------------------------------------------------
  904. void KeyValues::RemoveSubKey(KeyValues *subKey)
  905. {
  906. if (!subKey)
  907. return;
  908. // check the list pointer
  909. if (m_pSub == subKey)
  910. {
  911. m_pSub = subKey->m_pPeer;
  912. }
  913. else
  914. {
  915. // look through the list
  916. KeyValues *kv = m_pSub;
  917. while (kv->m_pPeer)
  918. {
  919. if (kv->m_pPeer == subKey)
  920. {
  921. kv->m_pPeer = subKey->m_pPeer;
  922. break;
  923. }
  924. kv = kv->m_pPeer;
  925. }
  926. }
  927. subKey->m_pPeer = NULL;
  928. }
  929. void KeyValues::InsertSubKey( int nIndex, KeyValues *pSubKey )
  930. {
  931. // Sub key must be valid and not part of another chain
  932. Assert( pSubKey && pSubKey->m_pPeer == NULL );
  933. if ( nIndex == 0 )
  934. {
  935. pSubKey->m_pPeer = m_pSub;
  936. m_pSub = pSubKey;
  937. return;
  938. }
  939. else
  940. {
  941. int nCurrentIndex = 0;
  942. for ( KeyValues *pIter = GetFirstSubKey(); pIter != NULL; pIter = pIter->GetNextKey() )
  943. {
  944. ++ nCurrentIndex;
  945. if ( nCurrentIndex == nIndex)
  946. {
  947. pSubKey->m_pPeer = pIter->m_pPeer;
  948. pIter->m_pPeer = pSubKey;
  949. return;
  950. }
  951. }
  952. // Index is out of range if we get here
  953. Assert( 0 );
  954. return;
  955. }
  956. }
  957. bool KeyValues::ContainsSubKey( KeyValues *pSubKey )
  958. {
  959. for ( KeyValues *pIter = GetFirstSubKey(); pIter != NULL; pIter = pIter->GetNextKey() )
  960. {
  961. if ( pSubKey == pIter )
  962. {
  963. return true;
  964. }
  965. }
  966. return false;
  967. }
  968. void KeyValues::SwapSubKey( KeyValues *pExistingSubkey, KeyValues *pNewSubKey )
  969. {
  970. Assert( pExistingSubkey != NULL && pNewSubKey != NULL );
  971. // Make sure the new sub key isn't a child of some other keyvalues
  972. Assert( pNewSubKey->m_pPeer == NULL );
  973. // Check the list pointer
  974. if ( m_pSub == pExistingSubkey )
  975. {
  976. pNewSubKey->m_pPeer = pExistingSubkey->m_pPeer;
  977. pExistingSubkey->m_pPeer = NULL;
  978. m_pSub = pNewSubKey;
  979. }
  980. else
  981. {
  982. // Look through the list
  983. KeyValues *kv = m_pSub;
  984. while ( kv->m_pPeer )
  985. {
  986. if ( kv->m_pPeer == pExistingSubkey )
  987. {
  988. pNewSubKey->m_pPeer = pExistingSubkey->m_pPeer;
  989. pExistingSubkey->m_pPeer = NULL;
  990. kv->m_pPeer = pNewSubKey;
  991. break;
  992. }
  993. kv = kv->m_pPeer;
  994. }
  995. // Existing sub key should always be found, otherwise it's a bug in the calling code.
  996. Assert( kv->m_pPeer != NULL );
  997. }
  998. }
  999. void KeyValues::ElideSubKey( KeyValues *pSubKey )
  1000. {
  1001. // This pointer's "next" pointer needs to be fixed up when we elide the key
  1002. KeyValues **ppPointerToFix = &m_pSub;
  1003. for ( KeyValues *pKeyIter = m_pSub; pKeyIter != NULL; ppPointerToFix = &pKeyIter->m_pPeer, pKeyIter = pKeyIter->GetNextKey() )
  1004. {
  1005. if ( pKeyIter == pSubKey )
  1006. {
  1007. if ( pSubKey->m_pSub == NULL )
  1008. {
  1009. // No children, simply remove the key
  1010. *ppPointerToFix = pSubKey->m_pPeer;
  1011. pSubKey->deleteThis();
  1012. }
  1013. else
  1014. {
  1015. *ppPointerToFix = pSubKey->m_pSub;
  1016. // Attach the remainder of this chain to the last child of pSubKey
  1017. KeyValues *pChildIter = pSubKey->m_pSub;
  1018. while ( pChildIter->m_pPeer != NULL )
  1019. {
  1020. pChildIter = pChildIter->m_pPeer;
  1021. }
  1022. // Now points to the last child of pSubKey
  1023. pChildIter->m_pPeer = pSubKey->m_pPeer;
  1024. // Detach the node to be elided
  1025. pSubKey->m_pSub = NULL;
  1026. pSubKey->m_pPeer = NULL;
  1027. pSubKey->deleteThis();
  1028. }
  1029. return;
  1030. }
  1031. }
  1032. // Key not found; that's caller error.
  1033. Assert( 0 );
  1034. }
  1035. //-----------------------------------------------------------------------------
  1036. // Purpose: Return the first subkey in the list
  1037. //-----------------------------------------------------------------------------
  1038. KeyValues *KeyValues::GetFirstSubKey()
  1039. {
  1040. return this ? m_pSub : NULL;
  1041. }
  1042. //-----------------------------------------------------------------------------
  1043. // Purpose: Return the next subkey
  1044. //-----------------------------------------------------------------------------
  1045. KeyValues *KeyValues::GetNextKey()
  1046. {
  1047. return this ? m_pPeer : NULL;
  1048. }
  1049. //-----------------------------------------------------------------------------
  1050. // Purpose: Sets this key's peer to the KeyValues passed in
  1051. //-----------------------------------------------------------------------------
  1052. void KeyValues::SetNextKey( KeyValues *pDat )
  1053. {
  1054. m_pPeer = pDat;
  1055. }
  1056. KeyValues* KeyValues::GetFirstTrueSubKey()
  1057. {
  1058. KeyValues *pRet = this ? m_pSub : NULL;
  1059. while ( pRet && pRet->m_iDataType != TYPE_NONE )
  1060. pRet = pRet->m_pPeer;
  1061. return pRet;
  1062. }
  1063. KeyValues* KeyValues::GetNextTrueSubKey()
  1064. {
  1065. KeyValues *pRet = this ? m_pPeer : NULL;
  1066. while ( pRet && pRet->m_iDataType != TYPE_NONE )
  1067. pRet = pRet->m_pPeer;
  1068. return pRet;
  1069. }
  1070. KeyValues* KeyValues::GetFirstValue()
  1071. {
  1072. KeyValues *pRet = this ? m_pSub : NULL;
  1073. while ( pRet && pRet->m_iDataType == TYPE_NONE )
  1074. pRet = pRet->m_pPeer;
  1075. return pRet;
  1076. }
  1077. KeyValues* KeyValues::GetNextValue()
  1078. {
  1079. KeyValues *pRet = this ? m_pPeer : NULL;
  1080. while ( pRet && pRet->m_iDataType == TYPE_NONE )
  1081. pRet = pRet->m_pPeer;
  1082. return pRet;
  1083. }
  1084. //-----------------------------------------------------------------------------
  1085. // Purpose: Get the integer value of a keyName. Default value is returned
  1086. // if the keyName can't be found.
  1087. //-----------------------------------------------------------------------------
  1088. int KeyValues::GetInt( const char *keyName, int defaultValue )
  1089. {
  1090. KeyValues *dat = FindKey( keyName, false );
  1091. if ( dat )
  1092. {
  1093. switch ( dat->m_iDataType )
  1094. {
  1095. case TYPE_STRING:
  1096. return atoi(dat->m_sValue);
  1097. case TYPE_WSTRING:
  1098. return _wtoi(dat->m_wsValue);
  1099. case TYPE_FLOAT:
  1100. return (int)dat->m_flValue;
  1101. case TYPE_UINT64:
  1102. // can't convert, since it would lose data
  1103. Assert(0);
  1104. return 0;
  1105. case TYPE_INT:
  1106. case TYPE_PTR:
  1107. default:
  1108. return dat->m_iValue;
  1109. };
  1110. }
  1111. return defaultValue;
  1112. }
  1113. //-----------------------------------------------------------------------------
  1114. // Purpose: Get the integer value of a keyName. Default value is returned
  1115. // if the keyName can't be found.
  1116. //-----------------------------------------------------------------------------
  1117. uint64 KeyValues::GetUint64( const char *keyName, uint64 defaultValue )
  1118. {
  1119. KeyValues *dat = FindKey( keyName, false );
  1120. if ( dat )
  1121. {
  1122. switch ( dat->m_iDataType )
  1123. {
  1124. case TYPE_STRING:
  1125. {
  1126. uint64 uiResult = 0ull;
  1127. sscanf( dat->m_sValue, "%lld", &uiResult );
  1128. return uiResult;
  1129. }
  1130. case TYPE_WSTRING:
  1131. {
  1132. uint64 uiResult = 0ull;
  1133. swscanf( dat->m_wsValue, L"%lld", &uiResult );
  1134. return uiResult;
  1135. }
  1136. case TYPE_FLOAT:
  1137. return (int)dat->m_flValue;
  1138. case TYPE_UINT64:
  1139. return *((uint64 *)dat->m_sValue);
  1140. case TYPE_INT:
  1141. case TYPE_PTR:
  1142. default:
  1143. return dat->m_iValue;
  1144. };
  1145. }
  1146. return defaultValue;
  1147. }
  1148. //-----------------------------------------------------------------------------
  1149. // Purpose: Get the pointer value of a keyName. Default value is returned
  1150. // if the keyName can't be found.
  1151. //-----------------------------------------------------------------------------
  1152. void *KeyValues::GetPtr( const char *keyName, void *defaultValue )
  1153. {
  1154. KeyValues *dat = FindKey( keyName, false );
  1155. if ( dat )
  1156. {
  1157. switch ( dat->m_iDataType )
  1158. {
  1159. case TYPE_PTR:
  1160. return dat->m_pValue;
  1161. case TYPE_WSTRING:
  1162. case TYPE_STRING:
  1163. case TYPE_FLOAT:
  1164. case TYPE_INT:
  1165. case TYPE_UINT64:
  1166. default:
  1167. return NULL;
  1168. };
  1169. }
  1170. return defaultValue;
  1171. }
  1172. //-----------------------------------------------------------------------------
  1173. // Purpose: Get the float value of a keyName. Default value is returned
  1174. // if the keyName can't be found.
  1175. //-----------------------------------------------------------------------------
  1176. float KeyValues::GetFloat( const char *keyName, float defaultValue )
  1177. {
  1178. KeyValues *dat = FindKey( keyName, false );
  1179. if ( dat )
  1180. {
  1181. switch ( dat->m_iDataType )
  1182. {
  1183. case TYPE_STRING:
  1184. return (float)atof(dat->m_sValue);
  1185. case TYPE_WSTRING:
  1186. #ifdef WIN32
  1187. return (float) _wtof(dat->m_wsValue); // no wtof
  1188. #else
  1189. return (float) wcstof( dat->m_wsValue, (wchar_t **)NULL );
  1190. #endif
  1191. case TYPE_FLOAT:
  1192. return dat->m_flValue;
  1193. case TYPE_INT:
  1194. return (float)dat->m_iValue;
  1195. case TYPE_UINT64:
  1196. return (float)(*((uint64 *)dat->m_sValue));
  1197. case TYPE_PTR:
  1198. default:
  1199. return 0.0f;
  1200. };
  1201. }
  1202. return defaultValue;
  1203. }
  1204. //-----------------------------------------------------------------------------
  1205. // Purpose: Get the string pointer of a keyName. Default value is returned
  1206. // if the keyName can't be found.
  1207. //-----------------------------------------------------------------------------
  1208. const char *KeyValues::GetString( const char *keyName, const char *defaultValue )
  1209. {
  1210. KeyValues *dat = FindKey( keyName, false );
  1211. if ( dat )
  1212. {
  1213. // convert the data to string form then return it
  1214. char buf[64];
  1215. switch ( dat->m_iDataType )
  1216. {
  1217. case TYPE_FLOAT:
  1218. V_snprintf( buf, sizeof( buf ), "%f", dat->m_flValue );
  1219. SetString( keyName, buf );
  1220. break;
  1221. case TYPE_INT:
  1222. case TYPE_PTR:
  1223. V_snprintf( buf, sizeof( buf ), "%d", dat->m_iValue );
  1224. SetString( keyName, buf );
  1225. break;
  1226. case TYPE_UINT64:
  1227. V_snprintf( buf, sizeof( buf ), "%lld", *((uint64 *)(dat->m_sValue)) );
  1228. SetString( keyName, buf );
  1229. break;
  1230. case TYPE_WSTRING:
  1231. {
  1232. // convert the string to char *, set it for future use, and return it
  1233. char wideBuf[512];
  1234. int result = V_UnicodeToUTF8(dat->m_wsValue, wideBuf, 512);
  1235. if ( result )
  1236. {
  1237. // note: this will copy wideBuf
  1238. SetString( keyName, wideBuf );
  1239. }
  1240. else
  1241. {
  1242. return defaultValue;
  1243. }
  1244. break;
  1245. }
  1246. case TYPE_STRING:
  1247. break;
  1248. default:
  1249. return defaultValue;
  1250. };
  1251. return dat->m_sValue;
  1252. }
  1253. return defaultValue;
  1254. }
  1255. const wchar_t *KeyValues::GetWString( const char *keyName, const wchar_t *defaultValue)
  1256. {
  1257. KeyValues *dat = FindKey( keyName, false );
  1258. if ( dat )
  1259. {
  1260. wchar_t wbuf[64];
  1261. switch ( dat->m_iDataType )
  1262. {
  1263. case TYPE_FLOAT:
  1264. swprintf(wbuf, V_ARRAYSIZE(wbuf), L"%f", dat->m_flValue);
  1265. SetWString( keyName, wbuf);
  1266. break;
  1267. case TYPE_INT:
  1268. case TYPE_PTR:
  1269. swprintf( wbuf, V_ARRAYSIZE(wbuf), L"%d", dat->m_iValue );
  1270. SetWString( keyName, wbuf );
  1271. break;
  1272. case TYPE_UINT64:
  1273. {
  1274. swprintf( wbuf, V_ARRAYSIZE(wbuf), L"%lld", *((uint64 *)(dat->m_sValue)) );
  1275. SetWString( keyName, wbuf );
  1276. }
  1277. break;
  1278. case TYPE_WSTRING:
  1279. break;
  1280. case TYPE_STRING:
  1281. {
  1282. int bufSize = V_strlen(dat->m_sValue) + 1;
  1283. wchar_t *pWBuf = new wchar_t[ bufSize ];
  1284. int result = V_UTF8ToUnicode(dat->m_sValue, pWBuf, bufSize * sizeof( wchar_t ) );
  1285. if ( result >= 0 ) // may be a zero length string
  1286. {
  1287. SetWString( keyName, pWBuf);
  1288. }
  1289. else
  1290. {
  1291. delete [] pWBuf;
  1292. return defaultValue;
  1293. }
  1294. delete [] pWBuf;
  1295. break;
  1296. }
  1297. default:
  1298. return defaultValue;
  1299. };
  1300. return (const wchar_t* )dat->m_wsValue;
  1301. }
  1302. return defaultValue;
  1303. }
  1304. //-----------------------------------------------------------------------------
  1305. // Purpose: Gets a color
  1306. //-----------------------------------------------------------------------------
  1307. Color KeyValues::GetColor( const char *keyName , const Color& defaultColor )
  1308. {
  1309. Color color = defaultColor;
  1310. KeyValues *dat = FindKey( keyName , false );
  1311. if ( dat )
  1312. {
  1313. if ( dat->m_iDataType == TYPE_COLOR )
  1314. {
  1315. color[0] = dat->m_Color[0];
  1316. color[1] = dat->m_Color[1];
  1317. color[2] = dat->m_Color[2];
  1318. color[3] = dat->m_Color[3];
  1319. }
  1320. else if ( dat->m_iDataType == TYPE_FLOAT )
  1321. {
  1322. color[0] = (unsigned char)dat->m_flValue;
  1323. }
  1324. else if ( dat->m_iDataType == TYPE_INT )
  1325. {
  1326. color[0] = (unsigned char)dat->m_iValue;
  1327. }
  1328. else if ( dat->m_iDataType == TYPE_STRING )
  1329. {
  1330. // parse the colors out of the string
  1331. float a, b, c, d;
  1332. sscanf(dat->m_sValue, "%f %f %f %f", &a, &b, &c, &d);
  1333. color[0] = (unsigned char)a;
  1334. color[1] = (unsigned char)b;
  1335. color[2] = (unsigned char)c;
  1336. color[3] = (unsigned char)d;
  1337. }
  1338. }
  1339. return color;
  1340. }
  1341. //-----------------------------------------------------------------------------
  1342. // Purpose: Sets a color
  1343. //-----------------------------------------------------------------------------
  1344. void KeyValues::SetColor( const char *keyName, Color value)
  1345. {
  1346. KeyValues *dat = FindKey( keyName, true );
  1347. if ( dat )
  1348. {
  1349. dat->m_iDataType = TYPE_COLOR;
  1350. dat->m_Color[0] = value[0];
  1351. dat->m_Color[1] = value[1];
  1352. dat->m_Color[2] = value[2];
  1353. dat->m_Color[3] = value[3];
  1354. }
  1355. }
  1356. void KeyValues::SetStringValue( char const *strValue )
  1357. {
  1358. // delete the old value
  1359. delete [] m_sValue;
  1360. // make sure we're not storing the WSTRING - as we're converting over to STRING
  1361. delete [] m_wsValue;
  1362. m_wsValue = NULL;
  1363. if (!strValue)
  1364. {
  1365. // ensure a valid value
  1366. strValue = "";
  1367. }
  1368. // allocate memory for the new value and copy it in
  1369. int len = V_strlen( strValue );
  1370. m_sValue = new char[len + 1];
  1371. V_memcpy( m_sValue, strValue, len+1 );
  1372. m_iDataType = TYPE_STRING;
  1373. }
  1374. //-----------------------------------------------------------------------------
  1375. // Purpose: Set the string value of a keyName.
  1376. //-----------------------------------------------------------------------------
  1377. void KeyValues::SetString( const char *keyName, const char *value )
  1378. {
  1379. if ( KeyValues *dat = FindKey( keyName, true ) )
  1380. {
  1381. dat->SetStringValue( value );
  1382. }
  1383. }
  1384. //-----------------------------------------------------------------------------
  1385. // Purpose: Set the string value of a keyName.
  1386. //-----------------------------------------------------------------------------
  1387. void KeyValues::SetWString( const char *keyName, const wchar_t *value )
  1388. {
  1389. KeyValues *dat = FindKey( keyName, true );
  1390. if ( dat )
  1391. {
  1392. // delete the old value
  1393. delete [] dat->m_wsValue;
  1394. // make sure we're not storing the STRING - as we're converting over to WSTRING
  1395. delete [] dat->m_sValue;
  1396. dat->m_sValue = NULL;
  1397. if (!value)
  1398. {
  1399. // ensure a valid value
  1400. value = L"";
  1401. }
  1402. // allocate memory for the new value and copy it in
  1403. int len = wcslen( value );
  1404. dat->m_wsValue = new wchar_t[len + 1];
  1405. V_memcpy( dat->m_wsValue, value, (len+1) * sizeof(wchar_t) );
  1406. dat->m_iDataType = TYPE_WSTRING;
  1407. }
  1408. }
  1409. //-----------------------------------------------------------------------------
  1410. // Purpose: Set the integer value of a keyName.
  1411. //-----------------------------------------------------------------------------
  1412. void KeyValues::SetInt( const char *keyName, int value )
  1413. {
  1414. KeyValues *dat = FindKey( keyName, true );
  1415. if ( dat )
  1416. {
  1417. dat->m_iValue = value;
  1418. dat->m_iDataType = TYPE_INT;
  1419. }
  1420. }
  1421. //-----------------------------------------------------------------------------
  1422. // Purpose: Set the integer value of a keyName.
  1423. //-----------------------------------------------------------------------------
  1424. void KeyValues::SetUint64( const char *keyName, uint64 value )
  1425. {
  1426. KeyValues *dat = FindKey( keyName, true );
  1427. if ( dat )
  1428. {
  1429. // delete the old value
  1430. delete [] dat->m_sValue;
  1431. // make sure we're not storing the WSTRING - as we're converting over to STRING
  1432. delete [] dat->m_wsValue;
  1433. dat->m_wsValue = NULL;
  1434. dat->m_sValue = new char[sizeof(uint64)];
  1435. *((uint64 *)dat->m_sValue) = value;
  1436. dat->m_iDataType = TYPE_UINT64;
  1437. }
  1438. }
  1439. //-----------------------------------------------------------------------------
  1440. // Purpose: Set the float value of a keyName.
  1441. //-----------------------------------------------------------------------------
  1442. void KeyValues::SetFloat( const char *keyName, float value )
  1443. {
  1444. KeyValues *dat = FindKey( keyName, true );
  1445. if ( dat )
  1446. {
  1447. dat->m_flValue = value;
  1448. dat->m_iDataType = TYPE_FLOAT;
  1449. }
  1450. }
  1451. void KeyValues::SetName( const char * setName )
  1452. {
  1453. HKeySymbol hCaseSensitiveKeyName = INVALID_KEY_SYMBOL, hCaseInsensitiveKeyName = INVALID_KEY_SYMBOL;
  1454. hCaseSensitiveKeyName = KeyValuesSystem()->GetSymbolForStringCaseSensitive( hCaseInsensitiveKeyName, setName );
  1455. m_iKeyName = hCaseInsensitiveKeyName;
  1456. SPLIT_3_BYTES_INTO_1_AND_2( m_iKeyNameCaseSensitive1, m_iKeyNameCaseSensitive2, hCaseSensitiveKeyName );
  1457. }
  1458. //-----------------------------------------------------------------------------
  1459. // Purpose: Set the pointer value of a keyName.
  1460. //-----------------------------------------------------------------------------
  1461. void KeyValues::SetPtr( const char *keyName, void *value )
  1462. {
  1463. KeyValues *dat = FindKey( keyName, true );
  1464. if ( dat )
  1465. {
  1466. dat->m_pValue = value;
  1467. dat->m_iDataType = TYPE_PTR;
  1468. }
  1469. }
  1470. void KeyValues::RecursiveCopyKeyValues( KeyValues& src )
  1471. {
  1472. // garymcthack - need to check this code for possible buffer overruns.
  1473. m_iKeyName = src.m_iKeyName;
  1474. m_iKeyNameCaseSensitive1 = src.m_iKeyNameCaseSensitive1;
  1475. m_iKeyNameCaseSensitive2 = src.m_iKeyNameCaseSensitive2;
  1476. if( !src.m_pSub )
  1477. {
  1478. m_iDataType = src.m_iDataType;
  1479. char buf[256];
  1480. switch( src.m_iDataType )
  1481. {
  1482. case TYPE_NONE:
  1483. break;
  1484. case TYPE_STRING:
  1485. if( src.m_sValue )
  1486. {
  1487. int len = V_strlen(src.m_sValue) + 1;
  1488. m_sValue = new char[len];
  1489. V_strncpy( m_sValue, src.m_sValue, len );
  1490. }
  1491. break;
  1492. case TYPE_INT:
  1493. {
  1494. m_iValue = src.m_iValue;
  1495. V_snprintf( buf,sizeof(buf), "%d", m_iValue );
  1496. int len = V_strlen(buf) + 1;
  1497. m_sValue = new char[len];
  1498. V_strncpy( m_sValue, buf, len );
  1499. }
  1500. break;
  1501. case TYPE_FLOAT:
  1502. {
  1503. m_flValue = src.m_flValue;
  1504. V_snprintf( buf,sizeof(buf), "%f", m_flValue );
  1505. int len = V_strlen(buf) + 1;
  1506. m_sValue = new char[len];
  1507. V_strncpy( m_sValue, buf, len );
  1508. }
  1509. break;
  1510. case TYPE_PTR:
  1511. {
  1512. m_pValue = src.m_pValue;
  1513. }
  1514. break;
  1515. case TYPE_UINT64:
  1516. {
  1517. m_sValue = new char[sizeof(uint64)];
  1518. V_memcpy( m_sValue, src.m_sValue, sizeof(uint64) );
  1519. }
  1520. break;
  1521. case TYPE_COLOR:
  1522. {
  1523. m_Color[0] = src.m_Color[0];
  1524. m_Color[1] = src.m_Color[1];
  1525. m_Color[2] = src.m_Color[2];
  1526. m_Color[3] = src.m_Color[3];
  1527. }
  1528. break;
  1529. default:
  1530. {
  1531. // do nothing . .what the heck is this?
  1532. Assert( 0 );
  1533. }
  1534. break;
  1535. }
  1536. }
  1537. #if 0
  1538. KeyValues *pDst = this;
  1539. for ( KeyValues *pSrc = src.m_pSub; pSrc; pSrc = pSrc->m_pPeer )
  1540. {
  1541. if ( pSrc->m_pSub )
  1542. {
  1543. pDst->m_pSub = new KeyValues( pSrc->m_pSub->getName() );
  1544. pDst->m_pSub->RecursiveCopyKeyValues( *pSrc->m_pSub );
  1545. }
  1546. else
  1547. {
  1548. // copy non-empty keys
  1549. if ( pSrc->m_sValue && *(pSrc->m_sValue) )
  1550. {
  1551. pDst->m_pPeer = new KeyValues(
  1552. }
  1553. }
  1554. }
  1555. #endif
  1556. // Handle the immediate child
  1557. if( src.m_pSub )
  1558. {
  1559. m_pSub = new KeyValues( NULL );
  1560. m_pSub->RecursiveCopyKeyValues( *src.m_pSub );
  1561. }
  1562. // Handle the immediate peer
  1563. if( src.m_pPeer )
  1564. {
  1565. m_pPeer = new KeyValues( NULL );
  1566. m_pPeer->RecursiveCopyKeyValues( *src.m_pPeer );
  1567. }
  1568. }
  1569. KeyValues& KeyValues::operator=( KeyValues& src )
  1570. {
  1571. RemoveEverything();
  1572. Init(); // reset all values
  1573. RecursiveCopyKeyValues( src );
  1574. return *this;
  1575. }
  1576. //-----------------------------------------------------------------------------
  1577. // Make a new copy of all subkeys, add them all to the passed-in keyvalues
  1578. //-----------------------------------------------------------------------------
  1579. void KeyValues::CopySubkeys( KeyValues *pParent ) const
  1580. {
  1581. // recursively copy subkeys
  1582. // Also maintain ordering....
  1583. KeyValues *pPrev = NULL;
  1584. for ( KeyValues *sub = m_pSub; sub != NULL; sub = sub->m_pPeer )
  1585. {
  1586. // take a copy of the subkey
  1587. KeyValues *dat = sub->MakeCopy();
  1588. // add into subkey list
  1589. if (pPrev)
  1590. {
  1591. pPrev->m_pPeer = dat;
  1592. }
  1593. else
  1594. {
  1595. pParent->m_pSub = dat;
  1596. }
  1597. dat->m_pPeer = NULL;
  1598. pPrev = dat;
  1599. }
  1600. }
  1601. //-----------------------------------------------------------------------------
  1602. // Purpose: Makes a copy of the whole key-value pair set
  1603. //-----------------------------------------------------------------------------
  1604. KeyValues *KeyValues::MakeCopy( void ) const
  1605. {
  1606. KeyValues *newKeyValue = new KeyValues(GetName());
  1607. // copy data
  1608. newKeyValue->m_iDataType = m_iDataType;
  1609. switch ( m_iDataType )
  1610. {
  1611. case TYPE_STRING:
  1612. {
  1613. if ( m_sValue )
  1614. {
  1615. int len = V_strlen( m_sValue );
  1616. Assert( !newKeyValue->m_sValue );
  1617. newKeyValue->m_sValue = new char[len + 1];
  1618. V_memcpy( newKeyValue->m_sValue, m_sValue, len+1 );
  1619. }
  1620. }
  1621. break;
  1622. case TYPE_WSTRING:
  1623. {
  1624. if ( m_wsValue )
  1625. {
  1626. int len = wcslen( m_wsValue );
  1627. newKeyValue->m_wsValue = new wchar_t[len+1];
  1628. V_memcpy( newKeyValue->m_wsValue, m_wsValue, (len+1)*sizeof(wchar_t));
  1629. }
  1630. }
  1631. break;
  1632. case TYPE_INT:
  1633. newKeyValue->m_iValue = m_iValue;
  1634. break;
  1635. case TYPE_FLOAT:
  1636. newKeyValue->m_flValue = m_flValue;
  1637. break;
  1638. case TYPE_PTR:
  1639. newKeyValue->m_pValue = m_pValue;
  1640. break;
  1641. case TYPE_COLOR:
  1642. newKeyValue->m_Color[0] = m_Color[0];
  1643. newKeyValue->m_Color[1] = m_Color[1];
  1644. newKeyValue->m_Color[2] = m_Color[2];
  1645. newKeyValue->m_Color[3] = m_Color[3];
  1646. break;
  1647. case TYPE_UINT64:
  1648. newKeyValue->m_sValue = new char[sizeof(uint64)];
  1649. V_memcpy( newKeyValue->m_sValue, m_sValue, sizeof(uint64) );
  1650. break;
  1651. };
  1652. // recursively copy subkeys
  1653. CopySubkeys( newKeyValue );
  1654. return newKeyValue;
  1655. }
  1656. //-----------------------------------------------------------------------------
  1657. // Purpose: Check if a keyName has no value assigned to it.
  1658. //-----------------------------------------------------------------------------
  1659. bool KeyValues::IsEmpty(const char *keyName)
  1660. {
  1661. KeyValues *dat = FindKey(keyName, false);
  1662. if (!dat)
  1663. return true;
  1664. if (dat->m_iDataType == TYPE_NONE && dat->m_pSub == NULL)
  1665. return true;
  1666. return false;
  1667. }
  1668. //-----------------------------------------------------------------------------
  1669. // Purpose: Clear out all subkeys, and the current value
  1670. //-----------------------------------------------------------------------------
  1671. void KeyValues::Clear( void )
  1672. {
  1673. delete m_pSub;
  1674. m_pSub = NULL;
  1675. m_iDataType = TYPE_NONE;
  1676. }
  1677. //-----------------------------------------------------------------------------
  1678. // Purpose: Get the data type of the value stored in a keyName
  1679. //-----------------------------------------------------------------------------
  1680. KeyValues::types_t KeyValues::GetDataType(const char *keyName)
  1681. {
  1682. KeyValues *dat = FindKey(keyName, false);
  1683. if (dat)
  1684. return (types_t)dat->m_iDataType;
  1685. return TYPE_NONE;
  1686. }
  1687. //-----------------------------------------------------------------------------
  1688. // Purpose: Deletion, ensures object gets deleted from correct heap
  1689. //-----------------------------------------------------------------------------
  1690. void KeyValues::deleteThis()
  1691. {
  1692. delete this;
  1693. }
  1694. //-----------------------------------------------------------------------------
  1695. // Purpose:
  1696. // Input : includedKeys -
  1697. //-----------------------------------------------------------------------------
  1698. void KeyValues::AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys )
  1699. {
  1700. // Append any included keys, too...
  1701. int includeCount = includedKeys.Count();
  1702. int i;
  1703. for ( i = 0; i < includeCount; i++ )
  1704. {
  1705. KeyValues *kv = includedKeys[ i ];
  1706. Assert( kv );
  1707. KeyValues *insertSpot = this;
  1708. while ( insertSpot->GetNextKey() )
  1709. {
  1710. insertSpot = insertSpot->GetNextKey();
  1711. }
  1712. insertSpot->SetNextKey( kv );
  1713. }
  1714. }
  1715. void KeyValues::ParseIncludedKeys( char const *resourceName, const char *filetoinclude,
  1716. IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys, GetSymbolProc_t pfnEvaluateSymbolProc )
  1717. {
  1718. Assert( resourceName );
  1719. Assert( filetoinclude );
  1720. Assert( pFileSystem );
  1721. // Load it...
  1722. if ( !pFileSystem )
  1723. {
  1724. return;
  1725. }
  1726. // Get relative subdirectory
  1727. char fullpath[ 512 ];
  1728. V_strncpy( fullpath, resourceName, sizeof( fullpath ) );
  1729. // Strip off characters back to start or first /
  1730. bool done = false;
  1731. int len = V_strlen( fullpath );
  1732. while ( !done )
  1733. {
  1734. if ( len <= 0 )
  1735. {
  1736. break;
  1737. }
  1738. if ( fullpath[ len - 1 ] == '\\' ||
  1739. fullpath[ len - 1 ] == '/' )
  1740. {
  1741. break;
  1742. }
  1743. // zero it
  1744. fullpath[ len - 1 ] = 0;
  1745. --len;
  1746. }
  1747. // Append included file
  1748. V_strncat( fullpath, filetoinclude, sizeof( fullpath ), COPY_ALL_CHARACTERS );
  1749. KeyValues *newKV = new KeyValues( fullpath );
  1750. // CUtlSymbol save = s_CurrentFileSymbol; // did that had any use ???
  1751. newKV->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // use same format as parent
  1752. if ( newKV->LoadFromFile( pFileSystem, fullpath, pPathID, pfnEvaluateSymbolProc ) )
  1753. {
  1754. includedKeys.AddToTail( newKV );
  1755. }
  1756. else
  1757. {
  1758. DevMsg( "KeyValues::ParseIncludedKeys: Couldn't load included keyvalue file %s\n", fullpath );
  1759. newKV->deleteThis();
  1760. }
  1761. // s_CurrentFileSymbol = save;
  1762. }
  1763. //-----------------------------------------------------------------------------
  1764. // Purpose:
  1765. // Input : baseKeys -
  1766. //-----------------------------------------------------------------------------
  1767. void KeyValues::MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys )
  1768. {
  1769. int includeCount = baseKeys.Count();
  1770. int i;
  1771. for ( i = 0; i < includeCount; i++ )
  1772. {
  1773. KeyValues *kv = baseKeys[ i ];
  1774. Assert( kv );
  1775. RecursiveMergeKeyValues( kv );
  1776. }
  1777. }
  1778. //-----------------------------------------------------------------------------
  1779. // Purpose:
  1780. // Input : baseKV - keyvalues we're basing ourselves on
  1781. //-----------------------------------------------------------------------------
  1782. void KeyValues::RecursiveMergeKeyValues( KeyValues *baseKV )
  1783. {
  1784. // Merge ourselves
  1785. // we always want to keep our value, so nothing to do here
  1786. // Now merge our children
  1787. for ( KeyValues *baseChild = baseKV->m_pSub; baseChild != NULL; baseChild = baseChild->m_pPeer )
  1788. {
  1789. // for each child in base, see if we have a matching kv
  1790. bool bFoundMatch = false;
  1791. // If we have a child by the same name, merge those keys
  1792. for ( KeyValues *newChild = m_pSub; newChild != NULL; newChild = newChild->m_pPeer )
  1793. {
  1794. if ( !V_strcmp( baseChild->GetName(), newChild->GetName() ) )
  1795. {
  1796. newChild->RecursiveMergeKeyValues( baseChild );
  1797. bFoundMatch = true;
  1798. break;
  1799. }
  1800. }
  1801. // If not merged, append this key
  1802. if ( !bFoundMatch )
  1803. {
  1804. KeyValues *dat = baseChild->MakeCopy();
  1805. Assert( dat );
  1806. AddSubKey( dat );
  1807. }
  1808. }
  1809. }
  1810. //-----------------------------------------------------------------------------
  1811. // Returns whether a keyvalues conditional expression string evaluates to true or false
  1812. //-----------------------------------------------------------------------------
  1813. bool KeyValues::EvaluateConditional( const char *pExpressionString, GetSymbolProc_t pfnEvaluateSymbolProc )
  1814. {
  1815. // evaluate the infix expression, calling the symbol proc to resolve each symbol's value
  1816. bool bResult = false;
  1817. bool bValid = g_ExpressionEvaluator.Evaluate( bResult, pExpressionString, pfnEvaluateSymbolProc );
  1818. if ( !bValid )
  1819. {
  1820. g_KeyValuesErrorStack.ReportError( "KV Conditional Evaluation Error" );
  1821. }
  1822. return bResult;
  1823. }
  1824. // prevent two threads from entering this at the same time and trying to share the global error reporting and parse buffers
  1825. static CThreadFastMutex g_KVMutex;
  1826. //-----------------------------------------------------------------------------
  1827. // Read from a buffer...
  1828. //-----------------------------------------------------------------------------
  1829. bool KeyValues::LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem, const char *pPathID, GetSymbolProc_t pfnEvaluateSymbolProc )
  1830. {
  1831. AUTO_LOCK_FM( g_KVMutex );
  1832. if ( IsGameConsole() )
  1833. {
  1834. // Let's not crash if the buffer is empty
  1835. unsigned char *pData = buf.Size() > 0 ? (unsigned char *)buf.PeekGet() : NULL;
  1836. if ( pData && (unsigned int)pData[0] == KV_BINARY_POOLED_FORMAT )
  1837. {
  1838. // skip past binary marker
  1839. buf.GetUnsignedChar();
  1840. // get the pool identifier, allows the fs to bind the expected string pool
  1841. unsigned int poolKey = buf.GetUnsignedInt();
  1842. RemoveEverything();
  1843. Init();
  1844. return ReadAsBinaryPooledFormat( buf, pFileSystem, poolKey, pfnEvaluateSymbolProc );
  1845. }
  1846. }
  1847. KeyValues *pPreviousKey = NULL;
  1848. KeyValues *pCurrentKey = this;
  1849. CUtlVector< KeyValues * > includedKeys;
  1850. CUtlVector< KeyValues * > baseKeys;
  1851. bool wasQuoted;
  1852. bool wasConditional;
  1853. g_KeyValuesErrorStack.SetFilename( resourceName );
  1854. do
  1855. {
  1856. bool bAccepted = true;
  1857. // the first thing must be a key
  1858. const char *s = ReadToken( buf, wasQuoted, wasConditional );
  1859. if ( !buf.IsValid() || !s )
  1860. break;
  1861. if ( !wasQuoted && *s == '\0' )
  1862. {
  1863. // non quoted empty strings stop parsing
  1864. // quoted empty strings are allowed to support unnnamed KV sections
  1865. break;
  1866. }
  1867. if ( !V_stricmp( s, "#include" ) ) // special include macro (not a key name)
  1868. {
  1869. s = ReadToken( buf, wasQuoted, wasConditional );
  1870. // Name of subfile to load is now in s
  1871. if ( !s || *s == 0 )
  1872. {
  1873. g_KeyValuesErrorStack.ReportError("#include is NULL " );
  1874. }
  1875. else
  1876. {
  1877. ParseIncludedKeys( resourceName, s, pFileSystem, pPathID, includedKeys, pfnEvaluateSymbolProc );
  1878. }
  1879. continue;
  1880. }
  1881. else if ( !V_stricmp( s, "#base" ) )
  1882. {
  1883. s = ReadToken( buf, wasQuoted, wasConditional );
  1884. // Name of subfile to load is now in s
  1885. if ( !s || *s == 0 )
  1886. {
  1887. g_KeyValuesErrorStack.ReportError("#base is NULL " );
  1888. }
  1889. else
  1890. {
  1891. ParseIncludedKeys( resourceName, s, pFileSystem, pPathID, baseKeys, pfnEvaluateSymbolProc );
  1892. }
  1893. continue;
  1894. }
  1895. if ( !pCurrentKey )
  1896. {
  1897. pCurrentKey = new KeyValues( s );
  1898. Assert( pCurrentKey );
  1899. pCurrentKey->UsesEscapeSequences( m_bHasEscapeSequences != 0 ); // same format has parent use
  1900. if ( pPreviousKey )
  1901. {
  1902. pPreviousKey->SetNextKey( pCurrentKey );
  1903. }
  1904. }
  1905. else
  1906. {
  1907. pCurrentKey->SetName( s );
  1908. }
  1909. // get the '{'
  1910. s = ReadToken( buf, wasQuoted, wasConditional );
  1911. if ( wasConditional )
  1912. {
  1913. bAccepted = EvaluateConditional( s, pfnEvaluateSymbolProc );
  1914. // Now get the '{'
  1915. s = ReadToken( buf, wasQuoted, wasConditional );
  1916. }
  1917. if ( s && *s == '{' && !wasQuoted )
  1918. {
  1919. // header is valid so load the file
  1920. pCurrentKey->RecursiveLoadFromBuffer( resourceName, buf, pfnEvaluateSymbolProc );
  1921. }
  1922. else
  1923. {
  1924. g_KeyValuesErrorStack.ReportError("LoadFromBuffer: missing {" );
  1925. }
  1926. if ( !bAccepted )
  1927. {
  1928. if ( pPreviousKey )
  1929. {
  1930. pPreviousKey->SetNextKey( NULL );
  1931. }
  1932. pCurrentKey->Clear();
  1933. }
  1934. else
  1935. {
  1936. pPreviousKey = pCurrentKey;
  1937. pCurrentKey = NULL;
  1938. }
  1939. } while ( buf.IsValid() );
  1940. AppendIncludedKeys( includedKeys );
  1941. {
  1942. // delete included keys!
  1943. int i;
  1944. for ( i = includedKeys.Count() - 1; i > 0; i-- )
  1945. {
  1946. KeyValues *kv = includedKeys[ i ];
  1947. kv->deleteThis();
  1948. }
  1949. }
  1950. MergeBaseKeys( baseKeys );
  1951. {
  1952. // delete base keys!
  1953. int i;
  1954. for ( i = baseKeys.Count() - 1; i >= 0; i-- )
  1955. {
  1956. KeyValues *kv = baseKeys[ i ];
  1957. kv->deleteThis();
  1958. }
  1959. }
  1960. g_KeyValuesErrorStack.SetFilename( "" );
  1961. return true;
  1962. }
  1963. //-----------------------------------------------------------------------------
  1964. // Read from a buffer...
  1965. //-----------------------------------------------------------------------------
  1966. bool KeyValues::LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem, const char *pPathID, GetSymbolProc_t pfnEvaluateSymbolProc )
  1967. {
  1968. if ( !pBuffer )
  1969. return true;
  1970. if ( IsGameConsole() && (unsigned int)((unsigned char *)pBuffer)[0] == KV_BINARY_POOLED_FORMAT )
  1971. {
  1972. // bad, got a binary compiled KV file through an unexpected text path
  1973. // not all paths support binary compiled kv, needs to get fixed
  1974. // need to have caller supply buffer length (strlen not valid), this interface change was never plumbed
  1975. Warning( "ERROR! Binary compiled KV '%s' in an unexpected handler\n", resourceName );
  1976. Assert( 0 );
  1977. return false;
  1978. }
  1979. int nLen = V_strlen( pBuffer );
  1980. CUtlBuffer buf( pBuffer, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER );
  1981. // Translate Unicode files into UTF-8 before proceeding
  1982. if ( nLen > 2 && (uint8)pBuffer[0] == 0xFF && (uint8)pBuffer[1] == 0xFE )
  1983. {
  1984. int nUTF8Len = V_UnicodeToUTF8( (wchar_t*)(pBuffer+2), NULL, 0 );
  1985. char *pUTF8Buf = new char[nUTF8Len];
  1986. V_UnicodeToUTF8( (wchar_t*)(pBuffer+2), pUTF8Buf, nUTF8Len );
  1987. buf.AssumeMemory( pUTF8Buf, nUTF8Len, nUTF8Len, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER );
  1988. }
  1989. return LoadFromBuffer( resourceName, buf, pFileSystem, pPathID, pfnEvaluateSymbolProc );
  1990. }
  1991. //-----------------------------------------------------------------------------
  1992. // Purpose:
  1993. //-----------------------------------------------------------------------------
  1994. void KeyValues::RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf, GetSymbolProc_t pfnEvaluateSymbolProc )
  1995. {
  1996. CKeyErrorContext errorReport( GetNameSymbolCaseSensitive() );
  1997. bool wasQuoted;
  1998. bool wasConditional;
  1999. // keep this out of the stack until a key is parsed
  2000. CKeyErrorContext errorKey( INVALID_KEY_SYMBOL );
  2001. while ( 1 )
  2002. {
  2003. bool bAccepted = true;
  2004. // get the key name
  2005. const char * name = ReadToken( buf, wasQuoted, wasConditional );
  2006. if ( !name ) // EOF stop reading
  2007. {
  2008. g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got EOF instead of keyname" );
  2009. break;
  2010. }
  2011. if ( !*name ) // empty token, maybe "" or EOF
  2012. {
  2013. g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got empty keyname" );
  2014. break;
  2015. }
  2016. if ( *name == '}' && !wasQuoted ) // top level closed, stop reading
  2017. break;
  2018. // Always create the key; note that this could potentially
  2019. // cause some duplication, but that's what we want sometimes
  2020. KeyValues *dat = CreateKey( name );
  2021. errorKey.Reset( dat->GetNameSymbolCaseSensitive() );
  2022. // get the value
  2023. const char * value = ReadToken( buf, wasQuoted, wasConditional );
  2024. if ( wasConditional && value )
  2025. {
  2026. bAccepted = EvaluateConditional( value, pfnEvaluateSymbolProc );
  2027. // get the real value
  2028. value = ReadToken( buf, wasQuoted, wasConditional );
  2029. }
  2030. if ( !value )
  2031. {
  2032. g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got NULL key" );
  2033. break;
  2034. }
  2035. if ( *value == '}' && !wasQuoted )
  2036. {
  2037. g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got } in key" );
  2038. break;
  2039. }
  2040. if ( *value == '{' && !wasQuoted )
  2041. {
  2042. // this isn't a key, it's a section
  2043. errorKey.Reset( INVALID_KEY_SYMBOL );
  2044. // sub value list
  2045. dat->RecursiveLoadFromBuffer( resourceName, buf, pfnEvaluateSymbolProc );
  2046. }
  2047. else
  2048. {
  2049. if ( wasConditional )
  2050. {
  2051. g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got conditional between key and value" );
  2052. break;
  2053. }
  2054. if (dat->m_sValue)
  2055. {
  2056. delete[] dat->m_sValue;
  2057. dat->m_sValue = NULL;
  2058. }
  2059. int len = V_strlen( value );
  2060. // Here, let's determine if we got a float or an int....
  2061. char* pIEnd; // pos where int scan ended
  2062. char* pFEnd; // pos where float scan ended
  2063. const char* pSEnd = value + len ; // pos where token ends
  2064. int ival = strtol( value, &pIEnd, 10 );
  2065. float fval = (float)strtod( value, &pFEnd );
  2066. bool bOverflow = ( ival == LONG_MAX || ival == LONG_MIN ) && errno == ERANGE;
  2067. #ifdef POSIX
  2068. // strtod supports hex representation in strings under posix but we DON'T
  2069. // want that support in keyvalues, so undo it here if needed
  2070. if ( len > 1 && tolower(value[1]) == 'x' )
  2071. {
  2072. fval = 0.0f;
  2073. pFEnd = (char *)value;
  2074. }
  2075. #endif
  2076. if ( *value == 0 )
  2077. {
  2078. dat->m_iDataType = TYPE_STRING;
  2079. }
  2080. else if ( ( 18 == len ) && ( value[0] == '0' ) && ( value[1] == 'x' ) )
  2081. {
  2082. // an 18-byte value prefixed with "0x" (followed by 16 hex digits) is an int64 value
  2083. int64 retVal = 0;
  2084. for( int i=2; i < 2 + 16; i++ )
  2085. {
  2086. char digit = value[i];
  2087. if ( digit >= 'a' )
  2088. digit -= 'a' - ( '9' + 1 );
  2089. else
  2090. if ( digit >= 'A' )
  2091. digit -= 'A' - ( '9' + 1 );
  2092. retVal = ( retVal * 16 ) + ( digit - '0' );
  2093. }
  2094. dat->m_sValue = new char[sizeof(uint64)];
  2095. *((uint64 *)dat->m_sValue) = retVal;
  2096. dat->m_iDataType = TYPE_UINT64;
  2097. }
  2098. else if ( (pFEnd > pIEnd) && (pFEnd == pSEnd) )
  2099. {
  2100. dat->m_flValue = fval;
  2101. dat->m_iDataType = TYPE_FLOAT;
  2102. }
  2103. else if (pIEnd == pSEnd && !bOverflow)
  2104. {
  2105. dat->m_iValue = ival;
  2106. dat->m_iDataType = TYPE_INT;
  2107. }
  2108. else
  2109. {
  2110. dat->m_iDataType = TYPE_STRING;
  2111. }
  2112. if (dat->m_iDataType == TYPE_STRING)
  2113. {
  2114. // copy in the string information
  2115. dat->m_sValue = new char[len+1];
  2116. V_memcpy( dat->m_sValue, value, len+1 );
  2117. }
  2118. // Look ahead one token for a conditional tag
  2119. int prevPos = buf.TellGet();
  2120. const char *peek = ReadToken( buf, wasQuoted, wasConditional );
  2121. if ( wasConditional )
  2122. {
  2123. bAccepted = EvaluateConditional( peek, pfnEvaluateSymbolProc );
  2124. }
  2125. else
  2126. {
  2127. buf.SeekGet( CUtlBuffer::SEEK_HEAD, prevPos );
  2128. }
  2129. }
  2130. if ( !bAccepted )
  2131. {
  2132. this->RemoveSubKey( dat );
  2133. dat->deleteThis();
  2134. dat = NULL;
  2135. }
  2136. }
  2137. }
  2138. // writes KeyValue as binary data to buffer
  2139. bool KeyValues::WriteAsBinary( CUtlBuffer &buffer ) const
  2140. {
  2141. if ( buffer.IsText() ) // must be a binary buffer
  2142. return false;
  2143. if ( !buffer.IsValid() ) // must be valid, no overflows etc
  2144. return false;
  2145. // Write subkeys:
  2146. // loop through all our peers
  2147. for ( const KeyValues *dat = this; dat != NULL; dat = dat->m_pPeer )
  2148. {
  2149. // write type
  2150. buffer.PutUnsignedChar( dat->m_iDataType );
  2151. // write name
  2152. buffer.PutString( dat->GetName() );
  2153. // write type
  2154. switch (dat->m_iDataType)
  2155. {
  2156. case TYPE_NONE:
  2157. {
  2158. dat->m_pSub->WriteAsBinary( buffer );
  2159. break;
  2160. }
  2161. case TYPE_STRING:
  2162. {
  2163. if (dat->m_sValue && *(dat->m_sValue))
  2164. {
  2165. buffer.PutString( dat->m_sValue );
  2166. }
  2167. else
  2168. {
  2169. buffer.PutString( "" );
  2170. }
  2171. break;
  2172. }
  2173. case TYPE_WSTRING:
  2174. {
  2175. int nLength = dat->m_wsValue ? V_wcslen( dat->m_wsValue ) : 0;
  2176. buffer.PutShort( nLength );
  2177. for( int k = 0; k < nLength; ++ k )
  2178. {
  2179. buffer.PutShort( ( unsigned short ) dat->m_wsValue[k] );
  2180. }
  2181. break;
  2182. }
  2183. case TYPE_INT:
  2184. {
  2185. buffer.PutInt( dat->m_iValue );
  2186. break;
  2187. }
  2188. case TYPE_UINT64:
  2189. {
  2190. buffer.PutInt64( *((int64 *)dat->m_sValue) );
  2191. break;
  2192. }
  2193. case TYPE_FLOAT:
  2194. {
  2195. buffer.PutFloat( dat->m_flValue );
  2196. break;
  2197. }
  2198. case TYPE_COLOR:
  2199. {
  2200. buffer.PutUnsignedChar( dat->m_Color[0] );
  2201. buffer.PutUnsignedChar( dat->m_Color[1] );
  2202. buffer.PutUnsignedChar( dat->m_Color[2] );
  2203. buffer.PutUnsignedChar( dat->m_Color[3] );
  2204. break;
  2205. }
  2206. case TYPE_PTR:
  2207. {
  2208. buffer.PutUnsignedInt( (int)dat->m_pValue );
  2209. break;
  2210. }
  2211. default:
  2212. break;
  2213. }
  2214. }
  2215. // write tail, marks end of peers
  2216. buffer.PutUnsignedChar( TYPE_NUMTYPES );
  2217. return buffer.IsValid();
  2218. }
  2219. // read KeyValues from binary buffer, returns true if parsing was successful
  2220. bool KeyValues::ReadAsBinary( CUtlBuffer &buffer )
  2221. {
  2222. if ( buffer.IsText() ) // must be a binary buffer
  2223. return false;
  2224. if ( !buffer.IsValid() ) // must be valid, no overflows etc
  2225. return false;
  2226. RemoveEverything(); // remove current content
  2227. Init(); // reset
  2228. char token[KEYVALUES_TOKEN_SIZE];
  2229. KeyValues *dat = this;
  2230. types_t type = (types_t)buffer.GetUnsignedChar();
  2231. // loop through all our peers
  2232. while ( true )
  2233. {
  2234. if ( type == TYPE_NUMTYPES )
  2235. break; // no more peers
  2236. dat->m_iDataType = type;
  2237. buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
  2238. token[KEYVALUES_TOKEN_SIZE-1] = 0;
  2239. dat->SetName( token );
  2240. switch ( type )
  2241. {
  2242. case TYPE_NONE:
  2243. {
  2244. dat->m_pSub = new KeyValues("");
  2245. dat->m_pSub->ReadAsBinary( buffer );
  2246. break;
  2247. }
  2248. case TYPE_STRING:
  2249. {
  2250. buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
  2251. token[KEYVALUES_TOKEN_SIZE-1] = 0;
  2252. int len = V_strlen( token );
  2253. dat->m_sValue = new char[len + 1];
  2254. V_memcpy( dat->m_sValue, token, len+1 );
  2255. break;
  2256. }
  2257. case TYPE_WSTRING:
  2258. {
  2259. int nLength = buffer.GetShort();
  2260. dat->m_wsValue = new wchar_t[nLength + 1];
  2261. for( int k = 0; k < nLength; ++ k )
  2262. {
  2263. dat->m_wsValue[k] = buffer.GetShort();
  2264. }
  2265. dat->m_wsValue[ nLength ] = 0;
  2266. break;
  2267. }
  2268. case TYPE_INT:
  2269. {
  2270. dat->m_iValue = buffer.GetInt();
  2271. break;
  2272. }
  2273. case TYPE_UINT64:
  2274. {
  2275. dat->m_sValue = new char[sizeof(uint64)];
  2276. *((uint64 *)dat->m_sValue) = buffer.GetInt64();
  2277. break;
  2278. }
  2279. case TYPE_FLOAT:
  2280. {
  2281. dat->m_flValue = buffer.GetFloat();
  2282. break;
  2283. }
  2284. case TYPE_COLOR:
  2285. {
  2286. dat->m_Color[0] = buffer.GetUnsignedChar();
  2287. dat->m_Color[1] = buffer.GetUnsignedChar();
  2288. dat->m_Color[2] = buffer.GetUnsignedChar();
  2289. dat->m_Color[3] = buffer.GetUnsignedChar();
  2290. break;
  2291. }
  2292. case TYPE_PTR:
  2293. {
  2294. dat->m_pValue = (void*)buffer.GetUnsignedInt();
  2295. break;
  2296. }
  2297. default:
  2298. break;
  2299. }
  2300. if ( !buffer.IsValid() ) // error occured
  2301. return false;
  2302. type = (types_t)buffer.GetUnsignedChar();
  2303. if ( type == TYPE_NUMTYPES )
  2304. break;
  2305. // new peer follows
  2306. dat->m_pPeer = new KeyValues("");
  2307. dat = dat->m_pPeer;
  2308. }
  2309. return buffer.IsValid();
  2310. }
  2311. //-----------------------------------------------------------------------------
  2312. // Alternate dense binary format that pools all the strings, the xbox supports
  2313. // this during creation of each mod dir's zip processing of kv files.
  2314. //-----------------------------------------------------------------------------
  2315. bool KeyValues::ReadAsBinaryPooledFormat( CUtlBuffer &buffer, IBaseFileSystem *pFileSystem, unsigned int poolKey, GetSymbolProc_t pfnEvaluateSymbolProc )
  2316. {
  2317. // xbox only support
  2318. if ( !IsGameConsole() )
  2319. {
  2320. Assert( 0 );
  2321. return false;
  2322. }
  2323. if ( buffer.IsText() ) // must be a binary buffer
  2324. return false;
  2325. if ( !buffer.IsValid() ) // must be valid, no overflows etc
  2326. return false;
  2327. char token[KEYVALUES_TOKEN_SIZE];
  2328. KeyValues *dat = this;
  2329. types_t type = (types_t)buffer.GetUnsignedChar();
  2330. // loop through all our peers
  2331. while ( true )
  2332. {
  2333. if ( type == TYPE_NUMTYPES )
  2334. break; // no more peers
  2335. dat->m_iDataType = type;
  2336. unsigned int stringKey = buffer.GetUnsignedInt();
  2337. if ( !((IFileSystem*)pFileSystem)->GetStringFromKVPool( poolKey, stringKey, token, sizeof( token ) ) )
  2338. return false;
  2339. dat->SetName( token );
  2340. switch ( type )
  2341. {
  2342. case TYPE_NONE:
  2343. {
  2344. dat->m_pSub = new KeyValues( "" );
  2345. if ( !dat->m_pSub->ReadAsBinaryPooledFormat( buffer, pFileSystem, poolKey, pfnEvaluateSymbolProc ) )
  2346. return false;
  2347. break;
  2348. }
  2349. case TYPE_STRING:
  2350. {
  2351. unsigned int stringKey = buffer.GetUnsignedInt();
  2352. if ( !((IFileSystem*)pFileSystem)->GetStringFromKVPool( poolKey, stringKey, token, sizeof( token ) ) )
  2353. return false;
  2354. int len = V_strlen( token );
  2355. dat->m_sValue = new char[len + 1];
  2356. V_memcpy( dat->m_sValue, token, len+1 );
  2357. break;
  2358. }
  2359. case TYPE_WSTRING:
  2360. {
  2361. int nLength = buffer.GetShort();
  2362. dat->m_wsValue = new wchar_t[nLength + 1];
  2363. for ( int k = 0; k < nLength; ++k )
  2364. {
  2365. dat->m_wsValue[k] = buffer.GetShort();
  2366. }
  2367. dat->m_wsValue[nLength] = 0;
  2368. break;
  2369. }
  2370. case TYPE_INT:
  2371. {
  2372. dat->m_iValue = buffer.GetInt();
  2373. break;
  2374. }
  2375. case TYPE_UINT64:
  2376. {
  2377. dat->m_sValue = new char[sizeof(uint64)];
  2378. *((uint64 *)dat->m_sValue) = buffer.GetInt64();
  2379. break;
  2380. }
  2381. case TYPE_FLOAT:
  2382. {
  2383. dat->m_flValue = buffer.GetFloat();
  2384. break;
  2385. }
  2386. case TYPE_COLOR:
  2387. {
  2388. dat->m_Color[0] = buffer.GetUnsignedChar();
  2389. dat->m_Color[1] = buffer.GetUnsignedChar();
  2390. dat->m_Color[2] = buffer.GetUnsignedChar();
  2391. dat->m_Color[3] = buffer.GetUnsignedChar();
  2392. break;
  2393. }
  2394. case TYPE_PTR:
  2395. {
  2396. dat->m_pValue = (void*)buffer.GetUnsignedInt();
  2397. break;
  2398. }
  2399. case TYPE_COMPILED_INT_0:
  2400. {
  2401. // only for dense storage purposes, flip back to preferred internal format
  2402. dat->m_iDataType = TYPE_INT;
  2403. dat->m_iValue = 0;
  2404. break;
  2405. }
  2406. case TYPE_COMPILED_INT_1:
  2407. {
  2408. // only for dense storage purposes, flip back to preferred internal format
  2409. dat->m_iDataType = TYPE_INT;
  2410. dat->m_iValue = 1;
  2411. break;
  2412. }
  2413. case TYPE_COMPILED_INT_BYTE:
  2414. {
  2415. // only for dense storage purposes, flip back to preferred internal format
  2416. dat->m_iDataType = TYPE_INT;
  2417. dat->m_iValue = buffer.GetChar();
  2418. break;
  2419. }
  2420. default:
  2421. break;
  2422. }
  2423. if ( !buffer.IsValid() ) // error occured
  2424. return false;
  2425. if ( !buffer.GetBytesRemaining() )
  2426. break;
  2427. type = (types_t)buffer.GetUnsignedChar();
  2428. if ( type == TYPE_NUMTYPES )
  2429. break;
  2430. // new peer follows
  2431. dat->m_pPeer = new KeyValues("");
  2432. dat = dat->m_pPeer;
  2433. }
  2434. return buffer.IsValid();
  2435. }
  2436. #include "tier0/memdbgoff.h"
  2437. //-----------------------------------------------------------------------------
  2438. // Purpose: memory allocator
  2439. //-----------------------------------------------------------------------------
  2440. void *KeyValues::operator new( size_t iAllocSize )
  2441. {
  2442. MEM_ALLOC_CREDIT();
  2443. return KeyValuesSystem()->AllocKeyValuesMemory(iAllocSize);
  2444. }
  2445. void *KeyValues::operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine )
  2446. {
  2447. MemAlloc_PushAllocDbgInfo( pFileName, nLine );
  2448. void *p = KeyValuesSystem()->AllocKeyValuesMemory(iAllocSize);
  2449. MemAlloc_PopAllocDbgInfo();
  2450. return p;
  2451. }
  2452. #include "tier0/memdbgon.h"
  2453. //-----------------------------------------------------------------------------
  2454. // Purpose: deallocator
  2455. //-----------------------------------------------------------------------------
  2456. void KeyValues::operator delete( void *pMem )
  2457. {
  2458. KeyValuesSystem()->FreeKeyValuesMemory(pMem);
  2459. }
  2460. void KeyValues::operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine )
  2461. {
  2462. KeyValuesSystem()->FreeKeyValuesMemory(pMem);
  2463. }
  2464. void KeyValues::UnpackIntoStructure( KeyValuesUnpackStructure const *pUnpackTable, void *pDest )
  2465. {
  2466. uint8 *dest = ( uint8 * ) pDest;
  2467. while( pUnpackTable->m_pKeyName )
  2468. {
  2469. uint8 * dest_field = dest + pUnpackTable->m_nFieldOffset;
  2470. KeyValues * find_it = FindKey( pUnpackTable->m_pKeyName );
  2471. switch( pUnpackTable->m_eDataType )
  2472. {
  2473. case UNPACK_TYPE_FLOAT:
  2474. {
  2475. float default_value = ( pUnpackTable->m_pKeyDefault ) ? atof( pUnpackTable->m_pKeyDefault ) : 0.0;
  2476. *( ( float * ) dest_field ) = GetFloat( pUnpackTable->m_pKeyName, default_value );
  2477. break;
  2478. }
  2479. break;
  2480. case UNPACK_TYPE_VECTOR:
  2481. {
  2482. Vector *dest_v = ( Vector * ) dest_field;
  2483. char const *src_string =
  2484. GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault );
  2485. if ( ( ! src_string ) ||
  2486. ( sscanf(src_string,"%f %f %f",
  2487. & ( dest_v->x ), & ( dest_v->y ), & ( dest_v->z )) != 3 ))
  2488. dest_v->Init( 0, 0, 0 );
  2489. }
  2490. break;
  2491. case UNPACK_TYPE_FOUR_FLOATS:
  2492. {
  2493. float *dest_f = ( float * ) dest_field;
  2494. char const *src_string =
  2495. GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault );
  2496. if ( ( ! src_string ) ||
  2497. ( sscanf(src_string,"%f %f %f %f",
  2498. dest_f, dest_f + 1, dest_f + 2, dest_f + 3 )) != 4 )
  2499. memset( dest_f, 0, 4 * sizeof( float ) );
  2500. }
  2501. break;
  2502. case UNPACK_TYPE_TWO_FLOATS:
  2503. {
  2504. float *dest_f = ( float * ) dest_field;
  2505. char const *src_string =
  2506. GetString( pUnpackTable->m_pKeyName, pUnpackTable->m_pKeyDefault );
  2507. if ( ( ! src_string ) ||
  2508. ( sscanf(src_string,"%f %f",
  2509. dest_f, dest_f + 1 )) != 2 )
  2510. memset( dest_f, 0, 2 * sizeof( float ) );
  2511. }
  2512. break;
  2513. case UNPACK_TYPE_STRING:
  2514. {
  2515. char *dest_s = ( char * ) dest_field;
  2516. char const *pDefault = "";
  2517. if ( pUnpackTable->m_pKeyDefault )
  2518. {
  2519. pDefault = pUnpackTable->m_pKeyDefault;
  2520. }
  2521. strncpy( dest_s,
  2522. GetString( pUnpackTable->m_pKeyName, pDefault ),
  2523. pUnpackTable->m_nFieldSize );
  2524. }
  2525. break;
  2526. case UNPACK_TYPE_INT:
  2527. {
  2528. int *dest_i = ( int * ) dest_field;
  2529. int default_int = 0;
  2530. if ( pUnpackTable->m_pKeyDefault )
  2531. default_int = atoi( pUnpackTable->m_pKeyDefault );
  2532. *( dest_i ) = GetInt( pUnpackTable->m_pKeyName, default_int );
  2533. }
  2534. break;
  2535. case UNPACK_TYPE_VECTOR_COLOR:
  2536. {
  2537. Vector *dest_v = ( Vector * ) dest_field;
  2538. if ( find_it )
  2539. {
  2540. Color c = GetColor( pUnpackTable->m_pKeyName );
  2541. dest_v->x = c.r();
  2542. dest_v->y = c.g();
  2543. dest_v->z = c.b();
  2544. }
  2545. else
  2546. {
  2547. if ( pUnpackTable->m_pKeyDefault )
  2548. sscanf(pUnpackTable->m_pKeyDefault,"%f %f %f",
  2549. & ( dest_v->x ), & ( dest_v->y ), & ( dest_v->z ));
  2550. else
  2551. dest_v->Init( 0, 0, 0 );
  2552. }
  2553. *( dest_v ) *= ( 1.0 / 255 );
  2554. }
  2555. }
  2556. pUnpackTable++;
  2557. }
  2558. }
  2559. //-----------------------------------------------------------------------------
  2560. // Helper function for processing a keyvalue tree for console resolution support.
  2561. // Alters key/values for easier console video resolution support.
  2562. // If running SD (640x480), the presence of "???_lodef" creates or slams "???".
  2563. // If running HD (1280x720), the presence of "???_hidef" creates or slams "???".
  2564. //-----------------------------------------------------------------------------
  2565. bool KeyValues::ProcessResolutionKeys( const char *pResString )
  2566. {
  2567. if ( !pResString )
  2568. {
  2569. // not for pc, console only
  2570. return false;
  2571. }
  2572. KeyValues *pSubKey = GetFirstSubKey();
  2573. if ( !pSubKey )
  2574. {
  2575. // not a block
  2576. return false;
  2577. }
  2578. for ( ; pSubKey != NULL; pSubKey = pSubKey->GetNextKey() )
  2579. {
  2580. // recursively descend each sub block
  2581. pSubKey->ProcessResolutionKeys( pResString );
  2582. // check to see if our substring is present
  2583. if ( V_stristr( pSubKey->GetName(), pResString ) != NULL )
  2584. {
  2585. char normalKeyName[128];
  2586. V_strncpy( normalKeyName, pSubKey->GetName(), sizeof( normalKeyName ) );
  2587. // substring must match exactly, otherwise keys like "_lodef" and "_lodef_wide" would clash.
  2588. char *pString = V_stristr( normalKeyName, pResString );
  2589. if ( pString && !V_stricmp( pString, pResString ) )
  2590. {
  2591. *pString = '\0';
  2592. // find and delete the original key (if any)
  2593. KeyValues *pKey = FindKey( normalKeyName );
  2594. if ( pKey )
  2595. {
  2596. // remove the key
  2597. RemoveSubKey( pKey );
  2598. pKey->deleteThis();
  2599. }
  2600. // rename the marked key
  2601. pSubKey->SetName( normalKeyName );
  2602. }
  2603. }
  2604. }
  2605. return true;
  2606. }
  2607. //
  2608. // KeyValues merge operations
  2609. //
  2610. void KeyValues::MergeFrom( KeyValues *kvMerge, MergeKeyValuesOp_t eOp /* = MERGE_KV_ALL */ )
  2611. {
  2612. if ( !this || !kvMerge )
  2613. return;
  2614. switch ( eOp )
  2615. {
  2616. case MERGE_KV_ALL:
  2617. MergeFrom( kvMerge->FindKey( "update" ), MERGE_KV_UPDATE );
  2618. MergeFrom( kvMerge->FindKey( "delete" ), MERGE_KV_DELETE );
  2619. MergeFrom( kvMerge->FindKey( "borrow" ), MERGE_KV_BORROW );
  2620. return;
  2621. case MERGE_KV_UPDATE:
  2622. {
  2623. for ( KeyValues *sub = kvMerge->GetFirstTrueSubKey(); sub; sub = sub->GetNextTrueSubKey() )
  2624. {
  2625. char const *szName = sub->GetName();
  2626. KeyValues *subStorage = this->FindKey( szName, false );
  2627. if ( !subStorage )
  2628. {
  2629. AddSubKey( sub->MakeCopy() );
  2630. }
  2631. else
  2632. {
  2633. subStorage->MergeFrom( sub, eOp );
  2634. }
  2635. }
  2636. for ( KeyValues *val = kvMerge->GetFirstValue(); val; val = val->GetNextValue() )
  2637. {
  2638. char const *szName = val->GetName();
  2639. if ( KeyValues *valStorage = this->FindKey( szName, false ) )
  2640. {
  2641. this->RemoveSubKey( valStorage );
  2642. valStorage->deleteThis();
  2643. }
  2644. this->AddSubKey( val->MakeCopy() );
  2645. }
  2646. }
  2647. return;
  2648. case MERGE_KV_BORROW:
  2649. {
  2650. for ( KeyValues *sub = kvMerge->GetFirstTrueSubKey(); sub; sub = sub->GetNextTrueSubKey() )
  2651. {
  2652. char const *szName = sub->GetName();
  2653. KeyValues *subStorage = this->FindKey( szName, false );
  2654. if ( !subStorage )
  2655. continue;
  2656. subStorage->MergeFrom( sub, eOp );
  2657. }
  2658. for ( KeyValues *val = kvMerge->GetFirstValue(); val; val = val->GetNextValue() )
  2659. {
  2660. char const *szName = val->GetName();
  2661. if ( KeyValues *valStorage = this->FindKey( szName, false ) )
  2662. {
  2663. this->RemoveSubKey( valStorage );
  2664. valStorage->deleteThis();
  2665. }
  2666. else
  2667. continue;
  2668. this->AddSubKey( val->MakeCopy() );
  2669. }
  2670. }
  2671. return;
  2672. case MERGE_KV_DELETE:
  2673. {
  2674. for ( KeyValues *sub = kvMerge->GetFirstTrueSubKey(); sub; sub = sub->GetNextTrueSubKey() )
  2675. {
  2676. char const *szName = sub->GetName();
  2677. if ( KeyValues *subStorage = this->FindKey( szName, false ) )
  2678. {
  2679. subStorage->MergeFrom( sub, eOp );
  2680. }
  2681. }
  2682. for ( KeyValues *val = kvMerge->GetFirstValue(); val; val = val->GetNextValue() )
  2683. {
  2684. char const *szName = val->GetName();
  2685. if ( KeyValues *valStorage = this->FindKey( szName, false ) )
  2686. {
  2687. this->RemoveSubKey( valStorage );
  2688. valStorage->deleteThis();
  2689. }
  2690. }
  2691. }
  2692. return;
  2693. }
  2694. }
  2695. //
  2696. // KeyValues from string parsing
  2697. //
  2698. static char const * ParseStringToken( char const *szStringVal, char const **ppEndOfParse )
  2699. {
  2700. // Eat whitespace
  2701. while ( V_isspace( *szStringVal ) )
  2702. ++ szStringVal;
  2703. char const *pszResult = szStringVal;
  2704. while ( *szStringVal && !V_isspace( *szStringVal ) )
  2705. ++ szStringVal;
  2706. if ( ppEndOfParse )
  2707. {
  2708. *ppEndOfParse = szStringVal;
  2709. }
  2710. return pszResult;
  2711. }
  2712. KeyValues * KeyValues::FromString( char const *szName, char const *szStringVal, char const **ppEndOfParse )
  2713. {
  2714. if ( !szName )
  2715. szName = "";
  2716. if ( !szStringVal )
  2717. szStringVal = "";
  2718. KeyValues *kv = new KeyValues( szName );
  2719. if ( !kv )
  2720. return NULL;
  2721. char chName[256] = {0};
  2722. char chValue[256] = {0};
  2723. for ( ; ; )
  2724. {
  2725. char const *szEnd;
  2726. char const *szVarValue = NULL;
  2727. char const *szVarName = ParseStringToken( szStringVal, &szEnd );
  2728. if ( !*szVarName )
  2729. break;
  2730. if ( *szVarName == '}' )
  2731. {
  2732. szStringVal = szVarName + 1;
  2733. break;
  2734. }
  2735. V_strncpy( chName, szVarName, MIN( sizeof( chName ), szEnd - szVarName + 1 ) );
  2736. szVarName = chName;
  2737. szStringVal = szEnd;
  2738. if ( *szVarName == '{' )
  2739. {
  2740. szVarName = "";
  2741. goto do_sub_key;
  2742. }
  2743. szVarValue = ParseStringToken( szStringVal, &szEnd );
  2744. if ( *szVarValue == '}' )
  2745. {
  2746. szStringVal = szVarValue + 1;
  2747. kv->SetString( szVarName, "" );
  2748. break;
  2749. }
  2750. V_strncpy( chValue, szVarValue, MIN( sizeof( chValue ), szEnd - szVarValue + 1 ) );
  2751. szVarValue = chValue;
  2752. szStringVal = szEnd;
  2753. if ( *szVarValue == '{' )
  2754. {
  2755. goto do_sub_key;
  2756. }
  2757. // Try to recognize some known types
  2758. if ( char const *szInt = StringAfterPrefix( szVarValue, "#int#" ) )
  2759. {
  2760. kv->SetInt( szVarName, atoi( szInt ) );
  2761. }
  2762. else if ( !V_stricmp( szVarValue, "#empty#" ) )
  2763. {
  2764. kv->SetString( szVarName, "" );
  2765. }
  2766. else
  2767. {
  2768. kv->SetString( szVarName, szVarValue );
  2769. }
  2770. continue;
  2771. do_sub_key:
  2772. {
  2773. KeyValues *pSubKey = KeyValues::FromString( szVarName, szStringVal, &szEnd );
  2774. if ( pSubKey )
  2775. {
  2776. kv->AddSubKey( pSubKey );
  2777. }
  2778. szStringVal = szEnd;
  2779. continue;
  2780. }
  2781. }
  2782. if ( ppEndOfParse )
  2783. {
  2784. *ppEndOfParse = szStringVal;
  2785. }
  2786. return kv;
  2787. }
  2788. //
  2789. // KeyValues dumping implementation
  2790. //
  2791. bool KeyValues::Dump( IKeyValuesDumpContext *pDump, int nIndentLevel /* = 0 */ )
  2792. {
  2793. if ( !pDump->KvBeginKey( this, nIndentLevel ) )
  2794. return false;
  2795. // Dump values
  2796. for ( KeyValues *val = this ? GetFirstValue() : NULL; val; val = val->GetNextValue() )
  2797. {
  2798. if ( !pDump->KvWriteValue( val, nIndentLevel + 1 ) )
  2799. return false;
  2800. }
  2801. // Dump subkeys
  2802. for ( KeyValues *sub = this ? GetFirstTrueSubKey() : NULL; sub; sub = sub->GetNextTrueSubKey() )
  2803. {
  2804. if ( !sub->Dump( pDump, nIndentLevel + 1 ) )
  2805. return false;
  2806. }
  2807. return pDump->KvEndKey( this, nIndentLevel );
  2808. }
  2809. bool IKeyValuesDumpContextAsText::KvBeginKey( KeyValues *pKey, int nIndentLevel )
  2810. {
  2811. if ( pKey )
  2812. {
  2813. return
  2814. KvWriteIndent( nIndentLevel ) &&
  2815. KvWriteText( pKey->GetName() ) &&
  2816. KvWriteText( " {\n" );
  2817. }
  2818. else
  2819. {
  2820. return
  2821. KvWriteIndent( nIndentLevel ) &&
  2822. KvWriteText( "<< NULL >>\n" );
  2823. }
  2824. }
  2825. bool IKeyValuesDumpContextAsText::KvWriteValue( KeyValues *val, int nIndentLevel )
  2826. {
  2827. if ( !val )
  2828. {
  2829. return
  2830. KvWriteIndent( nIndentLevel ) &&
  2831. KvWriteText( "<< NULL >>\n" );
  2832. }
  2833. if ( !KvWriteIndent( nIndentLevel ) )
  2834. return false;
  2835. if ( !KvWriteText( val->GetName() ) )
  2836. return false;
  2837. if ( !KvWriteText( " " ) )
  2838. return false;
  2839. switch ( val->GetDataType() )
  2840. {
  2841. case KeyValues::TYPE_STRING:
  2842. {
  2843. if ( !KvWriteText( val->GetString() ) )
  2844. return false;
  2845. }
  2846. break;
  2847. case KeyValues::TYPE_INT:
  2848. {
  2849. int n = val->GetInt();
  2850. char *chBuffer = ( char * ) stackalloc( 128 );
  2851. V_snprintf( chBuffer, 128, "int( %d = 0x%X )", n, n );
  2852. if ( !KvWriteText( chBuffer ) )
  2853. return false;
  2854. }
  2855. break;
  2856. case KeyValues::TYPE_FLOAT:
  2857. {
  2858. float fl = val->GetFloat();
  2859. char *chBuffer = ( char * ) stackalloc( 128 );
  2860. V_snprintf( chBuffer, 128, "float( %f )", fl );
  2861. if ( !KvWriteText( chBuffer ) )
  2862. return false;
  2863. }
  2864. break;
  2865. case KeyValues::TYPE_PTR:
  2866. {
  2867. void *ptr = val->GetPtr();
  2868. char *chBuffer = ( char * ) stackalloc( 128 );
  2869. V_snprintf( chBuffer, 128, "ptr( 0x%p )", ptr );
  2870. if ( !KvWriteText( chBuffer ) )
  2871. return false;
  2872. }
  2873. break;
  2874. case KeyValues::TYPE_WSTRING:
  2875. {
  2876. wchar_t const *wsz = val->GetWString();
  2877. int nLen = V_wcslen( wsz );
  2878. int numBytes = nLen*2 + 64;
  2879. char *chBuffer = ( char * ) stackalloc( numBytes );
  2880. V_snprintf( chBuffer, numBytes, "%ls [wstring, len = %d]", wsz, nLen );
  2881. if ( !KvWriteText( chBuffer ) )
  2882. return false;
  2883. }
  2884. break;
  2885. case KeyValues::TYPE_UINT64:
  2886. {
  2887. uint64 n = val->GetUint64();
  2888. char *chBuffer = ( char * ) stackalloc( 128 );
  2889. V_snprintf( chBuffer, 128, "u64( %lld = 0x%llX )", n, n );
  2890. if ( !KvWriteText( chBuffer ) )
  2891. return false;
  2892. }
  2893. break;
  2894. default:
  2895. break;
  2896. #if 0 // this code was accidentally stubbed out by a mis-integration in CL722860; it hasn't been tested
  2897. {
  2898. int n = val->GetDataType();
  2899. char *chBuffer = ( char * ) stackalloc( 128 );
  2900. V_snprintf( chBuffer, 128, "??kvtype[%d]", n );
  2901. if ( !KvWriteText( chBuffer ) )
  2902. return false;
  2903. }
  2904. break;
  2905. #endif
  2906. }
  2907. return KvWriteText( "\n" );
  2908. }
  2909. bool IKeyValuesDumpContextAsText::KvEndKey( KeyValues *pKey, int nIndentLevel )
  2910. {
  2911. if ( pKey )
  2912. {
  2913. return
  2914. KvWriteIndent( nIndentLevel ) &&
  2915. KvWriteText( "}\n" );
  2916. }
  2917. else
  2918. {
  2919. return true;
  2920. }
  2921. }
  2922. bool IKeyValuesDumpContextAsText::KvWriteIndent( int nIndentLevel )
  2923. {
  2924. int numIndentBytes = ( nIndentLevel * 2 + 1 );
  2925. char *pchIndent = ( char * ) stackalloc( numIndentBytes );
  2926. memset( pchIndent, ' ', numIndentBytes - 1 );
  2927. pchIndent[ numIndentBytes - 1 ] = 0;
  2928. return KvWriteText( pchIndent );
  2929. }
  2930. bool CKeyValuesDumpContextAsDevMsg::KvBeginKey( KeyValues *pKey, int nIndentLevel )
  2931. {
  2932. static ConVarRef r_developer( "developer" );
  2933. if ( r_developer.IsValid() && r_developer.GetInt() < m_nDeveloperLevel )
  2934. // If "developer" is not the correct level, then avoid evaluating KeyValues tree early
  2935. return false;
  2936. else
  2937. return IKeyValuesDumpContextAsText::KvBeginKey( pKey, nIndentLevel );
  2938. }
  2939. bool CKeyValuesDumpContextAsDevMsg::KvWriteText( char const *szText )
  2940. {
  2941. if ( m_nDeveloperLevel > 0 )
  2942. {
  2943. DevMsg( "%s", szText );
  2944. }
  2945. else
  2946. {
  2947. Msg( "%s", szText );
  2948. }
  2949. return true;
  2950. }