1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the Qt 3 compatibility classes of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
30
#include "q3gvector.h"
31
#include "qdatastream.h"
32
#include "q3valuelist.h"
35
\class Q3LNode qglist.h
37
\brief The Q3LNode class is an internal class for the Q3PtrList template collection.
41
Q3LNode is a doubly-linked list node. It has three pointers:
43
\i Pointer to the previous node.
44
\i Pointer to the next node.
45
\i Pointer to the actual data.
48
It might sometimes be practical to have direct access to the list nodes
49
in a Q3PtrList, but it is seldom required.
51
Be very careful if you want to access the list nodes. The heap can
52
easily get corrupted if you make a mistake.
54
\sa Q3PtrList::currentNode(), Q3PtrList::removeNode(), Q3PtrList::takeNode()
58
\fn Q3PtrCollection::Item Q3LNode::getData()
59
Returns a pointer (\c void*) to the actual data in the list node.
64
\class Q3GList qglist.h
66
\brief The Q3GList class is an internal class for implementing Qt collection classes.
70
Q3GList is a strictly internal class that acts as a base class for
71
several collection classes; Q3PtrList, Q3PtrQueue and Q3PtrStack.
73
Q3GList has some virtual functions that can be reimplemented to
74
customize the subclasses, namely compareItems(), read() and
75
write. Normally, you do not have to reimplement any of these
76
functions. If you still want to reimplement them, see the QStrList
77
class (qstrlist.h) for an example.
81
/* Internal helper class for Q3GList. Contains some optimization for
82
the typically case where only one iterators is activre on the list.
84
class Q3GListIteratorList
88
: list(0), iterator(0) {
90
~Q3GListIteratorList() {
95
void add( Q3GListIterator* i ) {
99
list->push_front( i );
101
list = new Q3ValueList<Q3GListIterator*>;
102
list->push_front( i );
106
void remove( Q3GListIterator* i ) {
107
if ( iterator == i ) {
111
if ( list->isEmpty() ) {
118
void notifyClear( bool zeroList ) {
122
iterator->curNode = 0;
125
for ( Q3ValueList<Q3GListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) {
133
void notifyRemove( Q3LNode* n, Q3LNode* curNode ) {
135
if ( iterator->curNode == n )
136
iterator->curNode = curNode;
139
for ( Q3ValueList<Q3GListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) {
140
if ( (*i)->curNode == n )
141
(*i)->curNode = curNode;
147
Q3ValueList<Q3GListIterator*>* list;
148
Q3GListIterator* iterator;
153
/*****************************************************************************
154
Default implementation of virtual functions
155
*****************************************************************************/
158
Documented as Q3PtrList::compareItems().
160
Compares \a item1 with \a item2.
162
int Q3GList::compareItems( Q3PtrCollection::Item item1, Q3PtrCollection::Item item2 )
164
return item1 != item2; // compare pointers
167
#ifndef QT_NO_DATASTREAM
170
Reads a collection/list item from the stream \a s and returns a reference
173
The default implementation sets \a item to 0.
178
QDataStream &Q3GList::read( QDataStream &s, Q3PtrCollection::Item &item )
186
Writes a collection/list item to the stream \a s and
187
returns a reference to the stream.
189
The default implementation does nothing.
194
QDataStream &Q3GList::write( QDataStream &s, Q3PtrCollection::Item ) const
198
#endif // QT_NO_DATASTREAM
200
/*****************************************************************************
201
Q3GList member functions
202
*****************************************************************************/
205
Constructs an empty list.
210
firstNode = lastNode = curNode = 0; // initialize list
213
iterators = 0; // initialize iterator list
217
Constructs a copy of \a list.
220
Q3GList::Q3GList( const Q3GList & list )
221
: Q3PtrCollection( list )
223
firstNode = lastNode = curNode = 0; // initialize list
226
iterators = 0; // initialize iterator list
227
Q3LNode *n = list.firstNode;
228
while ( n ) { // copy all items from list
235
Removes all items from the list and destroys the list.
242
// Workaround for GCC 2.7.* bug. Compiler constructs 'static' Q3GList
243
// instances twice on the same address and therefore tries to destruct
244
// twice on the same address! This is insane but let's try not to crash
251
Assigns \a list to this list.
254
Q3GList& Q3GList::operator=( const Q3GList &list )
260
if ( list.count() > 0 ) {
261
Q3LNode *n = list.firstNode;
262
while ( n ) { // copy all items from list
273
Compares this list with \a list. Returns true if the lists
274
contain the same data, otherwise false.
277
bool Q3GList::operator==( const Q3GList &list ) const
279
if ( count() != list.count() )
285
Q3LNode *n1 = firstNode;
286
Q3LNode *n2 = list.firstNode;
289
if ( ( (Q3GList*)this )->compareItems( n1->data, n2->data ) != 0 )
299
\fn uint Q3GList::count() const
301
Returns the number of items in the list.
306
Returns the node at position \a index. Sets this node to current.
309
Q3LNode *Q3GList::locate( uint index )
311
if ( index == (uint)curIndex ) // current node ?
313
if ( !curNode && firstNode ) { // set current node
317
register Q3LNode *node;
318
int distance = index - curIndex; // node distance to cur node
319
bool forward; // direction to traverse
321
if ( index >= numNodes )
325
distance = -distance;
326
if ( (uint)distance < index && (uint)distance < numNodes - index ) {
327
node = curNode; // start from current node
328
forward = index > (uint)curIndex;
329
} else if ( index < numNodes - index ) { // start from first node
333
} else { // start from last node
335
distance = numNodes - index - 1;
340
if ( forward ) { // now run through nodes
347
curIndex = index; // must update index
348
return curNode = node;
353
Inserts item \a d at its sorted position in the list.
356
void Q3GList::inSort( Q3PtrCollection::Item d )
359
register Q3LNode *n = firstNode;
360
while ( n && compareItems(n->data,d) < 0 ){ // find position in list
364
insertAt( index, d );
369
Inserts item \a d at the start of the list.
372
void Q3GList::prepend( Q3PtrCollection::Item d )
374
register Q3LNode *n = new Q3LNode( newItem(d) );
377
if ( (n->next = firstNode) ) // list is not empty
379
else // initialize list
381
firstNode = curNode = n; // curNode affected
388
Inserts item \a d at the end of the list.
391
void Q3GList::append( Q3PtrCollection::Item d )
393
register Q3LNode *n = new Q3LNode( newItem(d) );
396
if ( (n->prev = lastNode) ) // list is not empty
398
else // initialize list
400
lastNode = curNode = n; // curNode affected
407
Inserts item \a d at position \a index in the list.
410
bool Q3GList::insertAt( uint index, Q3PtrCollection::Item d )
415
} else if ( index == numNodes ) {
419
Q3LNode *nextNode = locate( index );
422
Q3LNode *prevNode = nextNode->prev;
423
register Q3LNode *n = new Q3LNode( newItem(d) );
427
n->prev = prevNode; // link new node into list
429
curNode = n; // curIndex set by locate()
436
Relinks node \a n and makes it the first node in the list.
439
void Q3GList::relinkNode( Q3LNode *n )
441
if ( n == firstNode ) // already first
446
if ( (n->next = firstNode) ) // list is not empty
448
else // initialize list
450
firstNode = curNode = n; // curNode affected
457
Unlinks the current list node and returns a pointer to this node.
460
Q3LNode *Q3GList::unlink()
462
if ( curNode == 0 ) // null current node
464
register Q3LNode *n = curNode; // unlink this node
465
if ( n == firstNode ) { // removing first node ?
466
if ( (firstNode = n->next) ) {
469
lastNode = curNode = 0; // list becomes empty
473
if ( n == lastNode ) { // removing last node ?
476
} else { // neither last nor first node
477
n->prev->next = n->next;
478
n->next->prev = n->prev;
482
if ( n->next ) { // change current node
484
} else if ( n->prev ) {
490
iterators->notifyRemove( n, curNode );
497
Removes the node \a n from the list.
500
bool Q3GList::removeNode( Q3LNode *n )
502
#if defined(QT_CHECK_NULL)
503
if ( n == 0 || (n->prev && n->prev->next != n) ||
504
(n->next && n->next->prev != n) ) {
505
qWarning( "Q3GList::removeNode: Corrupted node" );
510
unlink(); // unlink node
511
deleteItem( n->data ); // deallocate this node
514
curIndex = curNode ? 0 : -1;
519
Removes the item \a d from the list. Uses compareItems() to find the item.
521
If \a d is 0, removes the current item.
524
bool Q3GList::remove( Q3PtrCollection::Item d )
526
if ( d && find(d) == -1 )
528
Q3LNode *n = unlink();
531
deleteItem( n->data );
537
Removes the item \a d from the list.
540
bool Q3GList::removeRef( Q3PtrCollection::Item d )
542
if ( findRef(d) == -1 )
544
Q3LNode *n = unlink();
547
deleteItem( n->data );
553
\fn bool Q3GList::removeFirst()
555
Removes the first item in the list.
559
\fn bool Q3GList::removeLast()
561
Removes the last item in the list.
565
Removes the item at position \a index from the list.
568
bool Q3GList::removeAt( uint index )
570
if ( !locate(index) )
572
Q3LNode *n = unlink();
575
deleteItem( n->data );
582
Replaces the item at index \a index with \a d.
584
bool Q3GList::replaceAt( uint index, Q3PtrCollection::Item d )
586
Q3LNode *n = locate( index );
589
if ( n->data != d ) {
590
deleteItem( n->data );
591
n->data = newItem( d );
599
Takes the node \a n out of the list.
602
Q3PtrCollection::Item Q3GList::takeNode( Q3LNode *n )
604
#if defined(QT_CHECK_NULL)
605
if ( n == 0 || (n->prev && n->prev->next != n) ||
606
(n->next && n->next->prev != n) ) {
607
qWarning( "Q3GList::takeNode: Corrupted node" );
612
unlink(); // unlink node
614
delete n; // delete the node, not data
616
curIndex = curNode ? 0 : -1;
621
Takes the current item out of the list.
624
Q3PtrCollection::Item Q3GList::take()
626
Q3LNode *n = unlink(); // unlink node
627
Item d = n ? n->data : 0;
628
delete n; // delete node, keep contents
633
Takes the item at position \a index out of the list.
636
Q3PtrCollection::Item Q3GList::takeAt( uint index )
638
if ( !locate(index) )
640
Q3LNode *n = unlink(); // unlink node
641
Item d = n ? n->data : 0;
642
delete n; // delete node, keep contents
647
Takes the first item out of the list.
650
Q3PtrCollection::Item Q3GList::takeFirst()
653
Q3LNode *n = unlink(); // unlink node
654
Item d = n ? n->data : 0;
660
Takes the last item out of the list.
663
Q3PtrCollection::Item Q3GList::takeLast()
666
Q3LNode *n = unlink(); // unlink node
667
Item d = n ? n->data : 0;
674
Removes all items from the list.
677
void Q3GList::clear()
679
register Q3LNode *n = firstNode;
681
firstNode = lastNode = curNode = 0; // initialize list
686
iterators->notifyClear( false );
689
while ( n ) { // for all nodes ...
690
deleteItem( n->data ); // deallocate data
693
delete prevNode; // deallocate node
699
Finds item \a d in the list. If \a fromStart is true the search
700
begins at the first node; otherwise it begins at the current node.
703
int Q3GList::findRef( Q3PtrCollection::Item d, bool fromStart )
707
if ( fromStart ) { // start from first node
710
} else { // start from current node
714
while ( n && n->data != d ) { // find exact match
719
curIndex = n ? index : -1;
720
return curIndex; // return position of item
724
Finds item \a d in the list using compareItems(). If \a fromStart is
725
true the search begins at the first node; otherwise it begins at the
729
int Q3GList::find( Q3PtrCollection::Item d, bool fromStart )
733
if ( fromStart ) { // start from first node
736
} else { // start from current node
740
while ( n && compareItems(n->data,d) ){ // find equal match
745
curIndex = n ? index : -1;
746
return curIndex; // return position of item
751
Counts the number item \a d occurs in the list.
754
uint Q3GList::containsRef( Q3PtrCollection::Item d ) const
756
register Q3LNode *n = firstNode;
758
while ( n ) { // for all nodes...
759
if ( n->data == d ) // count # exact matches
767
Counts the number of times item \a d occurs in the list. Uses
771
uint Q3GList::contains( Q3PtrCollection::Item d ) const
773
register Q3LNode *n = firstNode;
775
Q3GList *that = (Q3GList*)this; // mutable for compareItems()
776
while ( n ) { // for all nodes...
777
if ( !that->compareItems(n->data,d) ) // count # equal matches
786
\fn Q3PtrCollection::Item Q3GList::at( uint index )
789
Sets the item at position \a index to the current item.
793
\fn int Q3GList::at() const
795
Returns the current index.
799
\fn Q3LNode *Q3GList::currentNode() const
801
Returns the current node.
805
\fn Q3PtrCollection::Item Q3GList::get() const
807
Returns the current item.
811
\fn Q3PtrCollection::Item Q3GList::cfirst() const
813
Returns the first item in the list.
817
\fn Q3PtrCollection::Item Q3GList::clast() const
819
Returns the last item in the list.
824
Returns the first list item. Sets this to current.
827
Q3PtrCollection::Item Q3GList::first()
831
return (curNode=firstNode)->data;
837
Returns the last list item. Sets this to current.
840
Q3PtrCollection::Item Q3GList::last()
843
curIndex = numNodes-1;
844
return (curNode=lastNode)->data;
850
Returns the next list item (after current). Sets this to current.
853
Q3PtrCollection::Item Q3GList::next()
856
if ( curNode->next ) {
858
curNode = curNode->next;
859
return curNode->data;
868
Returns the previous list item (before current). Sets this to current.
871
Q3PtrCollection::Item Q3GList::prev()
874
if ( curNode->prev ) {
876
curNode = curNode->prev;
877
return curNode->data;
887
Converts the list to a vector, \a vector.
890
void Q3GList::toVector( Q3GVector *vector ) const
893
if ( !vector->resize( count() ) )
895
register Q3LNode *n = firstNode;
898
vector->insert( i, n->data );
904
void Q3GList::heapSortPushDown( Q3PtrCollection::Item* heap, int first, int last )
907
while( r <= last/2 ) {
908
// Node r has only one child ?
910
// Need for swapping ?
911
if ( compareItems( heap[r], heap[ 2*r ] ) > 0 ) {
912
Q3PtrCollection::Item tmp = heap[r];
913
heap[ r ] = heap[ 2*r ];
919
// Node has two children
920
if ( compareItems( heap[r], heap[ 2*r ] ) > 0 &&
921
compareItems( heap[ 2*r ], heap[ 2*r+1 ] ) <= 0 ) {
922
// Swap with left child
923
Q3PtrCollection::Item tmp = heap[r];
924
heap[ r ] = heap[ 2*r ];
927
} else if ( compareItems( heap[r], heap[ 2*r+1 ] ) > 0 &&
928
compareItems( heap[ 2*r+1 ], heap[ 2*r ] ) < 0 ) {
929
// Swap with right child
930
Q3PtrCollection::Item tmp = heap[r];
931
heap[ r ] = heap[ 2*r+1 ];
943
/*! Sorts the list by the result of the virtual compareItems() function.
945
The Heap-Sort algorithm is used for sorting. It sorts n items with
946
O(n*log n) compares. This is the asymptotic optimal solution of the
957
Q3PtrCollection::Item* realheap = new Q3PtrCollection::Item[ n ];
958
// Wow, what a fake. But I want the heap to be indexed as 1...n
959
Q3PtrCollection::Item* heap = realheap - 1;
961
Q3LNode* insert = firstNode;
962
for( ; insert != 0; insert = insert->next ) {
963
heap[++size] = insert->data;
965
while( i > 1 && compareItems( heap[i], heap[ i / 2 ] ) < 0 ) {
966
Q3PtrCollection::Item tmp = heap[ i ];
967
heap[ i ] = heap[ i/2 ];
974
// Now do the sorting
975
for ( int i = n; i > 0; i-- ) {
976
insert->data = heap[1];
977
insert = insert->next;
980
heapSortPushDown( heap, 1, i - 1 );
988
/*****************************************************************************
989
Q3GList stream functions
990
*****************************************************************************/
992
#ifndef QT_NO_DATASTREAM
993
QDataStream &operator>>( QDataStream &s, Q3GList &list )
995
return list.read( s );
998
QDataStream &operator<<( QDataStream &s, const Q3GList &list )
1000
return list.write( s );
1004
Reads a list from the stream \a s.
1007
QDataStream &Q3GList::read( QDataStream &s )
1010
s >> num; // read number of items
1011
clear(); // clear list
1012
while ( num-- ) { // read all items
1016
if ( !d ) // no memory
1018
Q3LNode *n = new Q3LNode( d );
1020
if ( !n ) // no memory
1023
if ( (n->prev = lastNode) ) // list is not empty
1025
else // initialize list
1030
curNode = firstNode;
1031
curIndex = curNode ? 0 : -1;
1036
Writes the list to the stream \a s.
1039
QDataStream &Q3GList::write( QDataStream &s ) const
1041
s << count(); // write number of items
1042
Q3LNode *n = firstNode;
1043
while ( n ) { // write all items
1044
write( s, n->data );
1050
#endif // QT_NO_DATASTREAM
1056
Q3LNode* Q3GList::erase( Q3LNode* it )
1065
/*****************************************************************************
1066
Q3GListIterator member functions
1067
*****************************************************************************/
1070
\class Q3GListIterator qglist.h
1072
\brief The Q3GListIterator class is an internal class for implementing Q3PtrListIterator.
1076
Q3GListIterator is a strictly internal class that does the heavy work for
1082
Constructs an iterator that operates on the list \a l.
1085
Q3GListIterator::Q3GListIterator( const Q3GList &l )
1087
list = (Q3GList *)&l; // get reference to list
1088
curNode = list->firstNode; // set to first node
1089
if ( !list->iterators ) {
1090
list->iterators = new Q3GListIteratorList; // create iterator list
1091
Q_CHECK_PTR( list->iterators );
1093
list->iterators->add( this ); // attach iterator to list
1098
Constructs a copy of the iterator \a it.
1101
Q3GListIterator::Q3GListIterator( const Q3GListIterator &it )
1104
curNode = it.curNode;
1106
list->iterators->add( this ); // attach iterator to list
1111
Assigns a copy of the iterator \a it and returns a reference to this
1115
Q3GListIterator &Q3GListIterator::operator=( const Q3GListIterator &it )
1117
if ( list ) // detach from old list
1118
list->iterators->remove( this );
1120
curNode = it.curNode;
1122
list->iterators->add( this ); // attach to new list
1128
Destroys the iterator.
1131
Q3GListIterator::~Q3GListIterator()
1133
if ( list ) // detach iterator from list
1134
list->iterators->remove(this);
1139
\fn bool Q3GListIterator::atFirst() const
1141
Returns true if the iterator points to the first item, otherwise false.
1145
\fn bool Q3GListIterator::atLast() const
1147
Returns true if the iterator points to the last item, otherwise false.
1153
Sets the list iterator to point to the first item in the list.
1156
Q3PtrCollection::Item Q3GListIterator::toFirst()
1159
#if defined(QT_CHECK_NULL)
1160
qWarning( "Q3GListIterator::toFirst: List has been deleted" );
1164
return list->firstNode ? (curNode = list->firstNode)->getData() : 0;
1169
Sets the list iterator to point to the last item in the list.
1172
Q3PtrCollection::Item Q3GListIterator::toLast()
1175
#if defined(QT_CHECK_NULL)
1176
qWarning( "Q3GListIterator::toLast: List has been deleted" );
1180
return list->lastNode ? (curNode = list->lastNode)->getData() : 0;
1185
\fn Q3PtrCollection::Item Q3GListIterator::get() const
1187
Returns the iterator item.
1193
Moves to the next item (postfix).
1196
Q3PtrCollection::Item Q3GListIterator::operator()()
1200
Q3PtrCollection::Item d = curNode->getData();
1201
curNode = curNode->next;
1207
Moves to the next item (prefix).
1210
Q3PtrCollection::Item Q3GListIterator::operator++()
1214
curNode = curNode->next;
1215
return curNode ? curNode->getData() : 0;
1220
Moves \a jumps positions forward.
1223
Q3PtrCollection::Item Q3GListIterator::operator+=( uint jumps )
1225
while ( curNode && jumps-- )
1226
curNode = curNode->next;
1227
return curNode ? curNode->getData() : 0;
1232
Moves to the previous item (prefix).
1235
Q3PtrCollection::Item Q3GListIterator::operator--()
1239
curNode = curNode->prev;
1240
return curNode ? curNode->getData() : 0;
1245
Moves \a jumps positions backward.
1248
Q3PtrCollection::Item Q3GListIterator::operator-=( uint jumps )
1250
while ( curNode && jumps-- )
1251
curNode = curNode->prev;
1252
return curNode ? curNode->getData() : 0;