00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "qglist.h"
00039 #include "qgvector.h"
00040 #include "qdatastream.h"
00041 #include "qvaluelist.h"
00042
00092
00093
00094
00095 class QGListIteratorList
00096 {
00097 public:
00098 QGListIteratorList()
00099 : list(0), iterator(0) {
00100 }
00101 ~QGListIteratorList() {
00102 notifyClear( TRUE );
00103 delete list;
00104 }
00105
00106 void add( QGListIterator* i ) {
00107 if ( !iterator ) {
00108 iterator = i;
00109 } else if ( list ) {
00110 list->push_front( i );
00111 } else {
00112 list = new QValueList<QGListIterator*>;
00113 list->push_front( i );
00114 }
00115 }
00116
00117 void remove( QGListIterator* i ) {
00118 if ( iterator == i ) {
00119 iterator = 0;
00120 } else if ( list ) {
00121 list->remove( i );
00122 if ( list->isEmpty() ) {
00123 delete list;
00124 list = 0;
00125 }
00126 }
00127 }
00128
00129 void notifyClear( bool zeroList ) {
00130 if ( iterator ) {
00131 if ( zeroList )
00132 iterator->list = 0;
00133 iterator->curNode = 0;
00134 }
00135 if ( list ) {
00136 for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) {
00137 if ( zeroList )
00138 (*i)->list = 0;
00139 (*i)->curNode = 0;
00140 }
00141 }
00142 }
00143
00144 void notifyRemove( QLNode* n, QLNode* curNode ) {
00145 if ( iterator ) {
00146 if ( iterator->curNode == n )
00147 iterator->curNode = curNode;
00148 }
00149 if ( list ) {
00150 for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) {
00151 if ( (*i)->curNode == n )
00152 (*i)->curNode = curNode;
00153 }
00154 }
00155 }
00156
00157 private:
00158 QValueList<QGListIterator*>* list;
00159 QGListIterator* iterator;
00160 };
00161
00162
00163
00164
00165
00166
00167
00173 int QGList::compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 )
00174 {
00175 return item1 != item2;
00176 }
00177
00178 #ifndef QT_NO_DATASTREAM
00179
00189 QDataStream &QGList::read( QDataStream &s, QPtrCollection::Item &item )
00190 {
00191 item = 0;
00192 return s;
00193 }
00194
00205 QDataStream &QGList::write( QDataStream &s, QPtrCollection::Item ) const
00206 {
00207 return s;
00208 }
00209 #endif // QT_NO_DATASTREAM
00210
00211
00212
00213
00214
00219 QGList::QGList()
00220 {
00221 firstNode = lastNode = curNode = 0;
00222 numNodes = 0;
00223 curIndex = -1;
00224 iterators = 0;
00225 }
00226
00231 QGList::QGList( const QGList & list )
00232 : QPtrCollection( list )
00233 {
00234 firstNode = lastNode = curNode = 0;
00235 numNodes = 0;
00236 curIndex = -1;
00237 iterators = 0;
00238 QLNode *n = list.firstNode;
00239 while ( n ) {
00240 append( n->data );
00241 n = n->next;
00242 }
00243 }
00244
00249 QGList::~QGList()
00250 {
00251 clear();
00252 delete iterators;
00253
00254
00255
00256
00257 iterators = 0;
00258 }
00259
00260
00265 QGList& QGList::operator=( const QGList &list )
00266 {
00267 if ( &list == this )
00268 return *this;
00269
00270 clear();
00271 if ( list.count() > 0 ) {
00272 QLNode *n = list.firstNode;
00273 while ( n ) {
00274 append( n->data );
00275 n = n->next;
00276 }
00277 curNode = firstNode;
00278 curIndex = 0;
00279 }
00280 return *this;
00281 }
00282
00288 bool QGList::operator==( const QGList &list ) const
00289 {
00290 if ( count() != list.count() )
00291 return FALSE;
00292
00293 if ( count() == 0 )
00294 return TRUE;
00295
00296 QLNode *n1 = firstNode;
00297 QLNode *n2 = list.firstNode;
00298 while ( n1 && n2 ) {
00299
00300 if ( ( (QGList*)this )->compareItems( n1->data, n2->data ) != 0 )
00301 return FALSE;
00302 n1 = n1->next;
00303 n2 = n2->next;
00304 }
00305
00306 return TRUE;
00307 }
00308
00320 QLNode *QGList::locate( uint index )
00321 {
00322 if ( index == (uint)curIndex )
00323 return curNode;
00324 if ( !curNode && firstNode ) {
00325 curNode = firstNode;
00326 curIndex = 0;
00327 }
00328 register QLNode *node;
00329 int distance = index - curIndex;
00330 bool forward;
00331
00332 if ( index >= numNodes )
00333 return 0;
00334
00335 if ( distance < 0 )
00336 distance = -distance;
00337 if ( (uint)distance < index && (uint)distance < numNodes - index ) {
00338 node = curNode;
00339 forward = index > (uint)curIndex;
00340 } else if ( index < numNodes - index ) {
00341 node = firstNode;
00342 distance = index;
00343 forward = TRUE;
00344 } else {
00345 node = lastNode;
00346 distance = numNodes - index - 1;
00347 if ( distance < 0 )
00348 distance = 0;
00349 forward = FALSE;
00350 }
00351 if ( forward ) {
00352 while ( distance-- )
00353 node = node->next;
00354 } else {
00355 while ( distance-- )
00356 node = node->prev;
00357 }
00358 curIndex = index;
00359 return curNode = node;
00360 }
00361
00362
00367 void QGList::inSort( QPtrCollection::Item d )
00368 {
00369 int index = 0;
00370 register QLNode *n = firstNode;
00371 while ( n && compareItems(n->data,d) < 0 ){
00372 n = n->next;
00373 index++;
00374 }
00375 insertAt( index, d );
00376 }
00377
00378
00383 void QGList::prepend( QPtrCollection::Item d )
00384 {
00385 register QLNode *n = new QLNode( newItem(d) );
00386 Q_CHECK_PTR( n );
00387 n->prev = 0;
00388 if ( (n->next = firstNode) )
00389 firstNode->prev = n;
00390 else
00391 lastNode = n;
00392 firstNode = curNode = n;
00393 numNodes++;
00394 curIndex = 0;
00395 }
00396
00397
00402 void QGList::append( QPtrCollection::Item d )
00403 {
00404 register QLNode *n = new QLNode( newItem(d) );
00405 Q_CHECK_PTR( n );
00406 n->next = 0;
00407 if ( (n->prev = lastNode) )
00408 lastNode->next = n;
00409 else
00410 firstNode = n;
00411 lastNode = curNode = n;
00412 curIndex = numNodes;
00413 numNodes++;
00414 }
00415
00416
00421 bool QGList::insertAt( uint index, QPtrCollection::Item d )
00422 {
00423 if ( index == 0 ) {
00424 prepend( d );
00425 return TRUE;
00426 } else if ( index == numNodes ) {
00427 append( d );
00428 return TRUE;
00429 }
00430 QLNode *nextNode = locate( index );
00431 if ( !nextNode )
00432 return FALSE;
00433 QLNode *prevNode = nextNode->prev;
00434 register QLNode *n = new QLNode( newItem(d) );
00435 Q_CHECK_PTR( n );
00436 nextNode->prev = n;
00437 prevNode->next = n;
00438 n->prev = prevNode;
00439 n->next = nextNode;
00440 curNode = n;
00441 numNodes++;
00442 return TRUE;
00443 }
00444
00445
00450 void QGList::relinkNode( QLNode *n )
00451 {
00452 if ( n == firstNode )
00453 return;
00454 curNode = n;
00455 unlink();
00456 n->prev = 0;
00457 if ( (n->next = firstNode) )
00458 firstNode->prev = n;
00459 else
00460 lastNode = n;
00461 firstNode = curNode = n;
00462 numNodes++;
00463 curIndex = 0;
00464 }
00465
00466
00471 QLNode *QGList::unlink()
00472 {
00473 if ( curNode == 0 )
00474 return 0;
00475 register QLNode *n = curNode;
00476 if ( n == firstNode ) {
00477 if ( (firstNode = n->next) ) {
00478 firstNode->prev = 0;
00479 } else {
00480 lastNode = curNode = 0;
00481 curIndex = -1;
00482 }
00483 } else {
00484 if ( n == lastNode ) {
00485 lastNode = n->prev;
00486 lastNode->next = 0;
00487 } else {
00488 n->prev->next = n->next;
00489 n->next->prev = n->prev;
00490 }
00491 }
00492
00493 if ( n->next ) {
00494 curNode = n->next;
00495 } else if ( n->prev ) {
00496 curNode = n->prev;
00497 curIndex--;
00498 }
00499
00500 if ( iterators )
00501 iterators->notifyRemove( n, curNode );
00502 numNodes--;
00503 return n;
00504 }
00505
00506
00511 bool QGList::removeNode( QLNode *n )
00512 {
00513 #if defined(QT_CHECK_NULL)
00514 if ( n == 0 || (n->prev && n->prev->next != n) ||
00515 (n->next && n->next->prev != n) ) {
00516 qWarning( "QGList::removeNode: Corrupted node" );
00517 return FALSE;
00518 }
00519 #endif
00520 curNode = n;
00521 unlink();
00522 deleteItem( n->data );
00523 delete n;
00524 curNode = firstNode;
00525 curIndex = curNode ? 0 : -1;
00526 return TRUE;
00527 }
00528
00535 bool QGList::remove( QPtrCollection::Item d )
00536 {
00537 if ( d && find(d) == -1 )
00538 return FALSE;
00539 QLNode *n = unlink();
00540 if ( !n )
00541 return FALSE;
00542 deleteItem( n->data );
00543 delete n;
00544 return TRUE;
00545 }
00546
00551 bool QGList::removeRef( QPtrCollection::Item d )
00552 {
00553 if ( findRef(d) == -1 )
00554 return FALSE;
00555 QLNode *n = unlink();
00556 if ( !n )
00557 return FALSE;
00558 deleteItem( n->data );
00559 delete n;
00560 return TRUE;
00561 }
00562
00579 bool QGList::removeAt( uint index )
00580 {
00581 if ( !locate(index) )
00582 return FALSE;
00583 QLNode *n = unlink();
00584 if ( !n )
00585 return FALSE;
00586 deleteItem( n->data );
00587 delete n;
00588 return TRUE;
00589 }
00590
00591
00595 bool QGList::replaceAt( uint index, QPtrCollection::Item d )
00596 {
00597 QLNode *n = locate( index );
00598 if ( !n )
00599 return FALSE;
00600 if ( n->data != d ) {
00601 deleteItem( n->data );
00602 n->data = newItem( d );
00603 }
00604 return TRUE;
00605 }
00606
00607
00608
00613 QPtrCollection::Item QGList::takeNode( QLNode *n )
00614 {
00615 #if defined(QT_CHECK_NULL)
00616 if ( n == 0 || (n->prev && n->prev->next != n) ||
00617 (n->next && n->next->prev != n) ) {
00618 qWarning( "QGList::takeNode: Corrupted node" );
00619 return 0;
00620 }
00621 #endif
00622 curNode = n;
00623 unlink();
00624 Item d = n->data;
00625 delete n;
00626 curNode = firstNode;
00627 curIndex = curNode ? 0 : -1;
00628 return d;
00629 }
00630
00635 QPtrCollection::Item QGList::take()
00636 {
00637 QLNode *n = unlink();
00638 Item d = n ? n->data : 0;
00639 delete n;
00640 return d;
00641 }
00642
00647 QPtrCollection::Item QGList::takeAt( uint index )
00648 {
00649 if ( !locate(index) )
00650 return 0;
00651 QLNode *n = unlink();
00652 Item d = n ? n->data : 0;
00653 delete n;
00654 return d;
00655 }
00656
00661 QPtrCollection::Item QGList::takeFirst()
00662 {
00663 first();
00664 QLNode *n = unlink();
00665 Item d = n ? n->data : 0;
00666 delete n;
00667 return d;
00668 }
00669
00674 QPtrCollection::Item QGList::takeLast()
00675 {
00676 last();
00677 QLNode *n = unlink();
00678 Item d = n ? n->data : 0;
00679 delete n;
00680 return d;
00681 }
00682
00683
00688 void QGList::clear()
00689 {
00690 register QLNode *n = firstNode;
00691
00692 firstNode = lastNode = curNode = 0;
00693 numNodes = 0;
00694 curIndex = -1;
00695
00696 if ( iterators )
00697 iterators->notifyClear( FALSE );
00698
00699 QLNode *prevNode;
00700 while ( n ) {
00701 deleteItem( n->data );
00702 prevNode = n;
00703 n = n->next;
00704 delete prevNode;
00705 }
00706 }
00707
00708
00714 int QGList::findRef( QPtrCollection::Item d, bool fromStart )
00715 {
00716 register QLNode *n;
00717 int index;
00718 if ( fromStart ) {
00719 n = firstNode;
00720 index = 0;
00721 } else {
00722 n = curNode;
00723 index = curIndex;
00724 }
00725 while ( n && n->data != d ) {
00726 n = n->next;
00727 index++;
00728 }
00729 curNode = n;
00730 curIndex = n ? index : -1;
00731 return curIndex;
00732 }
00733
00740 int QGList::find( QPtrCollection::Item d, bool fromStart )
00741 {
00742 register QLNode *n;
00743 int index;
00744 if ( fromStart ) {
00745 n = firstNode;
00746 index = 0;
00747 } else {
00748 n = curNode;
00749 index = curIndex;
00750 }
00751 while ( n && compareItems(n->data,d) ){
00752 n = n->next;
00753 index++;
00754 }
00755 curNode = n;
00756 curIndex = n ? index : -1;
00757 return curIndex;
00758 }
00759
00760
00765 uint QGList::containsRef( QPtrCollection::Item d ) const
00766 {
00767 register QLNode *n = firstNode;
00768 uint count = 0;
00769 while ( n ) {
00770 if ( n->data == d )
00771 count++;
00772 n = n->next;
00773 }
00774 return count;
00775 }
00776
00782 uint QGList::contains( QPtrCollection::Item d ) const
00783 {
00784 register QLNode *n = firstNode;
00785 uint count = 0;
00786 QGList *that = (QGList*)this;
00787 while ( n ) {
00788 if ( !that->compareItems(n->data,d) )
00789 count++;
00790 n = n->next;
00791 }
00792 return count;
00793 }
00794
00795
00837 QPtrCollection::Item QGList::first()
00838 {
00839 if ( firstNode ) {
00840 curIndex = 0;
00841 return (curNode=firstNode)->data;
00842 }
00843 return 0;
00844 }
00845
00850 QPtrCollection::Item QGList::last()
00851 {
00852 if ( lastNode ) {
00853 curIndex = numNodes-1;
00854 return (curNode=lastNode)->data;
00855 }
00856 return 0;
00857 }
00858
00863 QPtrCollection::Item QGList::next()
00864 {
00865 if ( curNode ) {
00866 if ( curNode->next ) {
00867 curIndex++;
00868 curNode = curNode->next;
00869 return curNode->data;
00870 }
00871 curIndex = -1;
00872 curNode = 0;
00873 }
00874 return 0;
00875 }
00876
00881 QPtrCollection::Item QGList::prev()
00882 {
00883 if ( curNode ) {
00884 if ( curNode->prev ) {
00885 curIndex--;
00886 curNode = curNode->prev;
00887 return curNode->data;
00888 }
00889 curIndex = -1;
00890 curNode = 0;
00891 }
00892 return 0;
00893 }
00894
00895
00900 void QGList::toVector( QGVector *vector ) const
00901 {
00902 vector->clear();
00903 if ( !vector->resize( count() ) )
00904 return;
00905 register QLNode *n = firstNode;
00906 uint i = 0;
00907 while ( n ) {
00908 vector->insert( i, n->data );
00909 n = n->next;
00910 i++;
00911 }
00912 }
00913
00914 void QGList::heapSortPushDown( QPtrCollection::Item* heap, int first, int last )
00915 {
00916 int r = first;
00917 while( r <= last/2 ) {
00918
00919 if ( last == 2*r ) {
00920
00921 if ( compareItems( heap[r], heap[ 2*r ] ) > 0 ) {
00922 QPtrCollection::Item tmp = heap[r];
00923 heap[ r ] = heap[ 2*r ];
00924 heap[ 2*r ] = tmp;
00925 }
00926
00927 r = last;
00928 } else {
00929
00930 if ( compareItems( heap[r], heap[ 2*r ] ) > 0 &&
00931 compareItems( heap[ 2*r ], heap[ 2*r+1 ] ) <= 0 ) {
00932
00933 QPtrCollection::Item tmp = heap[r];
00934 heap[ r ] = heap[ 2*r ];
00935 heap[ 2*r ] = tmp;
00936 r *= 2;
00937 } else if ( compareItems( heap[r], heap[ 2*r+1 ] ) > 0 &&
00938 compareItems( heap[ 2*r+1 ], heap[ 2*r ] ) < 0 ) {
00939
00940 QPtrCollection::Item tmp = heap[r];
00941 heap[ r ] = heap[ 2*r+1 ];
00942 heap[ 2*r+1 ] = tmp;
00943 r = 2*r+1;
00944 } else {
00945
00946 r = last;
00947 }
00948 }
00949 }
00950 }
00951
00952
00960 void QGList::sort()
00961 {
00962 uint n = count();
00963 if ( n < 2 )
00964 return;
00965
00966
00967 QPtrCollection::Item* realheap = new QPtrCollection::Item[ n ];
00968
00969 QPtrCollection::Item* heap = realheap - 1;
00970 int size = 0;
00971 QLNode* insert = firstNode;
00972 for( ; insert != 0; insert = insert->next ) {
00973 heap[++size] = insert->data;
00974 int i = size;
00975 while( i > 1 && compareItems( heap[i], heap[ i / 2 ] ) < 0 ) {
00976 QPtrCollection::Item tmp = heap[ i ];
00977 heap[ i ] = heap[ i/2 ];
00978 heap[ i/2 ] = tmp;
00979 i /= 2;
00980 }
00981 }
00982
00983 insert = firstNode;
00984
00985 for ( int i = n; i > 0; i-- ) {
00986 insert->data = heap[1];
00987 insert = insert->next;
00988 if ( i > 1 ) {
00989 heap[1] = heap[i];
00990 heapSortPushDown( heap, 1, i - 1 );
00991 }
00992 }
00993
00994 delete [] realheap;
00995 }
00996
00997
00998
00999
01000
01001
01002 #ifndef QT_NO_DATASTREAM
01003 QDataStream &operator>>( QDataStream &s, QGList &list )
01004 {
01005 return list.read( s );
01006 }
01007
01008 QDataStream &operator<<( QDataStream &s, const QGList &list )
01009 {
01010 return list.write( s );
01011 }
01012
01017 QDataStream &QGList::read( QDataStream &s )
01018 {
01019 uint num;
01020 s >> num;
01021 clear();
01022 while ( num-- ) {
01023 Item d;
01024 read( s, d );
01025 Q_CHECK_PTR( d );
01026 if ( !d )
01027 break;
01028 QLNode *n = new QLNode( d );
01029 Q_CHECK_PTR( n );
01030 if ( !n )
01031 break;
01032 n->next = 0;
01033 if ( (n->prev = lastNode) )
01034 lastNode->next = n;
01035 else
01036 firstNode = n;
01037 lastNode = n;
01038 numNodes++;
01039 }
01040 curNode = firstNode;
01041 curIndex = curNode ? 0 : -1;
01042 return s;
01043 }
01044
01049 QDataStream &QGList::write( QDataStream &s ) const
01050 {
01051 s << count();
01052 QLNode *n = firstNode;
01053 while ( n ) {
01054 write( s, n->data );
01055 n = n->next;
01056 }
01057 return s;
01058 }
01059
01060 #endif // QT_NO_DATASTREAM
01061
01062
01063
01064
01065
01083 QGListIterator::QGListIterator( const QGList &l )
01084 {
01085 list = (QGList *)&l;
01086 curNode = list->firstNode;
01087 if ( !list->iterators ) {
01088 list->iterators = new QGListIteratorList;
01089 Q_CHECK_PTR( list->iterators );
01090 }
01091 list->iterators->add( this );
01092 }
01093
01099 QGListIterator::QGListIterator( const QGListIterator &it )
01100 {
01101 list = it.list;
01102 curNode = it.curNode;
01103 if ( list )
01104 list->iterators->add( this );
01105 }
01106
01113 QGListIterator &QGListIterator::operator=( const QGListIterator &it )
01114 {
01115 if ( list )
01116 list->iterators->remove( this );
01117 list = it.list;
01118 curNode = it.curNode;
01119 if ( list )
01120 list->iterators->add( this );
01121 return *this;
01122 }
01123
01129 QGListIterator::~QGListIterator()
01130 {
01131 if ( list )
01132 list->iterators->remove(this);
01133 }
01134
01135
01154 QPtrCollection::Item QGListIterator::toFirst()
01155 {
01156 if ( !list ) {
01157 #if defined(QT_CHECK_NULL)
01158 qWarning( "QGListIterator::toFirst: List has been deleted" );
01159 #endif
01160 return 0;
01161 }
01162 return list->firstNode ? (curNode = list->firstNode)->getData() : 0;
01163 }
01164
01170 QPtrCollection::Item QGListIterator::toLast()
01171 {
01172 if ( !list ) {
01173 #if defined(QT_CHECK_NULL)
01174 qWarning( "QGListIterator::toLast: List has been deleted" );
01175 #endif
01176 return 0;
01177 }
01178 return list->lastNode ? (curNode = list->lastNode)->getData() : 0;
01179 }
01180
01181
01194 QPtrCollection::Item QGListIterator::operator()()
01195 {
01196 if ( !curNode )
01197 return 0;
01198 QPtrCollection::Item d = curNode->getData();
01199 curNode = curNode->next;
01200 return d;
01201 }
01202
01208 QPtrCollection::Item QGListIterator::operator++()
01209 {
01210 if ( !curNode )
01211 return 0;
01212 curNode = curNode->next;
01213 return curNode ? curNode->getData() : 0;
01214 }
01215
01221 QPtrCollection::Item QGListIterator::operator+=( uint jumps )
01222 {
01223 while ( curNode && jumps-- )
01224 curNode = curNode->next;
01225 return curNode ? curNode->getData() : 0;
01226 }
01227
01233 QPtrCollection::Item QGListIterator::operator--()
01234 {
01235 if ( !curNode )
01236 return 0;
01237 curNode = curNode->prev;
01238 return curNode ? curNode->getData() : 0;
01239 }
01240
01246 QPtrCollection::Item QGListIterator::operator-=( uint jumps )
01247 {
01248 while ( curNode && jumps-- )
01249 curNode = curNode->prev;
01250 return curNode ? curNode->getData() : 0;
01251 }