Dict.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "precompiled.h"
  21. #pragma hdrstop
  22. idStrPool idDict::globalKeys;
  23. idStrPool idDict::globalValues;
  24. /*
  25. ================
  26. idDict::operator=
  27. clear existing key/value pairs and copy all key/value pairs from other
  28. ================
  29. */
  30. idDict &idDict::operator=( const idDict &other ) {
  31. int i;
  32. // check for assignment to self
  33. if ( this == &other ) {
  34. return *this;
  35. }
  36. Clear();
  37. args = other.args;
  38. argHash = other.argHash;
  39. for ( i = 0; i < args.Num(); i++ ) {
  40. args[i].key = globalKeys.CopyString( args[i].key );
  41. args[i].value = globalValues.CopyString( args[i].value );
  42. }
  43. return *this;
  44. }
  45. /*
  46. ================
  47. idDict::Copy
  48. copy all key value pairs without removing existing key/value pairs not present in the other dict
  49. ================
  50. */
  51. void idDict::Copy( const idDict &other ) {
  52. int i, n, *found;
  53. idKeyValue kv;
  54. // check for assignment to self
  55. if ( this == &other ) {
  56. return;
  57. }
  58. n = other.args.Num();
  59. if ( args.Num() ) {
  60. found = (int *) _alloca16( other.args.Num() * sizeof( int ) );
  61. for ( i = 0; i < n; i++ ) {
  62. found[i] = FindKeyIndex( other.args[i].GetKey() );
  63. }
  64. } else {
  65. found = NULL;
  66. }
  67. for ( i = 0; i < n; i++ ) {
  68. if ( found && found[i] != -1 ) {
  69. // first set the new value and then free the old value to allow proper self copying
  70. const idPoolStr *oldValue = args[found[i]].value;
  71. args[found[i]].value = globalValues.CopyString( other.args[i].value );
  72. globalValues.FreeString( oldValue );
  73. } else {
  74. kv.key = globalKeys.CopyString( other.args[i].key );
  75. kv.value = globalValues.CopyString( other.args[i].value );
  76. argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) );
  77. }
  78. }
  79. }
  80. /*
  81. ================
  82. idDict::TransferKeyValues
  83. clear existing key/value pairs and transfer key/value pairs from other
  84. ================
  85. */
  86. void idDict::TransferKeyValues( idDict &other ) {
  87. int i, n;
  88. if ( this == &other ) {
  89. return;
  90. }
  91. if ( other.args.Num() && other.args[0].key->GetPool() != &globalKeys ) {
  92. common->FatalError( "idDict::TransferKeyValues: can't transfer values across a DLL boundary" );
  93. return;
  94. }
  95. Clear();
  96. n = other.args.Num();
  97. args.SetNum( n );
  98. for ( i = 0; i < n; i++ ) {
  99. args[i].key = other.args[i].key;
  100. args[i].value = other.args[i].value;
  101. }
  102. argHash = other.argHash;
  103. other.args.Clear();
  104. other.argHash.Free();
  105. }
  106. /*
  107. ================
  108. idDict::Parse
  109. ================
  110. */
  111. bool idDict::Parse( idParser &parser ) {
  112. idToken token;
  113. idToken token2;
  114. bool errors;
  115. errors = false;
  116. parser.ExpectTokenString( "{" );
  117. parser.ReadToken( &token );
  118. while( ( token.type != TT_PUNCTUATION ) || ( token != "}" ) ) {
  119. if ( token.type != TT_STRING ) {
  120. parser.Error( "Expected quoted string, but found '%s'", token.c_str() );
  121. }
  122. if ( !parser.ReadToken( &token2 ) ) {
  123. parser.Error( "Unexpected end of file" );
  124. }
  125. if ( FindKey( token ) ) {
  126. parser.Warning( "'%s' already defined", token.c_str() );
  127. errors = true;
  128. }
  129. Set( token, token2 );
  130. if ( !parser.ReadToken( &token ) ) {
  131. parser.Error( "Unexpected end of file" );
  132. }
  133. }
  134. return !errors;
  135. }
  136. /*
  137. ================
  138. idDict::SetDefaults
  139. ================
  140. */
  141. void idDict::SetDefaults( const idDict *dict ) {
  142. int i, n;
  143. const idKeyValue *kv, *def;
  144. idKeyValue newkv;
  145. n = dict->args.Num();
  146. for( i = 0; i < n; i++ ) {
  147. def = &dict->args[i];
  148. kv = FindKey( def->GetKey() );
  149. if ( !kv ) {
  150. newkv.key = globalKeys.CopyString( def->key );
  151. newkv.value = globalValues.CopyString( def->value );
  152. argHash.Add( argHash.GenerateKey( newkv.GetKey(), false ), args.Append( newkv ) );
  153. }
  154. }
  155. }
  156. /*
  157. ================
  158. idDict::Clear
  159. ================
  160. */
  161. void idDict::Clear( void ) {
  162. int i;
  163. for( i = 0; i < args.Num(); i++ ) {
  164. globalKeys.FreeString( args[i].key );
  165. globalValues.FreeString( args[i].value );
  166. }
  167. args.Clear();
  168. argHash.Free();
  169. }
  170. /*
  171. ================
  172. idDict::Print
  173. ================
  174. */
  175. void idDict::Print() const {
  176. int i;
  177. int n;
  178. n = args.Num();
  179. for( i = 0; i < n; i++ ) {
  180. idLib::common->Printf( "%s = %s\n", args[i].GetKey().c_str(), args[i].GetValue().c_str() );
  181. }
  182. }
  183. int KeyCompare( const idKeyValue *a, const idKeyValue *b ) {
  184. return idStr::Cmp( a->GetKey(), b->GetKey() );
  185. }
  186. /*
  187. ================
  188. idDict::Checksum
  189. ================
  190. */
  191. int idDict::Checksum( void ) const {
  192. unsigned long ret;
  193. int i, n;
  194. idList<idKeyValue> sorted = args;
  195. sorted.Sort( KeyCompare );
  196. n = sorted.Num();
  197. CRC32_InitChecksum( ret );
  198. for( i = 0; i < n; i++ ) {
  199. CRC32_UpdateChecksum( ret, sorted[i].GetKey().c_str(), sorted[i].GetKey().Length() );
  200. CRC32_UpdateChecksum( ret, sorted[i].GetValue().c_str(), sorted[i].GetValue().Length() );
  201. }
  202. CRC32_FinishChecksum( ret );
  203. return ret;
  204. }
  205. /*
  206. ================
  207. idDict::Allocated
  208. ================
  209. */
  210. size_t idDict::Allocated( void ) const {
  211. int i;
  212. size_t size;
  213. size = args.Allocated() + argHash.Allocated();
  214. for( i = 0; i < args.Num(); i++ ) {
  215. size += args[i].Size();
  216. }
  217. return size;
  218. }
  219. /*
  220. ================
  221. idDict::Set
  222. ================
  223. */
  224. void idDict::Set( const char *key, const char *value ) {
  225. int i;
  226. idKeyValue kv;
  227. if ( key == NULL || key[0] == '\0' ) {
  228. return;
  229. }
  230. i = FindKeyIndex( key );
  231. if ( i != -1 ) {
  232. // first set the new value and then free the old value to allow proper self copying
  233. const idPoolStr *oldValue = args[i].value;
  234. args[i].value = globalValues.AllocString( value );
  235. globalValues.FreeString( oldValue );
  236. } else {
  237. kv.key = globalKeys.AllocString( key );
  238. kv.value = globalValues.AllocString( value );
  239. argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) );
  240. }
  241. }
  242. /*
  243. ================
  244. idDict::GetFloat
  245. ================
  246. */
  247. bool idDict::GetFloat( const char *key, const char *defaultString, float &out ) const {
  248. const char *s;
  249. bool found;
  250. found = GetString( key, defaultString, &s );
  251. out = atof( s );
  252. return found;
  253. }
  254. /*
  255. ================
  256. idDict::GetInt
  257. ================
  258. */
  259. bool idDict::GetInt( const char *key, const char *defaultString, int &out ) const {
  260. const char *s;
  261. bool found;
  262. found = GetString( key, defaultString, &s );
  263. out = atoi( s );
  264. return found;
  265. }
  266. /*
  267. ================
  268. idDict::GetBool
  269. ================
  270. */
  271. bool idDict::GetBool( const char *key, const char *defaultString, bool &out ) const {
  272. const char *s;
  273. bool found;
  274. found = GetString( key, defaultString, &s );
  275. out = ( atoi( s ) != 0 );
  276. return found;
  277. }
  278. /*
  279. ================
  280. idDict::GetAngles
  281. ================
  282. */
  283. bool idDict::GetAngles( const char *key, const char *defaultString, idAngles &out ) const {
  284. bool found;
  285. const char *s;
  286. if ( !defaultString ) {
  287. defaultString = "0 0 0";
  288. }
  289. found = GetString( key, defaultString, &s );
  290. out.Zero();
  291. sscanf( s, "%f %f %f", &out.pitch, &out.yaw, &out.roll );
  292. return found;
  293. }
  294. /*
  295. ================
  296. idDict::GetVector
  297. ================
  298. */
  299. bool idDict::GetVector( const char *key, const char *defaultString, idVec3 &out ) const {
  300. bool found;
  301. const char *s;
  302. if ( !defaultString ) {
  303. defaultString = "0 0 0";
  304. }
  305. found = GetString( key, defaultString, &s );
  306. out.Zero();
  307. sscanf( s, "%f %f %f", &out.x, &out.y, &out.z );
  308. return found;
  309. }
  310. /*
  311. ================
  312. idDict::GetVec2
  313. ================
  314. */
  315. bool idDict::GetVec2( const char *key, const char *defaultString, idVec2 &out ) const {
  316. bool found;
  317. const char *s;
  318. if ( !defaultString ) {
  319. defaultString = "0 0";
  320. }
  321. found = GetString( key, defaultString, &s );
  322. out.Zero();
  323. sscanf( s, "%f %f", &out.x, &out.y );
  324. return found;
  325. }
  326. /*
  327. ================
  328. idDict::GetVec4
  329. ================
  330. */
  331. bool idDict::GetVec4( const char *key, const char *defaultString, idVec4 &out ) const {
  332. bool found;
  333. const char *s;
  334. if ( !defaultString ) {
  335. defaultString = "0 0 0 0";
  336. }
  337. found = GetString( key, defaultString, &s );
  338. out.Zero();
  339. sscanf( s, "%f %f %f %f", &out.x, &out.y, &out.z, &out.w );
  340. return found;
  341. }
  342. /*
  343. ================
  344. idDict::GetMatrix
  345. ================
  346. */
  347. bool idDict::GetMatrix( const char *key, const char *defaultString, idMat3 &out ) const {
  348. const char *s;
  349. bool found;
  350. if ( !defaultString ) {
  351. defaultString = "1 0 0 0 1 0 0 0 1";
  352. }
  353. found = GetString( key, defaultString, &s );
  354. out.Identity(); // sccanf has a bug in it on Mac OS 9. Sigh.
  355. sscanf( s, "%f %f %f %f %f %f %f %f %f", &out[0].x, &out[0].y, &out[0].z, &out[1].x, &out[1].y, &out[1].z, &out[2].x, &out[2].y, &out[2].z );
  356. return found;
  357. }
  358. /*
  359. ================
  360. WriteString
  361. ================
  362. */
  363. static void WriteString( const char *s, idFile *f ) {
  364. int len = strlen( s );
  365. if ( len >= MAX_STRING_CHARS-1 ) {
  366. idLib::common->Error( "idDict::WriteToFileHandle: bad string" );
  367. }
  368. f->Write( s, strlen(s) + 1 );
  369. }
  370. /*
  371. ================
  372. idDict::FindKey
  373. ================
  374. */
  375. const idKeyValue *idDict::FindKey( const char *key ) const {
  376. int i, hash;
  377. if ( key == NULL || key[0] == '\0' ) {
  378. idLib::common->DWarning( "idDict::FindKey: empty key" );
  379. return NULL;
  380. }
  381. hash = argHash.GenerateKey( key, false );
  382. for ( i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  383. if ( args[i].GetKey().Icmp( key ) == 0 ) {
  384. return &args[i];
  385. }
  386. }
  387. return NULL;
  388. }
  389. /*
  390. ================
  391. idDict::FindKeyIndex
  392. ================
  393. */
  394. int idDict::FindKeyIndex( const char *key ) const {
  395. if ( key == NULL || key[0] == '\0' ) {
  396. idLib::common->DWarning( "idDict::FindKeyIndex: empty key" );
  397. return NULL;
  398. }
  399. int hash = argHash.GenerateKey( key, false );
  400. for ( int i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  401. if ( args[i].GetKey().Icmp( key ) == 0 ) {
  402. return i;
  403. }
  404. }
  405. return -1;
  406. }
  407. /*
  408. ================
  409. idDict::Delete
  410. ================
  411. */
  412. void idDict::Delete( const char *key ) {
  413. int hash, i;
  414. hash = argHash.GenerateKey( key, false );
  415. for ( i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  416. if ( args[i].GetKey().Icmp( key ) == 0 ) {
  417. globalKeys.FreeString( args[i].key );
  418. globalValues.FreeString( args[i].value );
  419. args.RemoveIndex( i );
  420. argHash.RemoveIndex( hash, i );
  421. break;
  422. }
  423. }
  424. #if 0
  425. // make sure all keys can still be found in the hash index
  426. for ( i = 0; i < args.Num(); i++ ) {
  427. assert( FindKey( args[i].GetKey() ) != NULL );
  428. }
  429. #endif
  430. }
  431. /*
  432. ================
  433. idDict::MatchPrefix
  434. ================
  435. */
  436. const idKeyValue *idDict::MatchPrefix( const char *prefix, const idKeyValue *lastMatch ) const {
  437. int i;
  438. int len;
  439. int start;
  440. assert( prefix );
  441. len = strlen( prefix );
  442. start = -1;
  443. if ( lastMatch ) {
  444. start = args.FindIndex( *lastMatch );
  445. assert( start >= 0 );
  446. if ( start < 1 ) {
  447. start = 0;
  448. }
  449. }
  450. for( i = start + 1; i < args.Num(); i++ ) {
  451. if ( !args[i].GetKey().Icmpn( prefix, len ) ) {
  452. return &args[i];
  453. }
  454. }
  455. return NULL;
  456. }
  457. /*
  458. ================
  459. idDict::RandomPrefix
  460. ================
  461. */
  462. const char *idDict::RandomPrefix( const char *prefix, idRandom &random ) const {
  463. int count;
  464. const int MAX_RANDOM_KEYS = 2048;
  465. const char *list[MAX_RANDOM_KEYS];
  466. const idKeyValue *kv;
  467. list[0] = "";
  468. for ( count = 0, kv = MatchPrefix( prefix ); kv && count < MAX_RANDOM_KEYS; kv = MatchPrefix( prefix, kv ) ) {
  469. list[count++] = kv->GetValue().c_str();
  470. }
  471. return list[random.RandomInt( count )];
  472. }
  473. /*
  474. ================
  475. idDict::WriteToFileHandle
  476. ================
  477. */
  478. void idDict::WriteToFileHandle( idFile *f ) const {
  479. int c = LittleLong( args.Num() );
  480. f->Write( &c, sizeof( c ) );
  481. for ( int i = 0; i < args.Num(); i++ ) { // don't loop on the swapped count use the original
  482. WriteString( args[i].GetKey().c_str(), f );
  483. WriteString( args[i].GetValue().c_str(), f );
  484. }
  485. }
  486. /*
  487. ================
  488. ReadString
  489. ================
  490. */
  491. static idStr ReadString( idFile *f ) {
  492. char str[MAX_STRING_CHARS];
  493. int len;
  494. for ( len = 0; len < MAX_STRING_CHARS; len++ ) {
  495. f->Read( (void *)&str[len], 1 );
  496. if ( str[len] == 0 ) {
  497. break;
  498. }
  499. }
  500. if ( len == MAX_STRING_CHARS ) {
  501. idLib::common->Error( "idDict::ReadFromFileHandle: bad string" );
  502. }
  503. return idStr( str );
  504. }
  505. /*
  506. ================
  507. idDict::ReadFromFileHandle
  508. ================
  509. */
  510. void idDict::ReadFromFileHandle( idFile *f ) {
  511. int c;
  512. idStr key, val;
  513. Clear();
  514. f->Read( &c, sizeof( c ) );
  515. c = LittleLong( c );
  516. for ( int i = 0; i < c; i++ ) {
  517. key = ReadString( f );
  518. val = ReadString( f );
  519. Set( key, val );
  520. }
  521. }
  522. /*
  523. ================
  524. idDict::Init
  525. ================
  526. */
  527. void idDict::Init( void ) {
  528. globalKeys.SetCaseSensitive( false );
  529. globalValues.SetCaseSensitive( true );
  530. }
  531. /*
  532. ================
  533. idDict::Shutdown
  534. ================
  535. */
  536. void idDict::Shutdown( void ) {
  537. globalKeys.Clear();
  538. globalValues.Clear();
  539. }
  540. /*
  541. ================
  542. idDict::ShowMemoryUsage_f
  543. ================
  544. */
  545. void idDict::ShowMemoryUsage_f( const idCmdArgs &args ) {
  546. idLib::common->Printf( "%5d KB in %d keys\n", globalKeys.Size() >> 10, globalKeys.Num() );
  547. idLib::common->Printf( "%5d KB in %d values\n", globalValues.Size() >> 10, globalValues.Num() );
  548. }
  549. /*
  550. ================
  551. idDictStringSortCmp
  552. ================
  553. */
  554. // NOTE: the const wonkyness is required to make msvc happy
  555. template<>
  556. ID_INLINE int idListSortCompare( const idPoolStr * const *a, const idPoolStr * const *b ) {
  557. return (*a)->Icmp( **b );
  558. }
  559. /*
  560. ================
  561. idDict::ListKeys_f
  562. ================
  563. */
  564. void idDict::ListKeys_f( const idCmdArgs &args ) {
  565. int i;
  566. idList<const idPoolStr *> keyStrings;
  567. for ( i = 0; i < globalKeys.Num(); i++ ) {
  568. keyStrings.Append( globalKeys[i] );
  569. }
  570. keyStrings.Sort();
  571. for ( i = 0; i < keyStrings.Num(); i++ ) {
  572. idLib::common->Printf( "%s\n", keyStrings[i]->c_str() );
  573. }
  574. idLib::common->Printf( "%5d keys\n", keyStrings.Num() );
  575. }
  576. /*
  577. ================
  578. idDict::ListValues_f
  579. ================
  580. */
  581. void idDict::ListValues_f( const idCmdArgs &args ) {
  582. int i;
  583. idList<const idPoolStr *> valueStrings;
  584. for ( i = 0; i < globalValues.Num(); i++ ) {
  585. valueStrings.Append( globalValues[i] );
  586. }
  587. valueStrings.Sort();
  588. for ( i = 0; i < valueStrings.Num(); i++ ) {
  589. idLib::common->Printf( "%s\n", valueStrings[i]->c_str() );
  590. }
  591. idLib::common->Printf( "%5d values\n", valueStrings.Num() );
  592. }