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