Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qgdict.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qgdict.cpp,v 1.2 2003/07/10 02:40:11 llornkcor Exp $
00003 **
00004 ** Implementation of QGDict and QGDictIterator classes
00005 **
00006 ** Created : 920529
00007 **
00008 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the tools module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
00035 **
00036 **********************************************************************/
00037 
00038 #include "qgdict.h"
00039 #include "qptrlist.h"
00040 #include "qstring.h"
00041 #include "qdatastream.h"
00042 #include <ctype.h>
00043 
00064 static const int op_find = 0;
00065 static const int op_insert = 1;
00066 static const int op_replace = 2;
00067 
00068 
00069 class QGDItList : public QPtrList<QGDictIterator>
00070 {
00071 public:
00072     QGDItList() : QPtrList<QGDictIterator>() {}
00073     QGDItList( const QGDItList &list ) : QPtrList<QGDictIterator>(list) {}
00074     ~QGDItList() { clear(); }
00075     QGDItList &operator=(const QGDItList &list)
00076         { return (QGDItList&)QPtrList<QGDictIterator>::operator=(list); }
00077 };
00078 
00079 
00080 /*****************************************************************************
00081   Default implementation of special and virtual functions
00082  *****************************************************************************/
00083 
00088 int QGDict::hashKeyString( const QString &key )
00089 {
00090 #if defined(QT_CHECK_NULL)
00091     if ( key.isNull() )
00092         qWarning( "QGDict::hashKeyString: Invalid null key" );
00093 #endif
00094     int i;
00095     register uint h=0;
00096     uint g;
00097     const QChar *p = key.unicode();
00098     if ( cases ) {                              // case sensitive
00099         for ( i=0; i<(int)key.length(); i++ ) {
00100             h = (h<<4) + p[i].cell();
00101             if ( (g = h & 0xf0000000) )
00102                 h ^= g >> 24;
00103             h &= ~g;
00104         }
00105     } else {                                    // case insensitive
00106         for ( i=0; i<(int)key.length(); i++ ) {
00107             h = (h<<4) + p[i].lower().cell();
00108             if ( (g = h & 0xf0000000) )
00109                 h ^= g >> 24;
00110             h &= ~g;
00111         }
00112     }
00113     int index = h;
00114     if ( index < 0 )                            // adjust index to table size
00115         index = -index;
00116     return index;
00117 }
00118 
00123 int QGDict::hashKeyAscii( const char *key )
00124 {
00125 #if defined(QT_CHECK_NULL)
00126     if ( key == 0 )
00127         qWarning( "QGDict::hashAsciiKey: Invalid null key" );
00128 #endif
00129     register const char *k = key;
00130     register uint h=0;
00131     uint g;
00132     if ( cases ) {                              // case sensitive
00133         while ( *k ) {
00134             h = (h<<4) + *k++;
00135             if ( (g = h & 0xf0000000) )
00136                 h ^= g >> 24;
00137             h &= ~g;
00138         }
00139     } else {                                    // case insensitive
00140         while ( *k ) {
00141             h = (h<<4) + tolower((uchar) *k);
00142             if ( (g = h & 0xf0000000) )
00143                 h ^= g >> 24;
00144             h &= ~g;
00145             k++;
00146         }
00147     }
00148     int index = h;
00149     if ( index < 0 )                            // adjust index to table size
00150         index = -index;
00151     return index;
00152 }
00153 
00154 #ifndef QT_NO_DATASTREAM
00155 
00166 QDataStream& QGDict::read( QDataStream &s, QPtrCollection::Item &item )
00167 {
00168     item = 0;
00169     return s;
00170 }
00171 
00180 QDataStream& QGDict::write( QDataStream &s, QPtrCollection::Item ) const
00181 {
00182     return s;
00183 }
00184 #endif //QT_NO_DATASTREAM
00185 
00186 /*****************************************************************************
00187   QGDict member functions
00188  *****************************************************************************/
00189 
00199 QGDict::QGDict( uint len, KeyType kt, bool caseSensitive, bool copyKeys )
00200 {
00201     init( len, kt, caseSensitive, copyKeys );
00202 }
00203 
00204 
00205 void QGDict::init( uint len, KeyType kt, bool caseSensitive, bool copyKeys )
00206 {
00207     vlen = len;
00208     if ( vlen == 0 )
00209         vlen = 17;
00210     vec = new QBaseBucket *[vlen];
00211     Q_CHECK_PTR( vec );
00212     memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) );
00213     numItems  = 0;
00214     iterators = 0;
00215     // The caseSensitive and copyKey options don't make sense for
00216     // all dict types.
00217     switch ( (keytype = (uint)kt) ) {
00218         case StringKey:
00219             cases = caseSensitive;
00220             copyk = FALSE;
00221             break;
00222         case AsciiKey:
00223             cases = caseSensitive;
00224             copyk = copyKeys;
00225             break;
00226         default:
00227             cases = FALSE;
00228             copyk = FALSE;
00229             break;
00230     }
00231 }
00232 
00233 
00238 QGDict::QGDict( const QGDict & dict )
00239     : QPtrCollection( dict )
00240 {
00241     init( dict.vlen, (KeyType)dict.keytype, dict.cases, dict.copyk );
00242     QGDictIterator it( dict );
00243     while ( it.get() ) {                        // copy from other dict
00244         switch ( keytype ) {
00245             case StringKey:
00246                 look_string( it.getKeyString(), it.get(), op_insert );
00247                 break;
00248             case AsciiKey:
00249                 look_ascii( it.getKeyAscii(), it.get(), op_insert );
00250                 break;
00251             case IntKey:
00252                 look_int( it.getKeyInt(), it.get(), op_insert );
00253                 break;
00254             case PtrKey:
00255                 look_ptr( it.getKeyPtr(), it.get(), op_insert );
00256                 break;
00257         }
00258         ++it;
00259     }
00260 }
00261 
00262 
00267 QGDict::~QGDict()
00268 {
00269     clear();                                    // delete everything
00270     delete [] vec;
00271     if ( !iterators )                           // no iterators for this dict
00272         return;
00273     QGDictIterator *i = iterators->first();
00274     while ( i ) {                               // notify all iterators that
00275         i->dict = 0;                            // this dict is deleted
00276         i = iterators->next();
00277     }
00278     delete iterators;
00279 }
00280 
00281 
00286 QGDict &QGDict::operator=( const QGDict &dict )
00287 {
00288     if ( &dict == this )
00289         return *this;
00290     clear();
00291     QGDictIterator it( dict );
00292     while ( it.get() ) {                        // copy from other dict
00293         switch ( keytype ) {
00294             case StringKey:
00295                 look_string( it.getKeyString(), it.get(), op_insert );
00296                 break;
00297             case AsciiKey:
00298                 look_ascii( it.getKeyAscii(), it.get(), op_insert );
00299                 break;
00300             case IntKey:
00301                 look_int( it.getKeyInt(), it.get(), op_insert );
00302                 break;
00303             case PtrKey:
00304                 look_ptr( it.getKeyPtr(), it.get(), op_insert );
00305                 break;
00306         }
00307         ++it;
00308     }
00309     return *this;
00310 }
00311 
00329 QPtrCollection::Item QGDict::look_string( const QString &key, QPtrCollection::Item d,
00330                                        int op )
00331 {
00332     QStringBucket *n = 0;
00333     int index = hashKeyString(key) % vlen;
00334     if ( op == op_find ) {                      // find
00335         if ( cases ) {
00336             n = (QStringBucket*)vec[index];
00337             while( n != 0 ) {
00338                 if ( key == n->getKey() )
00339                     return n->getData();        // item found
00340                 n = (QStringBucket*)n->getNext();
00341             }
00342         } else {
00343             QString k = key.lower();
00344             n = (QStringBucket*)vec[index];
00345             while( n != 0 ) {
00346                 if ( k == n->getKey().lower() )
00347                     return n->getData();        // item found
00348                 n = (QStringBucket*)n->getNext();
00349             }
00350         }
00351         return 0;                               // not found
00352     }
00353     if ( op == op_replace ) {                   // replace
00354         if ( vec[index] != 0 )                  // maybe something there
00355             remove_string( key );
00356     }
00357     // op_insert or op_replace
00358     n = new QStringBucket(key,newItem(d),vec[index]);
00359     Q_CHECK_PTR( n );
00360 #if defined(QT_CHECK_NULL)
00361     if ( n->getData() == 0 )
00362         qWarning( "QDict: Cannot insert null item" );
00363 #endif
00364     vec[index] = n;
00365     numItems++;
00366     return n->getData();
00367 }
00368 
00369 QPtrCollection::Item QGDict::look_ascii( const char *key, QPtrCollection::Item d, int op )
00370 {
00371     QAsciiBucket *n;
00372     int index = hashKeyAscii(key) % vlen;
00373     if ( op == op_find ) {                      // find
00374         if ( cases ) {
00375             for ( n=(QAsciiBucket*)vec[index]; n;
00376                   n=(QAsciiBucket*)n->getNext() ) {
00377                 if ( qstrcmp(n->getKey(),key) == 0 )
00378                     return n->getData();        // item found
00379             }
00380         } else {
00381             for ( n=(QAsciiBucket*)vec[index]; n;
00382                   n=(QAsciiBucket*)n->getNext() ) {
00383                 if ( qstricmp(n->getKey(),key) == 0 )
00384                     return n->getData();        // item found
00385             }
00386         }
00387         return 0;                               // not found
00388     }
00389     if ( op == op_replace ) {                   // replace
00390         if ( vec[index] != 0 )                  // maybe something there
00391             remove_ascii( key );
00392     }
00393     // op_insert or op_replace
00394     n = new QAsciiBucket(copyk ? qstrdup(key) : key,newItem(d),vec[index]);
00395     Q_CHECK_PTR( n );
00396 #if defined(QT_CHECK_NULL)
00397     if ( n->getData() == 0 )
00398         qWarning( "QAsciiDict: Cannot insert null item" );
00399 #endif
00400     vec[index] = n;
00401     numItems++;
00402     return n->getData();
00403 }
00404 
00405 QPtrCollection::Item QGDict::look_int( long key, QPtrCollection::Item d, int op )
00406 {
00407     QIntBucket *n;
00408     int index = (int)((ulong)key % vlen);       // simple hash
00409     if ( op == op_find ) {                      // find
00410         for ( n=(QIntBucket*)vec[index]; n;
00411               n=(QIntBucket*)n->getNext() ) {
00412             if ( n->getKey() == key )
00413                 return n->getData();            // item found
00414         }
00415         return 0;                               // not found
00416     }
00417     if ( op == op_replace ) {                   // replace
00418         if ( vec[index] != 0 )                  // maybe something there
00419             remove_int( key );
00420     }
00421     // op_insert or op_replace
00422     n = new QIntBucket(key,newItem(d),vec[index]);
00423     Q_CHECK_PTR( n );
00424 #if defined(QT_CHECK_NULL)
00425     if ( n->getData() == 0 )
00426         qWarning( "QIntDict: Cannot insert null item" );
00427 #endif
00428     vec[index] = n;
00429     numItems++;
00430     return n->getData();
00431 }
00432 
00433 QPtrCollection::Item QGDict::look_ptr( void *key, QPtrCollection::Item d, int op )
00434 {
00435     QPtrBucket *n;
00436     int index = (int)((ulong)key % vlen);       // simple hash
00437     if ( op == op_find ) {                      // find
00438         for ( n=(QPtrBucket*)vec[index]; n;
00439               n=(QPtrBucket*)n->getNext() ) {
00440             if ( n->getKey() == key )
00441                 return n->getData();            // item found
00442         }
00443         return 0;                               // not found
00444     }
00445     if ( op == op_replace ) {                   // replace
00446         if ( vec[index] != 0 )                  // maybe something there
00447             remove_ptr( key );
00448     }
00449     // op_insert or op_replace
00450     n = new QPtrBucket(key,newItem(d),vec[index]);
00451     Q_CHECK_PTR( n );
00452 #if defined(QT_CHECK_NULL)
00453     if ( n->getData() == 0 )
00454         qWarning( "QPtrDict: Cannot insert null item" );
00455 #endif
00456     vec[index] = n;
00457     numItems++;
00458     return n->getData();
00459 }
00460 
00461 
00467 void QGDict::resize( uint newsize )
00468 {
00469     // Save old information
00470     QBaseBucket **old_vec = vec;
00471     uint old_vlen  = vlen;
00472     bool old_copyk = copyk;
00473 
00474     vec = new QBaseBucket *[vlen = newsize];
00475     Q_CHECK_PTR( vec );
00476     memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) );
00477     numItems = 0;
00478     copyk = FALSE;
00479 
00480     // Reinsert every item from vec, deleting vec as we go
00481     for ( uint index = 0; index < old_vlen; index++ ) {
00482         switch ( keytype ) {
00483             case StringKey:
00484                 {
00485                     QStringBucket *n=(QStringBucket *)old_vec[index];
00486                     while ( n ) {
00487                         look_string( n->getKey(), n->getData(), op_insert );
00488                         QStringBucket *t=(QStringBucket *)n->getNext();
00489                         delete n;
00490                         n = t;
00491                     }
00492                 }
00493                 break;
00494             case AsciiKey:
00495                 {
00496                     QAsciiBucket *n=(QAsciiBucket *)old_vec[index];
00497                     while ( n ) {
00498                         look_ascii( n->getKey(), n->getData(), op_insert );
00499                         QAsciiBucket *t=(QAsciiBucket *)n->getNext();
00500                         delete n;
00501                         n = t;
00502                     }
00503                 }
00504                 break;
00505             case IntKey:
00506                 {
00507                     QIntBucket *n=(QIntBucket *)old_vec[index];
00508                     while ( n ) {
00509                         look_int( n->getKey(), n->getData(), op_insert );
00510                         QIntBucket *t=(QIntBucket *)n->getNext();
00511                         delete n;
00512                         n = t;
00513                     }
00514                 }
00515                 break;
00516             case PtrKey:
00517                 {
00518                     QPtrBucket *n=(QPtrBucket *)old_vec[index];
00519                     while ( n ) {
00520                         look_ptr( n->getKey(), n->getData(), op_insert );
00521                         QPtrBucket *t=(QPtrBucket *)n->getNext();
00522                         delete n;
00523                         n = t;
00524                     }
00525                 }
00526                 break;
00527         }
00528     }
00529     delete [] old_vec;
00530 
00531     // Restore state
00532     copyk = old_copyk;
00533 
00534     // Invalidate all iterators, since order is lost
00535     if ( iterators && iterators->count() ) {
00536         QGDictIterator *i = iterators->first();
00537         while ( i ) {
00538             i->toFirst();
00539             i = iterators->next();
00540         }
00541     }
00542 }
00543 
00549 void QGDict::unlink_common( int index, QBaseBucket *node, QBaseBucket *prev )
00550 {
00551     if ( iterators && iterators->count() ) {    // update iterators
00552         QGDictIterator *i = iterators->first();
00553         while ( i ) {                           // invalidate all iterators
00554             if ( i->curNode == node )           // referring to pending node
00555                 i->operator++();
00556             i = iterators->next();
00557         }
00558     }
00559     if ( prev )                                 // unlink node
00560         prev->setNext( node->getNext() );
00561     else
00562         vec[index] = node->getNext();
00563     numItems--;
00564 }
00565 
00566 QStringBucket *QGDict::unlink_string( const QString &key, QPtrCollection::Item d )
00567 {
00568     if ( numItems == 0 )                        // nothing in dictionary
00569         return 0;
00570     QStringBucket *n;
00571     QStringBucket *prev = 0;
00572     int index = hashKeyString(key) % vlen;
00573     if ( cases ) {
00574         for ( n=(QStringBucket*)vec[index]; n;
00575               n=(QStringBucket*)n->getNext() ) {
00576             bool found = (key == n->getKey());
00577             if ( found && d )
00578                 found = (n->getData() == d);
00579             if ( found ) {
00580                 unlink_common(index,n,prev);
00581                 return n;
00582             }
00583             prev = n;
00584         }
00585     } else {
00586         QString k = key.lower();
00587         for ( n=(QStringBucket*)vec[index]; n;
00588               n=(QStringBucket*)n->getNext() ) {
00589             bool found = (k == n->getKey().lower());
00590             if ( found && d )
00591                 found = (n->getData() == d);
00592             if ( found ) {
00593                 unlink_common(index,n,prev);
00594                 return n;
00595             }
00596             prev = n;
00597         }
00598     }
00599     return 0;
00600 }
00601 
00602 QAsciiBucket *QGDict::unlink_ascii( const char *key, QPtrCollection::Item d )
00603 {
00604     if ( numItems == 0 )                        // nothing in dictionary
00605         return 0;
00606     QAsciiBucket *n;
00607     QAsciiBucket *prev = 0;
00608     int index = hashKeyAscii(key) % vlen;
00609     for ( n=(QAsciiBucket *)vec[index]; n; n=(QAsciiBucket *)n->getNext() ) {
00610         bool found = (cases ? qstrcmp(n->getKey(),key)
00611                        : qstricmp(n->getKey(),key)) == 0;
00612         if ( found && d )
00613             found = (n->getData() == d);
00614         if ( found ) {
00615             unlink_common(index,n,prev);
00616             return n;
00617         }
00618         prev = n;
00619     }
00620     return 0;
00621 }
00622 
00623 QIntBucket *QGDict::unlink_int( long key, QPtrCollection::Item d )
00624 {
00625     if ( numItems == 0 )                        // nothing in dictionary
00626         return 0;
00627     QIntBucket *n;
00628     QIntBucket *prev = 0;
00629     int index = (int)((ulong)key % vlen);
00630     for ( n=(QIntBucket *)vec[index]; n; n=(QIntBucket *)n->getNext() ) {
00631         bool found = (n->getKey() == key);
00632         if ( found && d )
00633             found = (n->getData() == d);
00634         if ( found ) {
00635             unlink_common(index,n,prev);
00636             return n;
00637         }
00638         prev = n;
00639     }
00640     return 0;
00641 }
00642 
00643 QPtrBucket *QGDict::unlink_ptr( void *key, QPtrCollection::Item d )
00644 {
00645     if ( numItems == 0 )                        // nothing in dictionary
00646         return 0;
00647     QPtrBucket *n;
00648     QPtrBucket *prev = 0;
00649     int index = (int)((ulong)key % vlen);
00650     for ( n=(QPtrBucket *)vec[index]; n; n=(QPtrBucket *)n->getNext() ) {
00651         bool found = (n->getKey() == key);
00652         if ( found && d )
00653             found = (n->getData() == d);
00654         if ( found ) {
00655             unlink_common(index,n,prev);
00656             return n;
00657         }
00658         prev = n;
00659     }
00660     return 0;
00661 }
00662 
00663 
00670 bool QGDict::remove_string( const QString &key, QPtrCollection::Item item )
00671 {
00672     QStringBucket *n = unlink_string( key, item );
00673     if ( n ) {
00674         deleteItem( n->getData() );
00675         delete n;
00676         return TRUE;
00677     } else {
00678         return FALSE;
00679     }
00680 }
00681 
00682 bool QGDict::remove_ascii( const char *key, QPtrCollection::Item item )
00683 {
00684     QAsciiBucket *n = unlink_ascii( key, item );
00685     if ( n ) {
00686         if ( copyk )
00687             delete [] (char *)n->getKey();
00688         deleteItem( n->getData() );
00689         delete n;
00690     }
00691     return n != 0;
00692 }
00693 
00694 bool QGDict::remove_int( long key, QPtrCollection::Item item )
00695 {
00696     QIntBucket *n = unlink_int( key, item );
00697     if ( n ) {
00698         deleteItem( n->getData() );
00699         delete n;
00700     }
00701     return n != 0;
00702 }
00703 
00704 bool QGDict::remove_ptr( void *key, QPtrCollection::Item item )
00705 {
00706     QPtrBucket *n = unlink_ptr( key, item );
00707     if ( n ) {
00708         deleteItem( n->getData() );
00709         delete n;
00710     }
00711     return n != 0;
00712 }
00713 
00714 QPtrCollection::Item QGDict::take_string( const QString &key )
00715 {
00716     QStringBucket *n = unlink_string( key );
00717     Item d;
00718     if ( n ) {
00719         d = n->getData();
00720         delete n;
00721     } else {
00722         d = 0;
00723     }
00724     return d;
00725 }
00726 
00727 QPtrCollection::Item QGDict::take_ascii( const char *key )
00728 {
00729     QAsciiBucket *n = unlink_ascii( key );
00730     Item d;
00731     if ( n ) {
00732         if ( copyk )
00733             delete [] (char *)n->getKey();
00734         d = n->getData();
00735         delete n;
00736     } else {
00737         d = 0;
00738     }
00739     return d;
00740 }
00741 
00742 QPtrCollection::Item QGDict::take_int( long key )
00743 {
00744     QIntBucket *n = unlink_int( key );
00745     Item d;
00746     if ( n ) {
00747         d = n->getData();
00748         delete n;
00749     } else {
00750         d = 0;
00751     }
00752     return d;
00753 }
00754 
00755 QPtrCollection::Item QGDict::take_ptr( void *key )
00756 {
00757     QPtrBucket *n = unlink_ptr( key );
00758     Item d;
00759     if ( n ) {
00760         d = n->getData();
00761         delete n;
00762     } else {
00763         d = 0;
00764     }
00765     return d;
00766 }
00767 
00771 void QGDict::clear()
00772 {
00773     if ( !numItems )
00774         return;
00775     numItems = 0;                               // disable remove() function
00776     for ( uint j=0; j<vlen; j++ ) {             // destroy hash table
00777         if ( vec[j] ) {
00778             switch ( keytype ) {
00779                 case StringKey:
00780                     {
00781                         QStringBucket *n=(QStringBucket *)vec[j];
00782                         while ( n ) {
00783                             QStringBucket *next = (QStringBucket*)n->getNext();
00784                             deleteItem( n->getData() );
00785                             delete n;
00786                             n = next;
00787                         }
00788                     }
00789                     break;
00790                 case AsciiKey:
00791                     {
00792                         QAsciiBucket *n=(QAsciiBucket *)vec[j];
00793                         while ( n ) {
00794                             QAsciiBucket *next = (QAsciiBucket*)n->getNext();
00795                             if ( copyk )
00796                                 delete [] (char *)n->getKey();
00797                             deleteItem( n->getData() );
00798                             delete n;
00799                             n = next;
00800                         }
00801                     }
00802                     break;
00803                 case IntKey:
00804                     {
00805                         QIntBucket *n=(QIntBucket *)vec[j];
00806                         while ( n ) {
00807                             QIntBucket *next = (QIntBucket*)n->getNext();
00808                             deleteItem( n->getData() );
00809                             delete n;
00810                             n = next;
00811                         }
00812                     }
00813                     break;
00814                 case PtrKey:
00815                     {
00816                         QPtrBucket *n=(QPtrBucket *)vec[j];
00817                         while ( n ) {
00818                             QPtrBucket *next = (QPtrBucket*)n->getNext();
00819                             deleteItem( n->getData() );
00820                             delete n;
00821                             n = next;
00822                         }
00823                     }
00824                     break;
00825             }
00826             vec[j] = 0;                         // detach list of buckets
00827         }
00828     }
00829     if ( iterators && iterators->count() ) {    // invalidate all iterators
00830         QGDictIterator *i = iterators->first();
00831         while ( i ) {
00832             i->curNode = 0;
00833             i = iterators->next();
00834         }
00835     }
00836 }
00837 
00841 void QGDict::statistics() const
00842 {
00843 #if defined(QT_DEBUG)
00844     QString line;
00845     line.fill( '-', 60 );
00846     double real, ideal;
00847     qDebug( line.ascii() );
00848     qDebug( "DICTIONARY STATISTICS:" );
00849     if ( count() == 0 ) {
00850         qDebug( "Empty!" );
00851         qDebug( line.ascii() );
00852         return;
00853     }
00854     real = 0.0;
00855     ideal = (float)count()/(2.0*size())*(count()+2.0*size()-1);
00856     uint i = 0;
00857     while ( i<size() ) {
00858         QBaseBucket *n = vec[i];
00859         int b = 0;
00860         while ( n ) {                           // count number of buckets
00861             b++;
00862             n = n->getNext();
00863         }
00864         real = real + (double)b * ((double)b+1.0)/2.0;
00865         char buf[80], *pbuf;
00866         if ( b > 78 )
00867             b = 78;
00868         pbuf = buf;
00869         while ( b-- )
00870             *pbuf++ = '*';
00871         *pbuf = '\0';
00872         qDebug( buf );
00873         i++;
00874     }
00875     qDebug( "Array size = %d", size() );
00876     qDebug( "# items    = %d", count() );
00877     qDebug( "Real dist  = %g", real );
00878     qDebug( "Rand dist  = %g", ideal );
00879     qDebug( "Real/Rand  = %g", real/ideal );
00880     qDebug( line.ascii() );
00881 #endif // QT_DEBUG
00882 }
00883 
00884 
00885 /*****************************************************************************
00886   QGDict stream functions
00887  *****************************************************************************/
00888 #ifndef QT_NO_DATASTREAM
00889 QDataStream &operator>>( QDataStream &s, QGDict &dict )
00890 {
00891     return dict.read( s );
00892 }
00893 
00894 QDataStream &operator<<( QDataStream &s, const QGDict &dict )
00895 {
00896     return dict.write( s );
00897 }
00898 
00899 #if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
00900 #pragma message disable narrowptr
00901 #endif
00902 
00907 QDataStream &QGDict::read( QDataStream &s )
00908 {
00909     uint num;
00910     s >> num;                                   // read number of items
00911     clear();                                    // clear dict
00912     while ( num-- ) {                           // read all items
00913         Item d;
00914         switch ( keytype ) {
00915             case StringKey:
00916                 {
00917                     QString k;
00918                     s >> k;
00919                     read( s, d );
00920                     look_string( k, d, op_insert );
00921                 }
00922                 break;
00923             case AsciiKey:
00924                 {
00925                     char *k;
00926                     s >> k;
00927                     read( s, d );
00928                     look_ascii( k, d, op_insert );
00929                     if ( copyk )
00930                         delete [] k;
00931                 }
00932                 break;
00933             case IntKey:
00934                 {
00935                     Q_UINT32 k;
00936                     s >> k;
00937                     read( s, d );
00938                     look_int( k, d, op_insert );
00939                 }
00940                 break;
00941             case PtrKey:
00942                 {
00943                     Q_UINT32 k;
00944                     s >> k;
00945                     read( s, d );
00946                     // ### cannot insert 0 - this renders the thing
00947                     // useless since all pointers are written as 0,
00948                     // but hey, serializing pointers?  can it be done
00949                     // at all, ever?
00950                     if ( k )
00951                         look_ptr( (void *)k, d, op_insert );
00952                 }
00953                 break;
00954         }
00955     }
00956     return s;
00957 }
00958 
00963 QDataStream& QGDict::write( QDataStream &s ) const
00964 {
00965     s << count();                               // write number of items
00966     uint i = 0;
00967     while ( i<size() ) {
00968         QBaseBucket *n = vec[i];
00969         while ( n ) {                           // write all buckets
00970             switch ( keytype ) {
00971                 case StringKey:
00972                     s << ((QStringBucket*)n)->getKey();
00973                     break;
00974                 case AsciiKey:
00975                     s << ((QAsciiBucket*)n)->getKey();
00976                     break;
00977                 case IntKey:
00978                     s << (Q_UINT32)((QIntBucket*)n)->getKey();
00979                     break;
00980                 case PtrKey:
00981                     s << (Q_UINT32)0; // ### cannot serialize a pointer
00982                     break;
00983             }
00984             write( s, n->getData() );           // write data
00985             n = n->getNext();
00986         }
00987         i++;
00988     }
00989     return s;
00990 }
00991 #endif //QT_NO_DATASTREAM
00992 
00993 /*****************************************************************************
00994   QGDictIterator member functions
00995  *****************************************************************************/
00996 
01013 QGDictIterator::QGDictIterator( const QGDict &d )
01014 {
01015     dict = (QGDict *)&d;                        // get reference to dict
01016     toFirst();                                  // set to first noe
01017     if ( !dict->iterators ) {
01018         dict->iterators = new QGDItList;        // create iterator list
01019         Q_CHECK_PTR( dict->iterators );
01020     }
01021     dict->iterators->append( this );            // attach iterator to dict
01022 }
01023 
01028 QGDictIterator::QGDictIterator( const QGDictIterator &it )
01029 {
01030     dict = it.dict;
01031     curNode = it.curNode;
01032     curIndex = it.curIndex;
01033     if ( dict )
01034         dict->iterators->append( this );        // attach iterator to dict
01035 }
01036 
01042 QGDictIterator &QGDictIterator::operator=( const QGDictIterator &it )
01043 {
01044     if ( dict )                                 // detach from old dict
01045         dict->iterators->removeRef( this );
01046     dict = it.dict;
01047     curNode = it.curNode;
01048     curIndex = it.curIndex;
01049     if ( dict )
01050         dict->iterators->append( this );        // attach to new list
01051     return *this;
01052 }
01053 
01058 QGDictIterator::~QGDictIterator()
01059 {
01060     if ( dict )                                 // detach iterator from dict
01061         dict->iterators->removeRef( this );
01062 }
01063 
01064 
01069 QPtrCollection::Item QGDictIterator::toFirst()
01070 {
01071     if ( !dict ) {
01072 #if defined(QT_CHECK_NULL)
01073         qWarning( "QGDictIterator::toFirst: Dictionary has been deleted" );
01074 #endif
01075         return 0;
01076     }
01077     if ( dict->count() == 0 ) {                 // empty dictionary
01078         curNode = 0;
01079         return 0;
01080     }
01081     register uint i = 0;
01082     register QBaseBucket **v = dict->vec;
01083     while ( !(*v++) )
01084         i++;
01085     curNode = dict->vec[i];
01086     curIndex = i;
01087     return curNode->getData();
01088 }
01089 
01090 
01095 QPtrCollection::Item QGDictIterator::operator()()
01096 {
01097     if ( !dict ) {
01098 #if defined(QT_CHECK_NULL)
01099         qWarning( "QGDictIterator::operator(): Dictionary has been deleted" );
01100 #endif
01101         return 0;
01102     }
01103     if ( !curNode )
01104         return 0;
01105     QPtrCollection::Item d = curNode->getData();
01106     this->operator++();
01107     return d;
01108 }
01109 
01114 QPtrCollection::Item QGDictIterator::operator++()
01115 {
01116     if ( !dict ) {
01117 #if defined(QT_CHECK_NULL)
01118         qWarning( "QGDictIterator::operator++: Dictionary has been deleted" );
01119 #endif
01120         return 0;
01121     }
01122     if ( !curNode )
01123         return 0;
01124     curNode = curNode->getNext();
01125     if ( !curNode ) {                           // no next bucket
01126         register uint i = curIndex + 1;         // look from next vec element
01127         register QBaseBucket **v = &dict->vec[i];
01128         while ( i < dict->size() && !(*v++) )
01129             i++;
01130         if ( i == dict->size() ) {              // nothing found
01131             curNode = 0;
01132             return 0;
01133         }
01134         curNode = dict->vec[i];
01135         curIndex = i;
01136     }
01137     return curNode->getData();
01138 }
01139 
01144 QPtrCollection::Item QGDictIterator::operator+=( uint jumps )
01145 {
01146     while ( curNode && jumps-- )
01147         operator++();
01148     return curNode ? curNode->getData() : 0;
01149 }

Generated on Sat Nov 5 16:18:30 2005 for OPIE by  doxygen 1.4.2