diff options
Diffstat (limited to 'src/tools/qgdict.cpp')
-rw-r--r-- | src/tools/qgdict.cpp | 1151 |
1 files changed, 1151 insertions, 0 deletions
diff --git a/src/tools/qgdict.cpp b/src/tools/qgdict.cpp new file mode 100644 index 000000000..1a5e2c31d --- /dev/null +++ b/src/tools/qgdict.cpp @@ -0,0 +1,1151 @@ +/**************************************************************************** +** +** Implementation of TQGDict and TQGDictIterator classes +** +** Created : 920529 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qgdict.h" +#include "qptrlist.h" +#include "qstring.h" +#include "qdatastream.h" +#include <ctype.h> + +/*! + \class TQGDict + \reentrant + \ingroup collection + \brief The TQGDict class is an internal class for implementing TQDict template classes. + + \internal + + TQGDict is a strictly internal class that acts as a base class for the + \link collection.html collection classes\endlink TQDict and TQIntDict. + + TQGDict has some virtual functions that can be reimplemented to customize + the subclasses. + \list + \i read() reads a collection/dictionary item from a TQDataStream. + \i write() writes a collection/dictionary item to a TQDataStream. + \endlist + Normally, you do not have to reimplement any of these functions. +*/ + +static const int op_find = 0; +static const int op_insert = 1; +static const int op_replace = 2; + + +class TQGDItList : public TQPtrList<TQGDictIterator> +{ +public: + TQGDItList() : TQPtrList<TQGDictIterator>() {} + TQGDItList( const TQGDItList &list ) : TQPtrList<TQGDictIterator>(list) {} + ~TQGDItList() { clear(); } + TQGDItList &operator=(const TQGDItList &list) + { return (TQGDItList&)TQPtrList<TQGDictIterator>::operator=(list); } +}; + + +/***************************************************************************** + Default implementation of special and virtual functions + *****************************************************************************/ + +/*! + Returns the hash key for \a key, when key is a string. +*/ + +int TQGDict::hashKeyString( const TQString &key ) +{ +#if defined(QT_CHECK_NULL) + if ( key.isNull() ) + qWarning( "TQGDict::hashKeyString: Invalid null key" ); +#endif + int i; + register uint h=0; + uint g; + const TQChar *p = key.unicode(); + if ( cases ) { // case sensitive + for ( i=0; i<(int)key.length(); i++ ) { + h = (h<<4) + p[i].cell(); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } else { // case insensitive + for ( i=0; i<(int)key.length(); i++ ) { + h = (h<<4) + p[i].lower().cell(); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } + int index = h; + if ( index < 0 ) // adjust index to table size + index = -index; + return index; +} + +/*! + Returns the hash key for \a key, which is a C string. +*/ + +int TQGDict::hashKeyAscii( const char *key ) +{ +#if defined(QT_CHECK_NULL) + if ( key == 0 ) + qWarning( "TQGDict::hashAsciiKey: Invalid null key" ); +#endif + register const char *k = key; + register uint h=0; + uint g; + if ( cases ) { // case sensitive + while ( *k ) { + h = (h<<4) + *k++; + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } else { // case insensitive + while ( *k ) { + h = (h<<4) + tolower((uchar) *k); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + k++; + } + } + int index = h; + if ( index < 0 ) // adjust index to table size + index = -index; + return index; +} + +#ifndef QT_NO_DATASTREAM + +/*! + \overload + Reads a collection/dictionary item from the stream \a s and returns a + reference to the stream. + + The default implementation sets \a item to 0. + + \sa write() +*/ + +TQDataStream& TQGDict::read( TQDataStream &s, TQPtrCollection::Item &item ) +{ + item = 0; + return s; +} + +/*! + \overload + Writes a collection/dictionary item to the stream \a s and returns a + reference to the stream. + + \sa read() +*/ + +TQDataStream& TQGDict::write( TQDataStream &s, TQPtrCollection::Item ) const +{ + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + TQGDict member functions + *****************************************************************************/ + +/*! + Constructs a dictionary. + + \a len is the initial size of the dictionary. + The key type is \a kt which may be \c StringKey, \c AsciiKey, + \c IntKey or \c PtrKey. The case-sensitivity of lookups is set with + \a caseSensitive. Keys are copied if \a copyKeys is TRUE. +*/ + +TQGDict::TQGDict( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) +{ + init( len, kt, caseSensitive, copyKeys ); +} + + +void TQGDict::init( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) +{ + vlen = len ? len : 17; + vec = new TQBaseBucket *[ vlen ]; + + Q_CHECK_PTR( vec ); + memset( (char*)vec, 0, vlen*sizeof(TQBaseBucket*) ); + numItems = 0; + iterators = 0; + // The caseSensitive and copyKey options don't make sense for + // all dict types. + switch ( (keytype = (uint)kt) ) { + case StringKey: + cases = caseSensitive; + copyk = FALSE; + break; + case AsciiKey: + cases = caseSensitive; + copyk = copyKeys; + break; + default: + cases = FALSE; + copyk = FALSE; + break; + } +} + + +/*! + Constructs a copy of \a dict. +*/ + +TQGDict::TQGDict( const TQGDict & dict ) + : TQPtrCollection( dict ) +{ + init( dict.vlen, (KeyType)dict.keytype, dict.cases, dict.copyk ); + TQGDictIterator it( dict ); + while ( it.get() ) { // copy from other dict + switch ( keytype ) { + case StringKey: + look_string( it.getKeyString(), it.get(), op_insert ); + break; + case AsciiKey: + look_ascii( it.getKeyAscii(), it.get(), op_insert ); + break; + case IntKey: + look_int( it.getKeyInt(), it.get(), op_insert ); + break; + case PtrKey: + look_ptr( it.getKeyPtr(), it.get(), op_insert ); + break; + } + ++it; + } +} + + +/*! + Removes all items from the dictionary and destroys it. +*/ + +TQGDict::~TQGDict() +{ + clear(); // delete everything + delete [] vec; + if ( !iterators ) // no iterators for this dict + return; + TQGDictIterator *i = iterators->first(); + while ( i ) { // notify all iterators that + i->dict = 0; // this dict is deleted + i = iterators->next(); + } + delete iterators; +} + + +/*! + Assigns \a dict to this dictionary. +*/ + +TQGDict &TQGDict::operator=( const TQGDict &dict ) +{ + if ( &dict == this ) + return *this; + clear(); + TQGDictIterator it( dict ); + while ( it.get() ) { // copy from other dict + switch ( keytype ) { + case StringKey: + look_string( it.getKeyString(), it.get(), op_insert ); + break; + case AsciiKey: + look_ascii( it.getKeyAscii(), it.get(), op_insert ); + break; + case IntKey: + look_int( it.getKeyInt(), it.get(), op_insert ); + break; + case PtrKey: + look_ptr( it.getKeyPtr(), it.get(), op_insert ); + break; + } + ++it; + } + return *this; +} + +/*! + \fn uint TQGDict::count() const + + Returns the number of items in the dictionary. +*/ + +/*! + \fn uint TQGDict::size() const + + Returns the size of the hash array. +*/ + +/*! + The do-it-all function; \a op is one of op_find, op_insert, op_replace. + The key is \a key and the item is \a d. +*/ + +TQPtrCollection::Item TQGDict::look_string( const TQString &key, TQPtrCollection::Item d, + int op ) +{ + TQStringBucket *n = 0; + int index = hashKeyString(key) % vlen; + if ( op == op_find ) { // find + if ( cases ) { + n = (TQStringBucket*)vec[index]; + while( n != 0 ) { + if ( key == n->getKey() ) + return n->getData(); // item found + n = (TQStringBucket*)n->getNext(); + } + } else { + TQString k = key.lower(); + n = (TQStringBucket*)vec[index]; + while( n != 0 ) { + if ( k == n->getKey().lower() ) + return n->getData(); // item found + n = (TQStringBucket*)n->getNext(); + } + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_string( key ); + } + // op_insert or op_replace + n = new TQStringBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "TQDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +TQPtrCollection::Item TQGDict::look_ascii( const char *key, TQPtrCollection::Item d, int op ) +{ + TQAsciiBucket *n; + int index = hashKeyAscii(key) % vlen; + if ( op == op_find ) { // find + if ( cases ) { + for ( n=(TQAsciiBucket*)vec[index]; n; + n=(TQAsciiBucket*)n->getNext() ) { + if ( qstrcmp(n->getKey(),key) == 0 ) + return n->getData(); // item found + } + } else { + for ( n=(TQAsciiBucket*)vec[index]; n; + n=(TQAsciiBucket*)n->getNext() ) { + if ( qstricmp(n->getKey(),key) == 0 ) + return n->getData(); // item found + } + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_ascii( key ); + } + // op_insert or op_replace + n = new TQAsciiBucket(copyk ? qstrdup(key) : key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "TQAsciiDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +TQPtrCollection::Item TQGDict::look_int( long key, TQPtrCollection::Item d, int op ) +{ + TQIntBucket *n; + int index = (int)((ulong)key % vlen); // simple hash + if ( op == op_find ) { // find + for ( n=(TQIntBucket*)vec[index]; n; + n=(TQIntBucket*)n->getNext() ) { + if ( n->getKey() == key ) + return n->getData(); // item found + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_int( key ); + } + // op_insert or op_replace + n = new TQIntBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "TQIntDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +TQPtrCollection::Item TQGDict::look_ptr( void *key, TQPtrCollection::Item d, int op ) +{ + TQPtrBucket *n; + int index = (int)((ulong)key % vlen); // simple hash + if ( op == op_find ) { // find + for ( n=(TQPtrBucket*)vec[index]; n; + n=(TQPtrBucket*)n->getNext() ) { + if ( n->getKey() == key ) + return n->getData(); // item found + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_ptr( key ); + } + // op_insert or op_replace + n = new TQPtrBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "TQPtrDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! + Changes the size of the hashtable to \a newsize. + The contents of the dictionary are preserved, + but all iterators on the dictionary become invalid. +*/ +void TQGDict::resize( uint newsize ) +{ + // Save old information + TQBaseBucket **old_vec = vec; + uint old_vlen = vlen; + bool old_copyk = copyk; + + vec = new TQBaseBucket *[vlen = newsize]; + Q_CHECK_PTR( vec ); + memset( (char*)vec, 0, vlen*sizeof(TQBaseBucket*) ); + numItems = 0; + copyk = FALSE; + + // Reinsert every item from vec, deleting vec as we go + for ( uint index = 0; index < old_vlen; index++ ) { + switch ( keytype ) { + case StringKey: + { + TQStringBucket *n=(TQStringBucket *)old_vec[index]; + while ( n ) { + look_string( n->getKey(), n->getData(), op_insert ); + TQStringBucket *t=(TQStringBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case AsciiKey: + { + TQAsciiBucket *n=(TQAsciiBucket *)old_vec[index]; + while ( n ) { + look_ascii( n->getKey(), n->getData(), op_insert ); + TQAsciiBucket *t=(TQAsciiBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case IntKey: + { + TQIntBucket *n=(TQIntBucket *)old_vec[index]; + while ( n ) { + look_int( n->getKey(), n->getData(), op_insert ); + TQIntBucket *t=(TQIntBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case PtrKey: + { + TQPtrBucket *n=(TQPtrBucket *)old_vec[index]; + while ( n ) { + look_ptr( n->getKey(), n->getData(), op_insert ); + TQPtrBucket *t=(TQPtrBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + } + } + delete [] old_vec; + + // Restore state + copyk = old_copyk; + + // Invalidate all iterators, since order is lost + if ( iterators && iterators->count() ) { + TQGDictIterator *i = iterators->first(); + while ( i ) { + i->toFirst(); + i = iterators->next(); + } + } +} + +/*! + Unlinks the bucket with the specified key (and specified data pointer, + if it is set). +*/ + +void TQGDict::unlink_common( int index, TQBaseBucket *node, TQBaseBucket *prev ) +{ + if ( iterators && iterators->count() ) { // update iterators + TQGDictIterator *i = iterators->first(); + while ( i ) { // invalidate all iterators + if ( i->curNode == node ) // referring to pending node + i->operator++(); + i = iterators->next(); + } + } + if ( prev ) // unlink node + prev->setNext( node->getNext() ); + else + vec[index] = node->getNext(); + numItems--; +} + +TQStringBucket *TQGDict::unlink_string( const TQString &key, TQPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + TQStringBucket *n; + TQStringBucket *prev = 0; + int index = hashKeyString(key) % vlen; + if ( cases ) { + for ( n=(TQStringBucket*)vec[index]; n; + n=(TQStringBucket*)n->getNext() ) { + bool found = (key == n->getKey()); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + } else { + TQString k = key.lower(); + for ( n=(TQStringBucket*)vec[index]; n; + n=(TQStringBucket*)n->getNext() ) { + bool found = (k == n->getKey().lower()); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + } + return 0; +} + +TQAsciiBucket *TQGDict::unlink_ascii( const char *key, TQPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + TQAsciiBucket *n; + TQAsciiBucket *prev = 0; + int index = hashKeyAscii(key) % vlen; + for ( n=(TQAsciiBucket *)vec[index]; n; n=(TQAsciiBucket *)n->getNext() ) { + bool found = (cases ? qstrcmp(n->getKey(),key) + : qstricmp(n->getKey(),key)) == 0; + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + +TQIntBucket *TQGDict::unlink_int( long key, TQPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + TQIntBucket *n; + TQIntBucket *prev = 0; + int index = (int)((ulong)key % vlen); + for ( n=(TQIntBucket *)vec[index]; n; n=(TQIntBucket *)n->getNext() ) { + bool found = (n->getKey() == key); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + +TQPtrBucket *TQGDict::unlink_ptr( void *key, TQPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + TQPtrBucket *n; + TQPtrBucket *prev = 0; + int index = (int)((ulong)key % vlen); + for ( n=(TQPtrBucket *)vec[index]; n; n=(TQPtrBucket *)n->getNext() ) { + bool found = (n->getKey() == key); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + + +/*! + Removes the item with the specified \a key. If \a item is not null, + the remove will match the \a item as well (used to remove an + item when several items have the same key). +*/ + +bool TQGDict::remove_string( const TQString &key, TQPtrCollection::Item item ) +{ + TQStringBucket *n = unlink_string( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + return TRUE; + } else { + return FALSE; + } +} + +bool TQGDict::remove_ascii( const char *key, TQPtrCollection::Item item ) +{ + TQAsciiBucket *n = unlink_ascii( key, item ); + if ( n ) { + if ( copyk ) + delete [] (char *)n->getKey(); + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +bool TQGDict::remove_int( long key, TQPtrCollection::Item item ) +{ + TQIntBucket *n = unlink_int( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +bool TQGDict::remove_ptr( void *key, TQPtrCollection::Item item ) +{ + TQPtrBucket *n = unlink_ptr( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +TQPtrCollection::Item TQGDict::take_string( const TQString &key ) +{ + TQStringBucket *n = unlink_string( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +TQPtrCollection::Item TQGDict::take_ascii( const char *key ) +{ + TQAsciiBucket *n = unlink_ascii( key ); + Item d; + if ( n ) { + if ( copyk ) + delete [] (char *)n->getKey(); + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +TQPtrCollection::Item TQGDict::take_int( long key ) +{ + TQIntBucket *n = unlink_int( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +TQPtrCollection::Item TQGDict::take_ptr( void *key ) +{ + TQPtrBucket *n = unlink_ptr( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +/*! + Removes all items from the dictionary. +*/ +void TQGDict::clear() +{ + if ( !numItems ) + return; + numItems = 0; // disable remove() function + for ( uint j=0; j<vlen; j++ ) { // destroy hash table + if ( vec[j] ) { + switch ( keytype ) { + case StringKey: + { + TQStringBucket *n=(TQStringBucket *)vec[j]; + while ( n ) { + TQStringBucket *next = (TQStringBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case AsciiKey: + { + TQAsciiBucket *n=(TQAsciiBucket *)vec[j]; + while ( n ) { + TQAsciiBucket *next = (TQAsciiBucket*)n->getNext(); + if ( copyk ) + delete [] (char *)n->getKey(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case IntKey: + { + TQIntBucket *n=(TQIntBucket *)vec[j]; + while ( n ) { + TQIntBucket *next = (TQIntBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case PtrKey: + { + TQPtrBucket *n=(TQPtrBucket *)vec[j]; + while ( n ) { + TQPtrBucket *next = (TQPtrBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + } + vec[j] = 0; // detach list of buckets + } + } + if ( iterators && iterators->count() ) { // invalidate all iterators + TQGDictIterator *i = iterators->first(); + while ( i ) { + i->curNode = 0; + i = iterators->next(); + } + } +} + +/*! + Outputs debug statistics. +*/ +void TQGDict::statistics() const +{ +#if defined(QT_DEBUG) + TQString line; + line.fill( '-', 60 ); + double real, ideal; + qDebug( line.ascii() ); + qDebug( "DICTIONARY STATISTICS:" ); + if ( count() == 0 ) { + qDebug( "Empty!" ); + qDebug( line.ascii() ); + return; + } + real = 0.0; + ideal = (float)count()/(2.0*size())*(count()+2.0*size()-1); + uint i = 0; + while ( i<size() ) { + TQBaseBucket *n = vec[i]; + int b = 0; + while ( n ) { // count number of buckets + b++; + n = n->getNext(); + } + real = real + (double)b * ((double)b+1.0)/2.0; + char buf[80], *pbuf; + if ( b > 78 ) + b = 78; + pbuf = buf; + while ( b-- ) + *pbuf++ = '*'; + *pbuf = '\0'; + qDebug( buf ); + i++; + } + qDebug( "Array size = %d", size() ); + qDebug( "# items = %d", count() ); + qDebug( "Real dist = %g", real ); + qDebug( "Rand dist = %g", ideal ); + qDebug( "Real/Rand = %g", real/ideal ); + qDebug( line.ascii() ); +#endif // QT_DEBUG +} + + +/***************************************************************************** + TQGDict stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +TQDataStream &operator>>( TQDataStream &s, TQGDict &dict ) +{ + return dict.read( s ); +} + +TQDataStream &operator<<( TQDataStream &s, const TQGDict &dict ) +{ + return dict.write( s ); +} + +#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001) +#pragma message disable narrowptr +#endif + +/*! + Reads a dictionary from the stream \a s. +*/ + +TQDataStream &TQGDict::read( TQDataStream &s ) +{ + uint num; + s >> num; // read number of items + clear(); // clear dict + while ( num-- ) { // read all items + Item d; + switch ( keytype ) { + case StringKey: + { + TQString k; + s >> k; + read( s, d ); + look_string( k, d, op_insert ); + } + break; + case AsciiKey: + { + char *k; + s >> k; + read( s, d ); + look_ascii( k, d, op_insert ); + if ( copyk ) + delete [] k; + } + break; + case IntKey: + { + Q_UINT32 k; + s >> k; + read( s, d ); + look_int( k, d, op_insert ); + } + break; + case PtrKey: + { + Q_UINT32 k; + s >> k; + read( s, d ); + // ### cannot insert 0 - this renders the thing + // useless since all pointers are written as 0, + // but hey, serializing pointers? can it be done + // at all, ever? + if ( k ) + look_ptr( (void *)k, d, op_insert ); + } + break; + } + } + return s; +} + +/*! + Writes the dictionary to the stream \a s. +*/ + +TQDataStream& TQGDict::write( TQDataStream &s ) const +{ + s << count(); // write number of items + uint i = 0; + while ( i<size() ) { + TQBaseBucket *n = vec[i]; + while ( n ) { // write all buckets + switch ( keytype ) { + case StringKey: + s << ((TQStringBucket*)n)->getKey(); + break; + case AsciiKey: + s << ((TQAsciiBucket*)n)->getKey(); + break; + case IntKey: + s << (Q_UINT32)((TQIntBucket*)n)->getKey(); + break; + case PtrKey: + s << (Q_UINT32)0; // ### cannot serialize a pointer + break; + } + write( s, n->getData() ); // write data + n = n->getNext(); + } + i++; + } + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + TQGDictIterator member functions + *****************************************************************************/ + +/*! + \class TQGDictIterator qgdict.h + \reentrant + \ingroup collection + \brief The TQGDictIterator class is an internal class for implementing TQDictIterator and TQIntDictIterator. + + \internal + + TQGDictIterator is a strictly internal class that does the heavy work for + TQDictIterator and TQIntDictIterator. +*/ + +/*! + Constructs an iterator that operates on the dictionary \a d. +*/ + +TQGDictIterator::TQGDictIterator( const TQGDict &d ) +{ + dict = (TQGDict *)&d; // get reference to dict + toFirst(); // set to first noe + if ( !dict->iterators ) { + dict->iterators = new TQGDItList; // create iterator list + Q_CHECK_PTR( dict->iterators ); + } + dict->iterators->append( this ); // attach iterator to dict +} + +/*! + Constructs a copy of the iterator \a it. +*/ + +TQGDictIterator::TQGDictIterator( const TQGDictIterator &it ) +{ + dict = it.dict; + curNode = it.curNode; + curIndex = it.curIndex; + if ( dict ) + dict->iterators->append( this ); // attach iterator to dict +} + +/*! + Assigns a copy of the iterator \a it and returns a reference to this + iterator. +*/ + +TQGDictIterator &TQGDictIterator::operator=( const TQGDictIterator &it ) +{ + if ( dict ) // detach from old dict + dict->iterators->removeRef( this ); + dict = it.dict; + curNode = it.curNode; + curIndex = it.curIndex; + if ( dict ) + dict->iterators->append( this ); // attach to new list + return *this; +} + +/*! + Destroys the iterator. +*/ + +TQGDictIterator::~TQGDictIterator() +{ + if ( dict ) // detach iterator from dict + dict->iterators->removeRef( this ); +} + + +/*! + Sets the iterator to point to the first item in the dictionary. +*/ + +TQPtrCollection::Item TQGDictIterator::toFirst() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "TQGDictIterator::toFirst: Dictionary has been deleted" ); +#endif + return 0; + } + if ( dict->count() == 0 ) { // empty dictionary + curNode = 0; + return 0; + } + register uint i = 0; + register TQBaseBucket **v = dict->vec; + while ( !(*v++) ) + i++; + curNode = dict->vec[i]; + curIndex = i; + return curNode->getData(); +} + + +/*! + Moves to the next item (postfix). +*/ + +TQPtrCollection::Item TQGDictIterator::operator()() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "TQGDictIterator::operator(): Dictionary has been deleted" ); +#endif + return 0; + } + if ( !curNode ) + return 0; + TQPtrCollection::Item d = curNode->getData(); + this->operator++(); + return d; +} + +/*! + Moves to the next item (prefix). +*/ + +TQPtrCollection::Item TQGDictIterator::operator++() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "TQGDictIterator::operator++: Dictionary has been deleted" ); +#endif + return 0; + } + if ( !curNode ) + return 0; + curNode = curNode->getNext(); + if ( !curNode ) { // no next bucket + register uint i = curIndex + 1; // look from next vec element + register TQBaseBucket **v = &dict->vec[i]; + while ( i < dict->size() && !(*v++) ) + i++; + if ( i == dict->size() ) { // nothing found + curNode = 0; + return 0; + } + curNode = dict->vec[i]; + curIndex = i; + } + return curNode->getData(); +} + +/*! + Moves \a jumps positions forward. +*/ + +TQPtrCollection::Item TQGDictIterator::operator+=( uint jumps ) +{ + while ( curNode && jumps-- ) + operator++(); + return curNode ? curNode->getData() : 0; +} |