home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / Dict.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  17KB  |  822 lines

  1.  
  2. #include "precompiled.h"
  3. #pragma hdrstop
  4.  
  5. idStrPool        idDict::globalKeys;
  6. idStrPool        idDict::globalValues;
  7.  
  8. /*
  9. ================
  10. idDict::operator=
  11.  
  12.   clear existing key/value pairs and copy all key/value pairs from other
  13. ================
  14. */
  15. idDict &idDict::operator=( const idDict &other ) {
  16.     int i;
  17. // RAVEN BEGIN
  18. // jnewquist: Tag scope and callees to track allocations using "new".
  19.     MEM_SCOPED_TAG(tag,MA_STRING);
  20. // RAVEN END
  21.  
  22.     // check for assignment to self
  23.     if ( this == &other ) {
  24.         return *this;
  25.     }
  26.  
  27.     Clear();
  28.  
  29.     args = other.args;
  30.     argHash = other.argHash;
  31.  
  32.     for ( i = 0; i < args.Num(); i++ ) {
  33.         args[i].key = globalKeys.CopyString( args[i].key );
  34.         args[i].value = globalValues.CopyString( args[i].value );
  35.     }
  36.  
  37.     return *this;
  38. }
  39.  
  40. /*
  41. ================
  42. idDict::Copy
  43.  
  44.   copy all key value pairs without removing existing key/value pairs not present in the other dict
  45. ================
  46. */
  47. void idDict::Copy( const idDict &other ) {
  48.     int i, n, *found;
  49.     idKeyValue kv;
  50.  
  51.     // check for assignment to self
  52.     if ( this == &other ) {
  53.         return;
  54.     }
  55.  
  56.     n = other.args.Num();
  57.  
  58.     if ( args.Num() ) {
  59.         found = (int *) _alloca16( other.args.Num() * sizeof( int ) );
  60.         for ( i = 0; i < n; i++ ) {
  61.             found[i] = FindKeyIndex( other.args[i].GetKey() );
  62.         }
  63.     } else {
  64.         found = NULL;
  65.     }
  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. ================
  83. idDict::TransferKeyValues
  84.  
  85.   clear existing key/value pairs and transfer key/value pairs from other
  86. ================
  87. */
  88. void idDict::TransferKeyValues( idDict &other ) {
  89.     int i, n;
  90. // RAVEN BEGIN
  91. // jnewquist: Tag scope and callees to track allocations using "new".
  92.     MEM_SCOPED_TAG(tag,MA_STRING);
  93. // RAVEN END
  94.  
  95.     if ( this == &other ) {
  96.         return;
  97.     }
  98.  
  99.     if ( other.args.Num() && other.args[0].key->GetPool() != &globalKeys ) {
  100.         common->FatalError( "idDict::TransferKeyValues: can't transfer values across a DLL boundary" );
  101.         return;
  102.     }
  103.  
  104.     Clear();
  105.  
  106.     n = other.args.Num();
  107.     args.SetNum( n );
  108.     for ( i = 0; i < n; i++ ) {
  109.         args[i].key = other.args[i].key;
  110.         args[i].value = other.args[i].value;
  111.     }
  112.     argHash = other.argHash;
  113.  
  114.     other.args.Clear();
  115.     other.argHash.Free();
  116. }
  117.  
  118. /*
  119. ================
  120. idDict::Parse
  121. ================
  122. */
  123. bool idDict::Parse( idParser &parser ) {
  124.     idToken    token;
  125.     idToken    token2;
  126.     bool    errors;
  127.  
  128.     errors = false;
  129.  
  130.     parser.ExpectTokenString( "{" );
  131.     parser.ReadToken( &token );
  132.     while( ( token.type != TT_PUNCTUATION ) || ( token != "}" ) ) {
  133.         if ( token.type != TT_STRING ) {
  134.             parser.Error( "Expected quoted string, but found '%s'", token.c_str() );
  135.         }
  136.  
  137.         if ( !parser.ReadToken( &token2 ) ) {
  138.             parser.Error( "Unexpected end of file" );
  139.         }
  140.  
  141.         if ( FindKey( token ) ) {
  142.             parser.Warning( "'%s' already defined", token.c_str() );
  143.             errors = true;
  144.         }
  145.         Set( token, token2 );
  146.  
  147.         if ( !parser.ReadToken( &token ) ) {
  148.             parser.Error( "Unexpected end of file" );
  149.         }
  150.     }
  151.  
  152.     return !errors;
  153. }
  154.  
  155. /*
  156. ================
  157. idDict::SetDefaults
  158. ================
  159. */
  160. void idDict::SetDefaults( const idDict *dict ) {
  161.     int i, n;
  162.     const idKeyValue *kv, *def;
  163.     idKeyValue newkv;
  164.  
  165.     n = dict->args.Num();
  166.     for( i = 0; i < n; i++ ) {
  167.         def = &dict->args[i];
  168.         kv = FindKey( def->GetKey() );
  169.         if ( !kv ) {
  170.             newkv.key = globalKeys.CopyString( def->key );
  171.             newkv.value = globalValues.CopyString( def->value );
  172.             argHash.Add( argHash.GenerateKey( newkv.GetKey(), false ), args.Append( newkv ) );
  173.         }
  174.     }
  175. }
  176.  
  177. /*
  178. ================
  179. idDict::Clear
  180. ================
  181. */
  182. void idDict::Clear( void ) {
  183.     int i;
  184.  
  185.     for( i = 0; i < args.Num(); i++ ) {
  186.         globalKeys.FreeString( args[i].key );
  187.         globalValues.FreeString( args[i].value );
  188.     }
  189.  
  190.     args.Clear();
  191.     argHash.Free();
  192. }
  193.  
  194. /*
  195. ================
  196. idDict::Print
  197. ================
  198. */
  199. void idDict::Print() const {
  200.     int i;
  201.     int n;
  202.  
  203.     n = args.Num();
  204.     for( i = 0; i < n; i++ ) {
  205.         idLib::common->Printf( "%s = %s\n", args[i].GetKey().c_str(), args[i].GetValue().c_str() );
  206.     }
  207. }
  208.  
  209. int KeyCompare( const idKeyValue *a, const idKeyValue *b ) {
  210.     return idStr::Cmp( a->GetKey(), b->GetKey() );
  211. }
  212.  
  213. /*
  214. ================
  215. idDict::Checksum
  216. ================
  217. */
  218. int    idDict::Checksum( void ) const {
  219.     unsigned long ret;
  220.     int i, n;
  221.  
  222.     idList<idKeyValue> sorted = args;
  223.     sorted.Sort( KeyCompare );
  224.     n = sorted.Num();
  225.     CRC32_InitChecksum( ret );
  226.     for( i = 0; i < n; i++ ) {
  227.         CRC32_UpdateChecksum( ret, sorted[i].GetKey().c_str(), sorted[i].GetKey().Length() );
  228.         CRC32_UpdateChecksum( ret, sorted[i].GetValue().c_str(), sorted[i].GetValue().Length() );
  229.     }
  230.     CRC32_FinishChecksum( ret );
  231.     return ret;
  232. }
  233.  
  234. /*
  235. ================
  236. idDict::Allocated
  237. ================
  238. */
  239. size_t idDict::Allocated( void ) const {
  240.     int        i;
  241.     size_t    size;
  242.  
  243.     size = args.Allocated() + argHash.Allocated();
  244.     for( i = 0; i < args.Num(); i++ ) {
  245.         size += args[i].Size();
  246.     }
  247.  
  248.     return size;
  249. }
  250.  
  251. /*
  252. ================
  253. idDict::Set
  254. ================
  255. */
  256. void idDict::Set( const char *key, const char *value ) {
  257.     int i;
  258.     idKeyValue kv;
  259. // RAVEN BEGIN
  260. // jnewquist: Tag scope and callees to track allocations using "new".
  261.     MEM_SCOPED_TAG(tag,MA_STRING);
  262. // RAVEN END
  263.  
  264.     if ( key == NULL || key[0] == '\0' ) {
  265.         return;
  266.     }
  267.  
  268.     i = FindKeyIndex( key );
  269.     if ( i != -1 ) {
  270.         // first set the new value and then free the old value to allow proper self copying
  271.         const idPoolStr *oldValue = args[i].value;
  272.         args[i].value = globalValues.AllocString( value );
  273.         globalValues.FreeString( oldValue );
  274.     } else {
  275.         kv.key = globalKeys.AllocString( key );
  276.         kv.value = globalValues.AllocString( value );
  277.         argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) );
  278.     }
  279. }
  280.  
  281. /*
  282. ================
  283. idDict::GetFloat
  284. ================
  285. */
  286. bool idDict::GetFloat( const char *key, const char *defaultString, float &out ) const {
  287.     const char    *s;
  288.     bool        found;
  289.  
  290.     found = GetString( key, defaultString, &s );
  291.     out = atof( s );
  292.     return found;
  293. }
  294.  
  295. /*
  296. ================
  297. idDict::GetInt
  298. ================
  299. */
  300. bool idDict::GetInt( const char *key, const char *defaultString, int &out ) const {
  301.     const char    *s;
  302.     bool        found;
  303.  
  304.     found = GetString( key, defaultString, &s );
  305.     out = atoi( s );
  306.     return found;
  307. }
  308.  
  309. /*
  310. ================
  311. idDict::GetBool
  312. ================
  313. */
  314. bool idDict::GetBool( const char *key, const char *defaultString, bool &out ) const {
  315.     const char    *s;
  316.     bool        found;
  317.  
  318.     found = GetString( key, defaultString, &s );
  319.     out = ( atoi( s ) != 0 );
  320.     return found;
  321. }
  322.  
  323. /*
  324. ================
  325. idDict::GetAngles
  326. ================
  327. */
  328. bool idDict::GetAngles( const char *key, const char *defaultString, idAngles &out ) const {
  329.     bool        found;
  330.     const char    *s;
  331.     
  332.     if ( !defaultString ) {
  333.         defaultString = "0 0 0";
  334.     }
  335.  
  336.     found = GetString( key, defaultString, &s );
  337.     out.Zero();    
  338.     sscanf( s, "%f %f %f", &out.pitch, &out.yaw, &out.roll );
  339.     return found;
  340. }
  341.  
  342. /*
  343. ================
  344. idDict::GetVector
  345. ================
  346. */
  347. bool idDict::GetVector( const char *key, const char *defaultString, idVec3 &out ) const {
  348.     bool        found;
  349.     const char    *s;
  350.     
  351.     if ( !defaultString ) {
  352.         defaultString = "0 0 0";
  353.     }
  354.  
  355.     found = GetString( key, defaultString, &s );
  356.     out.Zero();
  357.     sscanf( s, "%f %f %f", &out.x, &out.y, &out.z );
  358.     return found;
  359. }
  360.  
  361. /*
  362. ================
  363. idDict::GetVec2
  364. ================
  365. */
  366. bool idDict::GetVec2( const char *key, const char *defaultString, idVec2 &out ) const {
  367.     bool        found;
  368.     const char    *s;
  369.     
  370.     if ( !defaultString ) {
  371.         defaultString = "0 0";
  372.     }
  373.  
  374.     found = GetString( key, defaultString, &s );
  375.     out.Zero();
  376.     sscanf( s, "%f %f", &out.x, &out.y );
  377.     return found;
  378. }
  379.  
  380. /*
  381. ================
  382. idDict::GetVec4
  383. ================
  384. */
  385. bool idDict::GetVec4( const char *key, const char *defaultString, idVec4 &out ) const {
  386.     bool        found;
  387.     const char    *s;
  388.     
  389.     if ( !defaultString ) {
  390.         defaultString = "0 0 0 0";
  391.     }
  392.  
  393.     found = GetString( key, defaultString, &s );
  394.     out.Zero();
  395.     sscanf( s, "%f %f %f %f", &out.x, &out.y, &out.z, &out.w );
  396.     return found;
  397. }
  398.  
  399. /*
  400. ================
  401. idDict::GetMatrix
  402. ================
  403. */
  404. bool idDict::GetMatrix( const char *key, const char *defaultString, idMat3 &out ) const {
  405.     const char    *s;
  406.     bool        found;
  407.         
  408.     if ( !defaultString ) {
  409.         defaultString = "1 0 0 0 1 0 0 0 1";
  410.     }
  411.  
  412.     found = GetString( key, defaultString, &s );
  413.     out.Identity();        // sccanf has a bug in it on Mac OS 9.  Sigh.
  414.     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 );
  415.     return found;
  416. }
  417.  
  418. /*
  419. ================
  420. WriteString
  421. ================
  422. */
  423. static void WriteString( const char *s, idFile *f ) {
  424.     int    len = strlen( s );
  425.     if ( len >= MAX_STRING_CHARS-1 ) {
  426.         idLib::common->Error( "idDict::WriteToFileHandle: bad string" );
  427.     }
  428.     f->Write( s, strlen(s) + 1 );
  429. }
  430.  
  431. /*
  432. ================
  433. idDict::FindKey
  434. ================
  435. */
  436. const idKeyValue *idDict::FindKey( const char *key ) const {
  437.     int i, hash;
  438.  
  439.     if ( key == NULL || key[0] == '\0' ) {
  440.         idLib::common->DWarning( "idDict::FindKey: empty key" );
  441.         return NULL;
  442.     }
  443.  
  444.     hash = argHash.GenerateKey( key, false );
  445.     for ( i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  446.         if ( args[i].GetKey().Icmp( key ) == 0 ) {
  447.             return &args[i];
  448.         }
  449.     }
  450.  
  451.     return NULL;
  452. }
  453.  
  454. /*
  455. ================
  456. idDict::FindKeyIndex
  457. ================
  458. */
  459. int idDict::FindKeyIndex( const char *key ) const {
  460.  
  461.     if ( key == NULL || key[0] == '\0' ) {
  462.         idLib::common->DWarning( "idDict::FindKeyIndex: empty key" );
  463.         return NULL;
  464.     }
  465.  
  466.     int hash = argHash.GenerateKey( key, false );
  467.     for ( int i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  468.         if ( args[i].GetKey().Icmp( key ) == 0 ) {
  469.             return i;
  470.         }
  471.     }
  472.  
  473.     return -1;
  474. }
  475.  
  476. /*
  477. ================
  478. idDict::Delete
  479. ================
  480. */
  481. void idDict::Delete( const char *key ) {
  482.     int hash, i;
  483.  
  484.     hash = argHash.GenerateKey( key, false );
  485.     for ( i = argHash.First( hash ); i != -1; i = argHash.Next( i ) ) {
  486.         if ( args[i].GetKey().Icmp( key ) == 0 ) {
  487.             globalKeys.FreeString( args[i].key );
  488.             globalValues.FreeString( args[i].value );
  489.             args.RemoveIndex( i );
  490.             argHash.RemoveIndex( hash, i );
  491.             break;
  492.         }
  493.     }
  494.  
  495. #if 0
  496.     // make sure all keys can still be found in the hash index
  497.     for ( i = 0; i < args.Num(); i++ ) {
  498.         assert( FindKey( args[i].GetKey() ) != NULL );
  499.     }
  500. #endif
  501. }
  502.  
  503. /*
  504. ================
  505. idDict::MatchPrefix
  506. ================
  507. */
  508. const idKeyValue *idDict::MatchPrefix( const char *prefix, const idKeyValue *lastMatch ) const {
  509.     int    i;
  510.     int len;
  511.     int start;
  512.  
  513.     assert( prefix );
  514.     len = strlen( prefix );
  515.  
  516.     start = -1;
  517.     if ( lastMatch ) {
  518.         start = args.FindIndex( *lastMatch );
  519.         assert( start >= 0 );
  520.         if ( start < 1 ) {
  521.             start = 0;
  522.         }
  523.     }
  524.  
  525.     for( i = start + 1; i < args.Num(); i++ ) {
  526.         if ( !args[i].GetKey().Icmpn( prefix, len ) ) {
  527.             return &args[i];
  528.         }
  529.     }
  530.     return NULL;
  531. }
  532.  
  533. /*
  534. ================
  535. idDict::RandomPrefix
  536. ================
  537. */
  538. // RAVEN BEGIN
  539. // abahr: added default value param
  540. const char *idDict::RandomPrefix( const char *prefix, idRandom &random, const char* defaultValue ) const {
  541.     int count;
  542.     const int MAX_RANDOM_KEYS = 2048;
  543.     const char *list[MAX_RANDOM_KEYS];
  544.     const idKeyValue *kv;
  545.  
  546. // RAVEN BEGIN
  547. // abahr: added defaultValue param
  548.     list[0] = defaultValue;
  549. // RAVEN END
  550.     for ( count = 0, kv = MatchPrefix( prefix ); kv && count < MAX_RANDOM_KEYS; kv = MatchPrefix( prefix, kv ) ) {
  551.         list[count++] = kv->GetValue().c_str();
  552.     }
  553.     return list[random.RandomInt( count )];
  554. }
  555.  
  556. /*
  557. ================
  558. idDict::WriteToFileHandle
  559. ================
  560. */
  561. void idDict::WriteToFileHandle( idFile *f ) const {
  562.     int c = LittleLong( args.Num() );
  563.     f->Write( &c, sizeof( c ) );
  564. // RAVEN BEGIN
  565. // jnewquist: For loop was looking at c, which got swapped on Xenon!
  566.     for ( int i = 0; i < args.Num(); i++ ) {
  567. // RAVEN END
  568.         WriteString( args[i].GetKey().c_str(), f );
  569.         WriteString( args[i].GetValue().c_str(), f );
  570.     }
  571. }
  572.  
  573. /*
  574. ================
  575. ReadString
  576. ================
  577. */
  578. static idStr ReadString( idFile *f ) {
  579.     char    str[MAX_STRING_CHARS];
  580.     int        len;
  581.  
  582.     for ( len = 0; len < MAX_STRING_CHARS; len++ ) {
  583.         f->Read( (void *)&str[len], 1 );
  584.         if ( str[len] == 0 ) {
  585.             break;
  586.         }
  587.     }
  588.     if ( len == MAX_STRING_CHARS ) {
  589.         idLib::common->Error( "idDict::ReadFromFileHandle: bad string" );
  590.     }
  591.  
  592.     return idStr( str );
  593. }
  594.  
  595. /*
  596. ================
  597. idDict::ReadFromFileHandle
  598. ================
  599. */
  600. void idDict::ReadFromFileHandle( idFile *f ) {
  601.     int c;
  602.     idStr key, val;
  603.  
  604.     Clear();
  605.  
  606.     f->Read( &c, sizeof( c ) );
  607.     c = LittleLong( c );
  608.     for ( int i = 0; i < c; i++ ) {
  609.         key = ReadString( f );
  610.         val = ReadString( f );
  611.         Set( key, val );
  612.     }
  613. }
  614.  
  615. // RAVEN BEGIN
  616. /*
  617. ================
  618. idDict::WriteToMemory
  619. ================
  620. */
  621. int idDict::WriteToMemory( void *mem, int maxSize ) const {
  622.     int bytesWritten = 0;
  623.     char *out = (char*)mem;
  624.     if ( out ) {
  625.         *((int*)out) = args.Num();
  626.         out+=sizeof(int);
  627.     }
  628.     bytesWritten+=sizeof(int);
  629.     
  630.     int l;
  631.     for ( int i = 0; i < args.Num(); i++ ) {
  632.         l = args[i].GetKey().Length();
  633.         ++l;
  634.         
  635.         if ( bytesWritten + l > maxSize ) {
  636.             assert( 0 );
  637.             return bytesWritten;
  638.         }
  639.         
  640.         if ( out ) {
  641.             memcpy( out, args[i].GetKey().c_str(), l );
  642.         }
  643.         if ( out ) {
  644.             out+=l;
  645.         }
  646.         bytesWritten+=l;
  647.         
  648.         l = args[i].GetValue().Length();
  649.         ++l;
  650.         
  651.         if ( bytesWritten + l > maxSize ) {
  652.             assert( 0 );
  653.             return bytesWritten;
  654.         }
  655.  
  656.         if ( out ) {
  657.             memcpy( out, args[i].GetValue().c_str(), l );
  658.         }
  659.         if ( out ) {
  660.             out+=l;
  661.         }
  662.         bytesWritten+=l;
  663.     }
  664.  
  665.     return bytesWritten;
  666. }
  667.  
  668. /*
  669. ================
  670. idDict::ReadFromMemory
  671. ================
  672. */
  673. void idDict::ReadFromMemory( void *mem, int size ) {
  674.     int bytesRead = 0;
  675.     
  676.     char *in = (char*)mem;
  677.     int c = *((int*)in);
  678.     in+=sizeof(int);
  679.     
  680.     idStr key, val;
  681.  
  682.     Clear();
  683.         
  684.     int readLen;
  685.     for ( int i = 0; i < c; i++ ) {
  686.         key = in;
  687.         readLen = key.Length() + 1;
  688.         in+=readLen;
  689.         bytesRead+=readLen;
  690.         if ( bytesRead >= size ) {
  691.             assert( 0 );
  692.             return;
  693.         }
  694.         
  695.         val = in;
  696.         readLen = val.Length() + 1;
  697.         in+=readLen;
  698.         bytesRead+=readLen;
  699.         if ( bytesRead >= size ) {
  700.             assert( 0 );
  701.             return;
  702.         }
  703.         
  704.         Set( key, val );
  705.     }
  706. }
  707. // RAVEN END
  708.  
  709. /*
  710. ================
  711. idDict::Init
  712. ================
  713. */
  714. void idDict::Init( void ) {
  715.     globalKeys.SetCaseSensitive( false );
  716.     globalValues.SetCaseSensitive( true );
  717.  
  718. // RAVEN BEGIN
  719. // mwhitlock: Dynamic memory consolidation
  720. #if defined(_RV_MEM_SYS_SUPPORT)
  721.     globalKeys.SetAllocatorHeap(rvGetSysHeap(RV_HEAP_ID_PERMANENT));
  722.     globalValues.SetAllocatorHeap(rvGetSysHeap(RV_HEAP_ID_PERMANENT));
  723. #endif
  724. // RAVEN END
  725. }
  726.  
  727. /*
  728. ================
  729. idDict::Shutdown
  730. ================
  731. */
  732. void idDict::Shutdown( void ) {
  733.     globalKeys.Clear();
  734.     globalValues.Clear();
  735. }
  736.  
  737. /*
  738. ================
  739. idDict::ShowMemoryUsage_f
  740. ================
  741. */
  742. void idDict::ShowMemoryUsage_f( const idCmdArgs &args ) {
  743.     idLib::common->Printf( "%5d KB in %d keys\n", globalKeys.Size() >> 10, globalKeys.Num() );
  744.     idLib::common->Printf( "%5d KB in %d values\n", globalValues.Size() >> 10, globalValues.Num() );
  745. }
  746.  
  747. /*
  748. ================
  749. idDictStringSortCmp
  750. ================
  751. */
  752. // NOTE: the const wonkyness is required to make msvc happy
  753. template<>
  754. ID_INLINE int idListSortCompare( const idPoolStr * const *a, const idPoolStr * const *b ) {
  755.     return (*a)->Icmp( **b );
  756. }
  757.  
  758. /*
  759. ================
  760. idDict::ListKeys_f
  761. ================
  762. */
  763. void idDict::ListKeys_f( const idCmdArgs &args ) {
  764.     int i;
  765.     idList<const idPoolStr *> keyStrings;
  766.  
  767.     for ( i = 0; i < globalKeys.Num(); i++ ) {
  768.         keyStrings.Append( globalKeys[i] );
  769.     }
  770.     keyStrings.Sort();
  771.     for ( i = 0; i < keyStrings.Num(); i++ ) {
  772.         idLib::common->Printf( "%s\n", keyStrings[i]->c_str() );
  773.     }
  774.     idLib::common->Printf( "%5d keys\n", keyStrings.Num() );
  775. }
  776.  
  777. /*
  778. ================
  779. idDict::ListValues_f
  780. ================
  781. */
  782. void idDict::ListValues_f( const idCmdArgs &args ) {
  783.     int i;
  784.     idList<const idPoolStr *> valueStrings;
  785.  
  786.     for ( i = 0; i < globalValues.Num(); i++ ) {
  787.         valueStrings.Append( globalValues[i] );
  788.     }
  789.     valueStrings.Sort();
  790.     for ( i = 0; i < valueStrings.Num(); i++ ) {
  791.         idLib::common->Printf( "%s\n", valueStrings[i]->c_str() );
  792.     }
  793.     idLib::common->Printf( "%5d values\n", valueStrings.Num() );
  794. }
  795.  
  796. // RAVEN BEGIN
  797. // jsinger: allow support for serialization/deserialization of binary decls
  798. #ifdef RV_BINARYDECLS
  799. void idDict::Write( SerialOutputStream &stream ) const
  800. {
  801.     stream.Write(GetNumKeyVals());
  802.     for(int i=0;i<GetNumKeyVals();i++)
  803.     {
  804.         idKeyValue const *keyVal = GetKeyVal(i);
  805.         stream.Write(keyVal->GetKey());
  806.         stream.Write(keyVal->GetValue());
  807.     }
  808. }
  809.  
  810. idDict::idDict( SerialInputStream &stream )
  811. {
  812.     int numKeyVals = stream.ReadIntValue();
  813.     for(int i=0; i<numKeyVals; i++)
  814.     {
  815.         idStr key = stream.ReadStringValue();
  816.         idStr value = stream.ReadStringValue();
  817.         Set(key.c_str(), value.c_str());
  818.     }
  819. }
  820. #endif
  821. // RAVEN END
  822.