Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/qtools/qgdict.cpp

Source at commit 1322 created 12 years 8 months ago.
By meklort, Add doxygen to utils folder
1/****************************************************************************
2**
3**
4** Implementation of QGDict and QGDictIterator classes
5**
6** Created : 920529
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qgdict.h"
39#include "qlist.h"
40#include "qstring.h"
41#include "qdatastream.h"
42#include <ctype.h>
43
44// NOT REVISED
45/*!
46 \class QGDict qgdict.h
47 \brief The QGDict class is an internal class for implementing QDict template classes.
48
49 QGDict is a strictly internal class that acts as a base class for the
50 \link collection.html collection classes\endlink QDict and QIntDict.
51
52 QGDict has some virtual functions that can be reimplemented to customize
53 the subclasses.
54 <ul>
55 <li> read() reads a collection/dictionary item from a QDataStream.
56 <li> write() writes a collection/dictionary item to a QDataStream.
57 </ul>
58 Normally, you do not have to reimplement any of these functions.
59*/
60
61static const int op_find = 0;
62static const int op_insert = 1;
63static const int op_replace = 2;
64
65
66class QGDItList : public QList<QGDictIterator>
67{
68public:
69 QGDItList() : QList<QGDictIterator>() {}
70 QGDItList( const QGDItList &list ) : QList<QGDictIterator>(list) {}
71 ~QGDItList() { clear(); }
72 QGDItList &operator=(const QGDItList &list)
73{ return (QGDItList&)QList<QGDictIterator>::operator=(list); }
74};
75
76
77/*****************************************************************************
78 Default implementation of special and virtual functions
79 *****************************************************************************/
80
81/*!
82 \internal
83 Returns the hash key for \e key, when key is a string.
84*/
85
86int QGDict::hashKeyString( const QString &key )
87{
88#if defined(CHECK_NULL)
89 if ( key.isNull() )
90qWarning( "QGDict::hashStringKey: Invalid null key" );
91#endif
92 int i;
93 register uint h=0;
94 uint g;
95 int len = key.length();
96 const QChar *p = key.unicode();
97 if ( cases ) {// case sensitive
98for ( i=0; i<len; i++ ) {
99 h = (h<<4) + p[i].cell();
100 if ( (g = h & 0xf0000000) )
101h ^= g >> 24;
102 h &= ~g;
103}
104 } else {// case insensitive
105for ( i=0; i<len; i++ ) {
106 h = (h<<4) + p[i].lower().cell();
107 if ( (g = h & 0xf0000000) )
108h ^= g >> 24;
109 h &= ~g;
110}
111 }
112 int index = h;
113 if ( index < 0 )// adjust index to table size
114index = -index;
115 return index;
116}
117
118/*!
119 \internal
120 Returns the hash key for \a key, which is a C string.
121*/
122
123int QGDict::hashKeyAscii( const char *key )
124{
125#if defined(CHECK_NULL)
126 if ( key == 0 )
127 {
128qWarning( "QGDict::hashAsciiKey: Invalid null key" );
129 return 0;
130 }
131#endif
132 register const char *k = key;
133 register uint h=0;
134 uint g;
135 if ( cases ) {// case sensitive
136while ( *k ) {
137 h = (h<<4) + *k++;
138 if ( (g = h & 0xf0000000) )
139h ^= g >> 24;
140 h &= ~g;
141}
142 } else {// case insensitive
143while ( *k ) {
144 h = (h<<4) + tolower(*k);
145 if ( (g = h & 0xf0000000) )
146h ^= g >> 24;
147 h &= ~g;
148 k++;
149}
150 }
151 int index = h;
152 if ( index < 0 )// adjust index to table size
153index = -index;
154 return index;
155}
156
157#ifndef QT_NO_DATASTREAM
158
159/*!
160 Reads a collection/dictionary item from the stream \e s and returns a
161 reference to the stream.
162
163 The default implementation sets \e item to 0.
164
165 \sa write()
166*/
167
168QDataStream& QGDict::read( QDataStream &s, QCollection::Item &item )
169{
170 item = 0;
171 return s;
172}
173
174/*!
175 Writes a collection/dictionary item to the stream \e s and returns a
176 reference to the stream.
177
178 \sa read()
179*/
180
181QDataStream& QGDict::write( QDataStream &s, QCollection::Item ) const
182{
183 return s;
184}
185#endif //QT_NO_DATASTREAM
186
187/*****************************************************************************
188 QGDict member functions
189 *****************************************************************************/
190
191/*!
192 \internal
193 Constructs a dictionary.
194*/
195
196QGDict::QGDict( uint len, KeyType kt, bool caseSensitive, bool copyKeys )
197{
198 init( len, kt, caseSensitive, copyKeys );
199}
200
201
202void QGDict::init( uint len, KeyType kt, bool caseSensitive, bool copyKeys )
203{
204 vec = new QBaseBucket *[vlen = len];// allocate hash table
205 CHECK_PTR( vec );
206 memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) );
207 numItems = 0;
208 iterators = 0;
209 // The caseSensitive and copyKey options don't make sense for
210 // all dict types.
211 switch ( (keytype = (uint)kt) ) {
212case StringKey:
213 cases = caseSensitive;
214 copyk = FALSE;
215 break;
216case AsciiKey:
217 cases = caseSensitive;
218 copyk = copyKeys;
219 break;
220default:
221 cases = FALSE;
222 copyk = FALSE;
223 break;
224 }
225}
226
227
228/*!
229 \internal
230 Constructs a copy of \e dict.
231*/
232
233QGDict::QGDict( const QGDict & dict )
234 : QCollection( dict )
235{
236 init( dict.vlen, (KeyType)dict.keytype, dict.cases, dict.copyk );
237 QGDictIterator it( dict );
238 while ( it.get() ) {// copy from other dict
239switch ( keytype ) {
240 case StringKey:
241look_string( it.getKeyString(), it.get(), op_insert );
242break;
243 case AsciiKey:
244look_ascii( it.getKeyAscii(), it.get(), op_insert );
245break;
246 case IntKey:
247look_int( it.getKeyInt(), it.get(), op_insert );
248break;
249 case PtrKey:
250look_ptr( it.getKeyPtr(), it.get(), op_insert );
251break;
252}
253++it;
254 }
255}
256
257
258/*!
259 \internal
260 Removes all items from the dictionary and destroys it.
261*/
262
263QGDict::~QGDict()
264{
265 clear();// delete everything
266 delete [] vec;
267 if ( !iterators )// no iterators for this dict
268return;
269 QGDictIterator *i = iterators->first();
270 while ( i ) {// notify all iterators that
271i->dict = 0;// this dict is deleted
272i = iterators->next();
273 }
274 delete iterators;
275}
276
277
278/*!
279 \internal
280 Assigns \e dict to this dictionary.
281*/
282
283QGDict &QGDict::operator=( const QGDict &dict )
284{
285 clear();
286 QGDictIterator it( dict );
287 while ( it.get() ) {// copy from other dict
288switch ( keytype ) {
289 case StringKey:
290look_string( it.getKeyString(), it.get(), op_insert );
291break;
292 case AsciiKey:
293look_ascii( it.getKeyAscii(), it.get(), op_insert );
294break;
295 case IntKey:
296look_int( it.getKeyInt(), it.get(), op_insert );
297break;
298 case PtrKey:
299look_ptr( it.getKeyPtr(), it.get(), op_insert );
300break;
301}
302++it;
303 }
304 return *this;
305}
306
307
308/*! \fn QCollection::Item QGDictIterator::get() const
309
310 \internal
311*/
312
313
314/*! \fn QString QGDictIterator::getKeyString() const
315
316 \internal
317*/
318
319
320/*! \fn const char * QGDictIterator::getKeyAscii() const
321
322 \internal
323*/
324
325
326/*! \fn void * QGDictIterator::getKeyPtr() const
327
328 \internal
329*/
330
331
332/*! \fn long QGDictIterator::getKeyInt() const
333
334 \internal
335*/
336
337
338/*!
339 \fn uint QGDict::count() const
340 \internal
341 Returns the number of items in the dictionary.
342*/
343
344/*!
345 \fn uint QGDict::size() const
346 \internal
347 Returns the size of the hash array.
348*/
349
350
351/*!
352 \internal
353 The do-it-all function; op is one of op_find, op_insert, op_replace
354*/
355
356QCollection::Item QGDict::look_string( const QString &key, QCollection::Item d, int op )
357{
358 QStringBucket *n;
359 intindex = hashKeyString(key) % vlen;
360 if ( op == op_find ) {// find
361if ( cases ) {
362 for ( n=(QStringBucket*)vec[index]; n;
363 n=(QStringBucket*)n->getNext() ) {
364if ( key == n->getKey() )
365 return n->getData();// item found
366 }
367} else {
368 QString k = key.lower();
369 for ( n=(QStringBucket*)vec[index]; n;
370 n=(QStringBucket*)n->getNext() ) {
371if ( k == n->getKey().lower() )
372 return n->getData();// item found
373 }
374}
375return 0;// not found
376 }
377 if ( op == op_replace ) {// replace
378if ( vec[index] != 0 )// maybe something there
379 remove_string( key );
380 }
381 // op_insert or op_replace
382 n = new QStringBucket(key,newItem(d),vec[index]);
383 CHECK_PTR( n );
384#if defined(CHECK_NULL)
385 if ( n->getData() == 0 )
386qWarning( "QDict: Cannot insert null item" );
387#endif
388 vec[index] = n;
389 numItems++;
390 return n->getData();
391}
392
393
394/*! \internal */
395
396QCollection::Item QGDict::look_ascii( const char *key, QCollection::Item d, int op )
397{
398 QAsciiBucket *n;
399 intindex = hashKeyAscii(key) % vlen;
400 if ( op == op_find ) {// find
401if ( cases ) {
402 for ( n=(QAsciiBucket*)vec[index]; n;
403 n=(QAsciiBucket*)n->getNext() ) {
404if ( qstrcmp(n->getKey(),key) == 0 )
405 return n->getData();// item found
406 }
407} else {
408 for ( n=(QAsciiBucket*)vec[index]; n;
409 n=(QAsciiBucket*)n->getNext() ) {
410if ( qstricmp(n->getKey(),key) == 0 )
411 return n->getData();// item found
412 }
413}
414return 0;// not found
415 }
416 if ( op == op_replace ) {// replace
417if ( vec[index] != 0 )// maybe something there
418 remove_ascii( key );
419 }
420 // op_insert or op_replace
421 n = new QAsciiBucket(copyk ? qstrdup(key) : key,newItem(d),vec[index]);
422 CHECK_PTR( n );
423#if defined(CHECK_NULL)
424 if ( n->getData() == 0 )
425qWarning( "QAsciiDict: Cannot insert null item" );
426#endif
427 vec[index] = n;
428 numItems++;
429 return n->getData();
430}
431
432
433/*! \internal */
434
435QCollection::Item QGDict::look_int( long key, QCollection::Item d, int op )
436{
437 QIntBucket *n;
438 int index = (int)((ulong)key % vlen);// simple hash
439 if ( op == op_find ) {// find
440for ( n=(QIntBucket*)vec[index]; n;
441 n=(QIntBucket*)n->getNext() ) {
442 if ( n->getKey() == key )
443return n->getData();// item found
444}
445return 0;// not found
446 }
447 if ( op == op_replace ) {// replace
448if ( vec[index] != 0 )// maybe something there
449 remove_int( key );
450 }
451 // op_insert or op_replace
452 n = new QIntBucket(key,newItem(d),vec[index]);
453 CHECK_PTR( n );
454#if defined(CHECK_NULL)
455 if ( n->getData() == 0 )
456qWarning( "QIntDict: Cannot insert null item" );
457#endif
458 vec[index] = n;
459 numItems++;
460 return n->getData();
461}
462
463
464/*! \internal */
465
466QCollection::Item QGDict::look_ptr( void *key, QCollection::Item d, int op )
467{
468 QPtrBucket *n;
469 int index = (int)((ulong)key % vlen);// simple hash
470 if ( op == op_find ) {// find
471for ( n=(QPtrBucket*)vec[index]; n;
472 n=(QPtrBucket*)n->getNext() ) {
473 if ( n->getKey() == key )
474return n->getData();// item found
475}
476return 0;// not found
477 }
478 if ( op == op_replace ) {// replace
479if ( vec[index] != 0 )// maybe something there
480 remove_ptr( key );
481 }
482 // op_insert or op_replace
483 n = new QPtrBucket(key,newItem(d),vec[index]);
484 CHECK_PTR( n );
485#if defined(CHECK_NULL)
486 if ( n->getData() == 0 )
487qWarning( "QPtrDict: Cannot insert null item" );
488#endif
489 vec[index] = n;
490 numItems++;
491 return n->getData();
492}
493
494
495/*!
496 \internal
497 Changes the size of the hashtable.
498 The contents of the dictionary are preserved,
499 but all iterators on the dictionary become invalid.
500*/
501void QGDict::resize( uint newsize )
502{
503 // Save old information
504 QBaseBucket **old_vec = vec;
505 uint old_vlen = vlen;
506 bool old_copyk = copyk;
507
508 vec = new QBaseBucket *[vlen = newsize];
509 CHECK_PTR( vec );
510 memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) );
511 numItems = 0;
512 copyk = FALSE;
513
514 // Reinsert every item from vec, deleting vec as we go
515 for ( uint index = 0; index < old_vlen; index++ ) {
516switch ( keytype ) {
517 case StringKey:
518{
519 QStringBucket *n=(QStringBucket *)old_vec[index];
520 while ( n ) {
521look_string( n->getKey(), n->getData(), op_insert );
522QStringBucket *t=(QStringBucket *)n->getNext();
523delete n;
524n = t;
525 }
526}
527break;
528 case AsciiKey:
529{
530 QAsciiBucket *n=(QAsciiBucket *)old_vec[index];
531 while ( n ) {
532look_ascii( n->getKey(), n->getData(), op_insert );
533QAsciiBucket *t=(QAsciiBucket *)n->getNext();
534delete n;
535n = t;
536 }
537}
538break;
539 case IntKey:
540{
541 QIntBucket *n=(QIntBucket *)old_vec[index];
542 while ( n ) {
543look_int( n->getKey(), n->getData(), op_insert );
544QIntBucket *t=(QIntBucket *)n->getNext();
545delete n;
546n = t;
547 }
548}
549break;
550 case PtrKey:
551{
552 QPtrBucket *n=(QPtrBucket *)old_vec[index];
553 while ( n ) {
554look_ptr( n->getKey(), n->getData(), op_insert );
555QPtrBucket *t=(QPtrBucket *)n->getNext();
556delete n;
557n = t;
558 }
559}
560break;
561}
562 }
563 delete [] old_vec;
564
565 // Restore state
566 copyk = old_copyk;
567
568 // Invalidate all iterators, since order is lost
569 if ( iterators && iterators->count() ) {
570QGDictIterator *i = iterators->first();
571while ( i ) {
572 i->toFirst();
573 i = iterators->next();
574}
575 }
576}
577
578/*!
579 \internal
580 Unlinks the bucket with the specified key (and specified data pointer,
581 if it is set).
582*/
583
584void QGDict::unlink_common( int index, QBaseBucket *node, QBaseBucket *prev )
585{
586 if ( iterators && iterators->count() ) {// update iterators
587QGDictIterator *i = iterators->first();
588while ( i ) {// invalidate all iterators
589 if ( i->curNode == node )// referring to pending node
590i->operator++();
591 i = iterators->next();
592}
593 }
594 if ( prev )// unlink node
595prev->setNext( node->getNext() );
596 else
597vec[index] = node->getNext();
598 numItems--;
599}
600
601QStringBucket *QGDict::unlink_string( const QString &key, QCollection::Item d )
602{
603 if ( numItems == 0 )// nothing in dictionary
604return 0;
605 QStringBucket *n;
606 QStringBucket *prev = 0;
607 int index = hashKeyString(key) % vlen;
608 if ( cases ) {
609for ( n=(QStringBucket*)vec[index]; n;
610 n=(QStringBucket*)n->getNext() ) {
611 bool found = (key == n->getKey());
612 if ( found && d )
613found = (n->getData() == d);
614 if ( found ) {
615unlink_common(index,n,prev);
616return n;
617 }
618 prev = n;
619}
620 } else {
621QString k = key.lower();
622for ( n=(QStringBucket*)vec[index]; n;
623 n=(QStringBucket*)n->getNext() ) {
624 bool found = (k == n->getKey().lower());
625 if ( found && d )
626found = (n->getData() == d);
627 if ( found ) {
628unlink_common(index,n,prev);
629return n;
630 }
631 prev = n;
632}
633 }
634 return 0;
635}
636
637QAsciiBucket *QGDict::unlink_ascii( const char *key, QCollection::Item d )
638{
639 if ( numItems == 0 )// nothing in dictionary
640return 0;
641 QAsciiBucket *n;
642 QAsciiBucket *prev = 0;
643 int index = hashKeyAscii(key) % vlen;
644 for ( n=(QAsciiBucket *)vec[index]; n; n=(QAsciiBucket *)n->getNext() ) {
645bool found = (cases ? qstrcmp(n->getKey(),key)
646 : qstricmp(n->getKey(),key)) == 0;
647if ( found && d )
648 found = (n->getData() == d);
649if ( found ) {
650 unlink_common(index,n,prev);
651 return n;
652}
653prev = n;
654 }
655 return 0;
656}
657
658QIntBucket *QGDict::unlink_int( long key, QCollection::Item d )
659{
660 if ( numItems == 0 )// nothing in dictionary
661return 0;
662 QIntBucket *n;
663 QIntBucket *prev = 0;
664 int index = (int)((ulong)key % vlen);
665 for ( n=(QIntBucket *)vec[index]; n; n=(QIntBucket *)n->getNext() ) {
666bool found = (n->getKey() == key);
667if ( found && d )
668 found = (n->getData() == d);
669if ( found ) {
670 unlink_common(index,n,prev);
671 return n;
672}
673prev = n;
674 }
675 return 0;
676}
677
678QPtrBucket *QGDict::unlink_ptr( void *key, QCollection::Item d )
679{
680 if ( numItems == 0 )// nothing in dictionary
681return 0;
682 QPtrBucket *n;
683 QPtrBucket *prev = 0;
684 int index = (int)((ulong)key % vlen);
685 for ( n=(QPtrBucket *)vec[index]; n; n=(QPtrBucket *)n->getNext() ) {
686bool found = (n->getKey() == key);
687if ( found && d )
688 found = (n->getData() == d);
689if ( found ) {
690 unlink_common(index,n,prev);
691 return n;
692}
693prev = n;
694 }
695 return 0;
696}
697
698
699/*!
700 \internal
701 Removes the item with the specified key. If item is non-null,
702 the remove will match the \a item as well (used to remove an
703 item when several items have the same key).
704*/
705
706bool QGDict::remove_string( const QString &key, QCollection::Item item )
707{
708 QStringBucket *n = unlink_string( key, item );
709 if ( n ) {
710deleteItem( n->getData() );
711delete n;
712return TRUE;
713 } else {
714return FALSE;
715 }
716}
717
718
719/*! \internal */
720
721bool QGDict::remove_ascii( const char *key, QCollection::Item item )
722{
723 QAsciiBucket *n = unlink_ascii( key, item );
724 if ( n ) {
725if ( copyk )
726 delete [] (char *)n->getKey();
727deleteItem( n->getData() );
728delete n;
729 }
730 return n != 0;
731}
732
733
734/*! \internal */
735
736bool QGDict::remove_int( long key, QCollection::Item item )
737{
738 QIntBucket *n = unlink_int( key, item );
739 if ( n ) {
740deleteItem( n->getData() );
741delete n;
742 }
743 return n != 0;
744}
745
746
747/*! \internal */
748
749bool QGDict::remove_ptr( void *key, QCollection::Item item )
750{
751 QPtrBucket *n = unlink_ptr( key, item );
752 if ( n ) {
753deleteItem( n->getData() );
754delete n;
755 }
756 return n != 0;
757}
758
759
760/*! \internal */
761
762QCollection::Item QGDict::take_string( const QString &key )
763{
764 QStringBucket *n = unlink_string( key );
765 Item d;
766 if ( n ) {
767d = n->getData();
768delete n;
769 } else {
770d = 0;
771 }
772 return d;
773}
774
775
776/*! \internal */
777
778QCollection::Item QGDict::take_ascii( const char *key )
779{
780 QAsciiBucket *n = unlink_ascii( key );
781 Item d;
782 if ( n ) {
783if ( copyk )
784 delete [] (char *)n->getKey();
785d = n->getData();
786delete n;
787 } else {
788d = 0;
789 }
790 return d;
791}
792
793
794/*! \internal */
795
796QCollection::Item QGDict::take_int( long key )
797{
798 QIntBucket *n = unlink_int( key );
799 Item d;
800 if ( n ) {
801d = n->getData();
802delete n;
803 } else {
804d = 0;
805 }
806 return d;
807}
808
809
810/*! \internal */
811
812QCollection::Item QGDict::take_ptr( void *key )
813{
814 QPtrBucket *n = unlink_ptr( key );
815 Item d;
816 if ( n ) {
817d = n->getData();
818delete n;
819 } else {
820d = 0;
821 }
822 return d;
823}
824
825
826/*!
827 \internal
828 Removes all items from the dictionary.
829*/
830
831void QGDict::clear()
832{
833 if ( !numItems )
834return;
835 numItems = 0;// disable remove() function
836 for ( uint j=0; j<vlen; j++ ) {// destroy hash table
837if ( vec[j] ) {
838 switch ( keytype ) {
839case StringKey:
840 {
841QStringBucket *n=(QStringBucket *)vec[j];
842while ( n ) {
843 QStringBucket *next = (QStringBucket*)n->getNext();
844 deleteItem( n->getData() );
845 delete n;
846 n = next;
847}
848 }
849 break;
850case AsciiKey:
851 {
852QAsciiBucket *n=(QAsciiBucket *)vec[j];
853while ( n ) {
854 QAsciiBucket *next = (QAsciiBucket*)n->getNext();
855 if ( copyk )
856delete [] (char *)n->getKey();
857 deleteItem( n->getData() );
858 delete n;
859 n = next;
860}
861 }
862 break;
863case IntKey:
864 {
865QIntBucket *n=(QIntBucket *)vec[j];
866while ( n ) {
867 QIntBucket *next = (QIntBucket*)n->getNext();
868 deleteItem( n->getData() );
869 delete n;
870 n = next;
871}
872 }
873 break;
874case PtrKey:
875 {
876QPtrBucket *n=(QPtrBucket *)vec[j];
877while ( n ) {
878 QPtrBucket *next = (QPtrBucket*)n->getNext();
879 deleteItem( n->getData() );
880 delete n;
881 n = next;
882}
883 }
884 break;
885 }
886 vec[j] = 0;// detach list of buckets
887}
888 }
889 if ( iterators && iterators->count() ) {// invalidate all iterators
890QGDictIterator *i = iterators->first();
891while ( i ) {
892 i->curNode = 0;
893 i = iterators->next();
894}
895 }
896}
897
898
899/*!
900 \internal
901 Outputs debug statistics.
902*/
903
904void QGDict::statistics() const
905{
906#if defined(DEBUG)
907 QString line;
908 line.fill( '-', 60 );
909 double real, ideal;
910 qDebug( "%s",line.ascii() );
911 qDebug( "DICTIONARY STATISTICS:" );
912 if ( count() == 0 ) {
913qDebug( "Empty!" );
914qDebug( "%s", line.ascii() );
915return;
916 }
917 real = 0.0;
918 ideal = (float)count()/(2.0*size())*(count()+2.0*size()-1);
919 uint i = 0;
920 while ( i<size() ) {
921QBaseBucket *n = vec[i];
922int b = 0;
923while ( n ) {// count number of buckets
924 b++;
925 n = n->getNext();
926}
927real = real + (double)b * ((double)b+1.0)/2.0;
928char buf[80], *pbuf;
929if ( b > 78 )
930 b = 78;
931pbuf = buf;
932while ( b-- )
933 *pbuf++ = '*';
934*pbuf = '\0';
935qDebug( "%s", buf );
936i++;
937 }
938 qDebug( "Array size = %d", size() );
939 qDebug( "# items = %d", count() );
940 qDebug( "Real dist = %g", real );
941 qDebug( "Rand dist = %g", ideal );
942 qDebug( "Real/Rand = %g", real/ideal );
943 qDebug( "%s",line.ascii() );
944#endif // DEBUG
945}
946
947
948/*****************************************************************************
949 QGDict stream functions
950 *****************************************************************************/
951#ifndef QT_NO_DATASTREAM
952QDataStream &operator>>( QDataStream &s, QGDict &dict )
953{
954 return dict.read( s );
955}
956
957QDataStream &operator<<( QDataStream &s, const QGDict &dict )
958{
959 return dict.write( s );
960}
961
962#if defined(_CC_DEC_) && defined(__alpha) && (__DECCXX_VER >= 50190001)
963#pragma message disable narrowptr
964#endif
965
966/*!
967 \internal
968 Reads a dictionary from the stream \e s.
969*/
970
971QDataStream &QGDict::read( QDataStream &s )
972{
973 uint num;
974 s >> num;// read number of items
975 clear();// clear dict
976 while ( num-- ) {// read all items
977Item d;
978switch ( keytype ) {
979 case StringKey:
980{
981 QString k;
982 s >> k;
983 read( s, d );
984 look_string( k, d, op_insert );
985}
986break;
987 case AsciiKey:
988{
989 char *k;
990 s >> k;
991 read( s, d );
992 look_ascii( k, d, op_insert );
993 if ( copyk )
994delete [] k;
995}
996break;
997 case IntKey:
998{
999 Q_UINT32 k;
1000 s >> k;
1001 read( s, d );
1002 look_int( k, d, op_insert );
1003}
1004break;
1005 case PtrKey:
1006{
1007 Q_UINT32 k;
1008 s >> k;
1009 read( s, d );
1010 // ### cannot insert 0 - this renders the thing
1011 // useless since all pointers are written as 0,
1012 // but hey, serializing pointers? can it be done
1013 // at all, ever?
1014 if ( k )
1015look_ptr( (void *)k, d, op_insert );
1016}
1017break;
1018}
1019 }
1020 return s;
1021}
1022
1023/*!
1024 \internal
1025 Writes the dictionary to the stream \e s.
1026*/
1027
1028QDataStream& QGDict::write( QDataStream &s ) const
1029{
1030 s << count();// write number of items
1031 uint i = 0;
1032 while ( i<size() ) {
1033QBaseBucket *n = vec[i];
1034while ( n ) {// write all buckets
1035 switch ( keytype ) {
1036case StringKey:
1037 s << ((QStringBucket*)n)->getKey();
1038 break;
1039case AsciiKey:
1040 s << ((QAsciiBucket*)n)->getKey();
1041 break;
1042case IntKey:
1043 s << (Q_UINT32)((QIntBucket*)n)->getKey();
1044 break;
1045case PtrKey:
1046 s << (Q_UINT32)0; // ### cannot serialize a pointer
1047 break;
1048 }
1049 write( s, n->getData() );// write data
1050 n = n->getNext();
1051}
1052i++;
1053 }
1054 return s;
1055}
1056#endif //QT_NO_DATASTREAM
1057
1058/*****************************************************************************
1059 QGDictIterator member functions
1060 *****************************************************************************/
1061
1062/*!
1063 \class QGDictIterator qgdict.h
1064 \brief An internal class for implementing QDictIterator and QIntDictIterator.
1065
1066 QGDictIterator is a strictly internal class that does the heavy work for
1067 QDictIterator and QIntDictIterator.
1068*/
1069
1070/*!
1071 \internal
1072 Constructs an iterator that operates on the dictionary \e d.
1073*/
1074
1075QGDictIterator::QGDictIterator( const QGDict &d )
1076{
1077 dict = (QGDict *)&d;// get reference to dict
1078 toFirst();// set to first noe
1079 if ( !dict->iterators ) {
1080dict->iterators = new QGDItList;// create iterator list
1081CHECK_PTR( dict->iterators );
1082 }
1083 dict->iterators->append( this );// attach iterator to dict
1084}
1085
1086/*!
1087 \internal
1088 Constructs a copy of the iterator \e it.
1089*/
1090
1091QGDictIterator::QGDictIterator( const QGDictIterator &it )
1092{
1093 dict = it.dict;
1094 curNode = it.curNode;
1095 curIndex = it.curIndex;
1096 if ( dict )
1097dict->iterators->append( this );// attach iterator to dict
1098}
1099
1100/*!
1101 \internal
1102 Assigns a copy of the iterator \e it and returns a reference to this
1103 iterator.
1104*/
1105
1106QGDictIterator &QGDictIterator::operator=( const QGDictIterator &it )
1107{
1108 if ( dict )// detach from old dict
1109dict->iterators->removeRef( this );
1110 dict = it.dict;
1111 curNode = it.curNode;
1112 curIndex = it.curIndex;
1113 if ( dict )
1114dict->iterators->append( this );// attach to new list
1115 return *this;
1116}
1117
1118/*!
1119 \internal
1120 Destroys the iterator.
1121*/
1122
1123QGDictIterator::~QGDictIterator()
1124{
1125 if ( dict )// detach iterator from dict
1126dict->iterators->removeRef( this );
1127}
1128
1129
1130/*!
1131 \internal
1132 Sets the iterator to point to the first item in the dictionary.
1133*/
1134
1135QCollection::Item QGDictIterator::toFirst()
1136{
1137 if ( !dict ) {
1138#if defined(CHECK_NULL)
1139qWarning( "QGDictIterator::toFirst: Dictionary has been deleted" );
1140#endif
1141return 0;
1142 }
1143 if ( dict->count() == 0 ) {// empty dictionary
1144curNode = 0;
1145return 0;
1146 }
1147 register uint i = 0;
1148 register QBaseBucket **v = dict->vec;
1149 while ( !(*v++) )
1150i++;
1151 curNode = dict->vec[i];
1152 curIndex = i;
1153 return curNode->getData();
1154}
1155
1156
1157/*!
1158 \internal
1159 Moves to the next item (postfix).
1160*/
1161
1162QCollection::Item QGDictIterator::operator()()
1163{
1164 if ( !dict ) {
1165#if defined(CHECK_NULL)
1166qWarning( "QGDictIterator::operator(): Dictionary has been deleted" );
1167#endif
1168return 0;
1169 }
1170 if ( !curNode )
1171return 0;
1172 QCollection::Item d = curNode->getData();
1173 this->operator++();
1174 return d;
1175}
1176
1177/*!
1178 \internal
1179 Moves to the next item (prefix).
1180*/
1181
1182QCollection::Item QGDictIterator::operator++()
1183{
1184 if ( !dict ) {
1185#if defined(CHECK_NULL)
1186qWarning( "QGDictIterator::operator++: Dictionary has been deleted" );
1187#endif
1188return 0;
1189 }
1190 if ( !curNode )
1191return 0;
1192 curNode = curNode->getNext();
1193 if ( !curNode ) {// no next bucket
1194register uint i = curIndex + 1;// look from next vec element
1195register QBaseBucket **v = &dict->vec[i];
1196while ( i < dict->size() && !(*v++) )
1197 i++;
1198if ( i == dict->size() ) {// nothing found
1199 curNode = 0;
1200 return 0;
1201}
1202curNode = dict->vec[i];
1203curIndex = i;
1204 }
1205 return curNode->getData();
1206}
1207
1208/*!
1209 \internal
1210 Moves \e jumps positions forward.
1211*/
1212
1213QCollection::Item QGDictIterator::operator+=( uint jumps )
1214{
1215 while ( curNode && jumps-- )
1216operator++();
1217 return curNode ? curNode->getData() : 0;
1218}
1219

Archive Download this file

Revision: 1322