Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qvaluelist.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qvaluelist.h,v 1.2 2003/07/10 02:40:11 llornkcor Exp $
00003 **
00004 ** Definition of QValueList class
00005 **
00006 ** Created : 990406
00007 **
00008 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the tools module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
00035 **
00036 **********************************************************************/
00037 
00038 #ifndef QVALUELIST_H
00039 #define QVALUELIST_H
00040 
00041 #ifndef QT_H
00042 #include "qtl.h"
00043 #include "qshared.h"
00044 #include "qdatastream.h"
00045 #endif // QT_H
00046 
00047 #ifndef QT_NO_STL
00048 #include <iterator>
00049 #include <list>
00050 #endif
00051 
00052 //#define QT_CHECK_VALUELIST_RANGE
00053 
00054 #if defined(Q_CC_MSVC)
00055 #pragma warning(disable:4284) // "return type for operator -> is not a UDT"
00056 #endif
00057 
00058 template <class T>
00059 class QValueListNode
00060 {
00061 public:
00062     QValueListNode( const T& t ) : data( t ) { }
00063     QValueListNode() { }
00064 #if defined(Q_TEMPLATEDLL)
00065     // Workaround MS bug in memory de/allocation in DLL vs. EXE
00066     virtual ~QValueListNode() { }
00067 #endif
00068 
00069     QValueListNode<T>* next;
00070     QValueListNode<T>* prev;
00071     T data;
00072 };
00073 
00074 template<class T>
00075 class QValueListIterator
00076 {
00077  public:
00081     typedef QValueListNode<T>* NodePtr;
00082 #ifndef QT_NO_STL
00083     typedef std::bidirectional_iterator_tag  iterator_category;
00084 #endif
00085     typedef T        value_type;
00086     typedef size_t size_type;
00087 #ifndef QT_NO_STL
00088     typedef ptrdiff_t  difference_type;
00089 #else
00090     typedef int difference_type;
00091 #endif
00092     typedef T*   pointer;
00093     typedef T& reference;
00094 
00098     NodePtr node;
00099 
00103     QValueListIterator() : node( 0 ) {}
00104     QValueListIterator( NodePtr p ) : node( p ) {}
00105     QValueListIterator( const QValueListIterator<T>& it ) : node( it.node ) {}
00106 
00107     bool operator==( const QValueListIterator<T>& it ) const { return node == it.node; }
00108     bool operator!=( const QValueListIterator<T>& it ) const { return node != it.node; }
00109     const T& operator*() const { return node->data; }
00110     T& operator*() { return node->data; }
00111     // UDT for T = x*
00112     // T* operator->() const { return &node->data; }
00113 
00114     QValueListIterator<T>& operator++() {
00115         node = node->next;
00116         return *this;
00117     }
00118 
00119     QValueListIterator<T> operator++(int) {
00120         QValueListIterator<T> tmp = *this;
00121         node = node->next;
00122         return tmp;
00123     }
00124 
00125     QValueListIterator<T>& operator--() {
00126         node = node->prev;
00127         return *this;
00128     }
00129 
00130     QValueListIterator<T> operator--(int) {
00131         QValueListIterator<T> tmp = *this;
00132         node = node->prev;
00133         return tmp;
00134     }
00135     
00136     QValueListIterator<T>& operator+=( int j ) {
00137         while ( j-- )
00138             node = node->next;
00139         return *this;
00140     }
00141 
00142     QValueListIterator<T>& operator-=( int j ) {
00143         while ( j-- )
00144             node = node->prev;
00145         return *this;
00146     }
00147 
00148 };
00149 
00150 template<class T>
00151 class QValueListConstIterator
00152 {
00153  public:
00157     typedef QValueListNode<T>* NodePtr;
00158 #ifndef QT_NO_STL
00159     typedef std::bidirectional_iterator_tag  iterator_category;
00160 #endif
00161     typedef T        value_type;
00162     typedef size_t size_type;
00163 #ifndef QT_NO_STL
00164     typedef ptrdiff_t  difference_type;
00165 #else
00166     typedef int difference_type;
00167 #endif
00168     typedef const T*   pointer;
00169     typedef const T& reference;
00170 
00174     NodePtr node;
00175 
00179     QValueListConstIterator() : node( 0 ) {}
00180     QValueListConstIterator( NodePtr p ) : node( p ) {}
00181     QValueListConstIterator( const QValueListConstIterator<T>& it ) : node( it.node ) {}
00182     QValueListConstIterator( const QValueListIterator<T>& it ) : node( it.node ) {}
00183 
00184     bool operator==( const QValueListConstIterator<T>& it ) const { return node == it.node; }
00185     bool operator!=( const QValueListConstIterator<T>& it ) const { return node != it.node; }
00186     const T& operator*() const { return node->data; }
00187     // UDT for T = x*
00188     // const T* operator->() const { return &node->data; }
00189 
00190     QValueListConstIterator<T>& operator++() {
00191         node = node->next;
00192         return *this;
00193     }
00194 
00195     QValueListConstIterator<T> operator++(int) {
00196         QValueListConstIterator<T> tmp = *this;
00197         node = node->next;
00198         return tmp;
00199     }
00200 
00201     QValueListConstIterator<T>& operator--() {
00202         node = node->prev;
00203         return *this;
00204     }
00205 
00206     QValueListConstIterator<T> operator--(int) {
00207         QValueListConstIterator<T> tmp = *this;
00208         node = node->prev;
00209         return tmp;
00210     }
00211 };
00212 
00213 template <class T>
00214 class QValueListPrivate : public QShared
00215 {
00216 public:
00220     typedef QValueListIterator<T> Iterator;
00221     typedef QValueListConstIterator<T> ConstIterator;
00222     typedef QValueListNode<T> Node;
00223     typedef QValueListNode<T>* NodePtr;
00224     typedef size_t size_type;
00225 
00229     QValueListPrivate();
00230     QValueListPrivate( const QValueListPrivate<T>& _p );
00231 
00232     void derefAndDelete() // ### hack to get around hp-cc brain damage
00233     {
00234         if ( deref() )
00235             delete this;
00236     }
00237 
00238 #if defined(Q_TEMPLATEDLL)
00239     // Workaround MS bug in memory de/allocation in DLL vs. EXE
00240     virtual
00241 #endif
00242     ~QValueListPrivate();
00243 
00244     Iterator insert( Iterator it, const T& x );
00245     Iterator remove( Iterator it );
00246     NodePtr find( NodePtr start, const T& x ) const;
00247     int findIndex( NodePtr start, const T& x ) const;
00248     uint contains( const T& x ) const;
00249     uint remove( const T& x );
00250     NodePtr at( size_type i ) const;
00251     void clear();
00252 
00253     NodePtr node;
00254     size_type nodes;
00255 };
00256 
00257 template <class T>
00258 Q_INLINE_TEMPLATES QValueListPrivate<T>::QValueListPrivate()
00259 {
00260     node = new Node; node->next = node->prev = node; nodes = 0;
00261 }
00262 
00263 template <class T>
00264 Q_INLINE_TEMPLATES QValueListPrivate<T>::QValueListPrivate( const QValueListPrivate<T>& _p )
00265     : QShared()
00266 {
00267     node = new Node; node->next = node->prev = node; nodes = 0;
00268     Iterator b( _p.node->next );
00269     Iterator e( _p.node );
00270     Iterator i( node );
00271     while( b != e )
00272         insert( i, *b++ );
00273 }
00274 
00275 template <class T>
00276 Q_INLINE_TEMPLATES QValueListPrivate<T>::~QValueListPrivate() {
00277     NodePtr p = node->next;
00278     while( p != node ) {
00279         NodePtr x = p->next;
00280         delete p;
00281         p = x;
00282     }
00283     delete node;
00284 }
00285 
00286 template <class T>
00287 Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::insert( Q_TYPENAME QValueListPrivate<T>::Iterator it, const T& x )
00288 {
00289     NodePtr p = new Node( x );
00290     p->next = it.node;
00291     p->prev = it.node->prev;
00292     it.node->prev->next = p;
00293     it.node->prev = p;
00294     nodes++;
00295     return p;
00296 }
00297 
00298 template <class T>
00299 Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::remove( Q_TYPENAME QValueListPrivate<T>::Iterator it )
00300 {
00301     Q_ASSERT ( it.node != node );
00302     NodePtr next = it.node->next;
00303     NodePtr prev = it.node->prev;
00304     prev->next = next;
00305     next->prev = prev;
00306     delete it.node;
00307     nodes--;
00308     return Iterator( next );
00309 }
00310 
00311 template <class T>
00312 Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::find( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const
00313 {
00314     ConstIterator first( start );
00315     ConstIterator last( node );
00316     while( first != last) {
00317         if ( *first == x )
00318             return first.node;
00319         ++first;
00320     }
00321     return last.node;
00322 }
00323 
00324 template <class T>
00325 Q_INLINE_TEMPLATES int QValueListPrivate<T>::findIndex( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const
00326 {
00327     ConstIterator first( start );
00328     ConstIterator last( node );
00329     int pos = 0;
00330     while( first != last) {
00331         if ( *first == x )
00332             return pos;
00333         ++first;
00334         ++pos;
00335     }
00336     return -1;
00337 }
00338 
00339 template <class T>
00340 Q_INLINE_TEMPLATES uint QValueListPrivate<T>::contains( const T& x ) const
00341 {
00342     uint result = 0;
00343     Iterator first = Iterator( node->next );
00344     Iterator last = Iterator( node );
00345     while( first != last) {
00346         if ( *first == x )
00347             ++result;
00348         ++first;
00349     }
00350     return result;
00351 }
00352 
00353 template <class T>
00354 Q_INLINE_TEMPLATES uint QValueListPrivate<T>::remove( const T& x )
00355 {
00356     uint result = 0;
00357     Iterator first = Iterator( node->next );
00358     Iterator last = Iterator( node );
00359     while( first != last) {
00360         if ( *first == x ) {
00361             first = remove( first );
00362             ++result;
00363         } else
00364             ++first;
00365     }
00366     return result;
00367 }
00368 
00369 template <class T>
00370 Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::at( size_type i ) const
00371 {
00372     Q_ASSERT( i <= nodes );
00373     NodePtr p = node->next;
00374     for( size_type x = 0; x < i; ++x )
00375         p = p->next;
00376     return p;
00377 }
00378 
00379 template <class T>
00380 Q_INLINE_TEMPLATES void QValueListPrivate<T>::clear()
00381 {
00382     nodes = 0;
00383     NodePtr p = node->next;
00384     while( p != node ) {
00385         NodePtr next = p->next;
00386         delete p;
00387         p = next;
00388     }
00389     node->next = node->prev = node;
00390 }
00391 
00392 #ifdef QT_CHECK_RANGE
00393 # if !defined( QT_NO_DEBUG ) && defined( QT_CHECK_VALUELIST_RANGE )
00394 #  define QT_CHECK_INVALID_LIST_ELEMENT if ( empty() ) qWarning( "QValueList: Warning invalid element" )
00395 #  define QT_CHECK_INVALID_LIST_ELEMENT_FATAL Q_ASSERT( !empty() );
00396 # else
00397 #  define QT_CHECK_INVALID_LIST_ELEMENT
00398 #  define QT_CHECK_INVALID_LIST_ELEMENT_FATAL
00399 # endif
00400 #else
00401 # define QT_CHECK_INVALID_LIST_ELEMENT
00402 # define QT_CHECK_INVALID_LIST_ELEMENT_FATAL
00403 #endif
00404 
00405 template <class T> class QDeepCopy;
00406 
00407 template <class T>
00408 class QValueList
00409 {
00410 public:
00414     typedef QValueListIterator<T> iterator;
00415     typedef QValueListConstIterator<T> const_iterator;
00416     typedef T value_type;
00417     typedef value_type* pointer;
00418     typedef const value_type* const_pointer;
00419     typedef value_type& reference;
00420     typedef const value_type& const_reference;
00421     typedef size_t size_type;
00422 #ifndef QT_NO_STL
00423     typedef ptrdiff_t  difference_type;
00424 #else
00425     typedef int difference_type;
00426 #endif
00427 
00431     QValueList() { sh = new QValueListPrivate<T>; }
00432     QValueList( const QValueList<T>& l ) { sh = l.sh; sh->ref(); }
00433 #ifndef QT_NO_STL
00434 #  ifdef Q_CC_HPACC    // HP-UX aCC does require typename in some place
00435 #    undef Q_TYPENAME  // but not accept them at others.
00436 #    define Q_TYPENAME // also doesn't like re-defines ...
00437 #  endif
00438     QValueList( const Q_TYPENAME std::list<T>& l )
00439     {
00440         sh = new QValueListPrivate<T>;
00441         qCopy( l.begin(), l.end(), std::back_inserter( *this ) );
00442     }
00443 #endif
00444     ~QValueList() { sh->derefAndDelete(); }
00445 
00446     QValueList<T>& operator= ( const QValueList<T>& l )
00447     {
00448         l.sh->ref();
00449         sh->derefAndDelete();
00450         sh = l.sh;
00451         return *this;
00452     }
00453 #ifndef QT_NO_STL
00454     QValueList<T>& operator= ( const Q_TYPENAME std::list<T>& l )
00455     {
00456         detach();
00457         qCopy( l.begin(), l.end(), std::back_inserter( *this ) );
00458         return *this;
00459     }
00460     bool operator== ( const Q_TYPENAME std::list<T>& l ) const
00461     {
00462         if ( size() != l.size() )
00463             return FALSE;
00464         const_iterator it2 = begin();
00465 #if !defined(Q_CC_MIPS)
00466         typename
00467 #endif
00468         std::list<T>::const_iterator it = l.begin();
00469         for ( ; it2 != end(); ++it2, ++it )
00470         if ( !((*it2) == (*it)) )
00471             return FALSE;
00472         return TRUE;
00473     }
00474 #  ifdef Q_CC_HPACC    // undo the HP-UX aCC hackery done above
00475 #    undef Q_TYPENAME 
00476 #    define Q_TYPENAME typename
00477 #  endif
00478 #endif
00479     bool operator== ( const QValueList<T>& l ) const;
00480     bool operator!= ( const QValueList<T>& l ) const { return !( *this == l ); }
00481     iterator begin() { detach(); return iterator( sh->node->next ); }
00482     const_iterator begin() const { return const_iterator( sh->node->next ); }
00483     iterator end() { detach(); return iterator( sh->node ); }
00484     const_iterator end() const { return const_iterator( sh->node ); }
00485     iterator insert( iterator it, const T& x ) { detach(); return sh->insert( it, x ); }
00486     uint remove( const T& x ) { detach(); return sh->remove( x ); }
00487     void clear();
00488 
00489     QValueList<T>& operator<< ( const T& x )
00490     {
00491         append( x );
00492         return *this;
00493     }
00494 
00495     size_type size() const { return sh->nodes; }
00496     bool empty() const { return sh->nodes == 0; }
00497     void push_front( const T& x ) { detach(); sh->insert( begin(), x ); }
00498     void push_back( const T& x ) { detach(); sh->insert( end(), x ); }
00499     iterator erase( iterator pos ) { detach(); return sh->remove( pos ); }
00500     iterator erase( iterator first, iterator last );
00501     reference front() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); }
00502     const_reference front() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); }
00503     reference back() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); }
00504     const_reference back() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); }
00505     void pop_front() { QT_CHECK_INVALID_LIST_ELEMENT; erase( begin() ); }
00506     void pop_back() {
00507         QT_CHECK_INVALID_LIST_ELEMENT;
00508         iterator tmp = end();
00509         erase( --tmp );
00510     }
00511     void insert( iterator pos, size_type n, const T& x );
00512     // Some compilers (incl. vc++) would instantiate this function even if
00513     // it is not used; this would constrain QValueList to classes that provide
00514     // an operator<
00515     /*
00516     void sort()
00517     {
00518         qHeapSort( *this );
00519     }
00520     */
00521 
00522     QValueList<T> operator+ ( const QValueList<T>& l ) const;
00523     QValueList<T>& operator+= ( const QValueList<T>& l );
00524 
00525     iterator fromLast() { detach(); return iterator( sh->node->prev ); }
00526     const_iterator fromLast() const { return const_iterator( sh->node->prev ); }
00527 
00528     bool isEmpty() const { return ( sh->nodes == 0 ); }
00529 
00530     iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
00531     iterator prepend( const T& x ) { detach(); return sh->insert( begin(), x ); }
00532 
00533     iterator remove( iterator it ) { detach(); return sh->remove( it ); }
00534 
00535     T& first() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->next->data; }
00536     const T& first() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->next->data; }
00537     T& last() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->prev->data; }
00538     const T& last() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->prev->data; }
00539 
00540     T& operator[] ( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->at(i)->data; }
00541     const T& operator[] ( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->at(i)->data; }
00542     iterator at( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return iterator( sh->at(i) ); }
00543     const_iterator at( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return const_iterator( sh->at(i) ); }
00544     iterator find ( const T& x ) { detach(); return iterator( sh->find( sh->node->next, x) ); }
00545     const_iterator find ( const T& x ) const { return const_iterator( sh->find( sh->node->next, x) ); }
00546     iterator find ( iterator it, const T& x ) { detach(); return iterator( sh->find( it.node, x ) ); }
00547     const_iterator find ( const_iterator it, const T& x ) const { return const_iterator( sh->find( it.node, x ) ); }
00548     int findIndex( const T& x ) const { return sh->findIndex( sh->node->next, x) ; }
00549     size_type contains( const T& x ) const { return sh->contains( x ); }
00550 
00551     size_type count() const { return sh->nodes; }
00552 
00553     QValueList<T>& operator+= ( const T& x )
00554     {
00555         append( x );
00556         return *this;
00557     }
00558     typedef QValueListIterator<T> Iterator;
00559     typedef QValueListConstIterator<T> ConstIterator;
00560     typedef T ValueType;
00561 
00562 protected:
00566     void detach() { if ( sh->count > 1 ) detachInternal(); }
00567 
00571     QValueListPrivate<T>* sh;
00572 
00573 private:
00574     void detachInternal();
00575 
00576     friend class QDeepCopy< QValueList<T> >;
00577 };
00578 
00579 template <class T>
00580 Q_INLINE_TEMPLATES bool QValueList<T>::operator== ( const QValueList<T>& l ) const
00581 {
00582     if ( size() != l.size() )
00583         return FALSE;
00584     const_iterator it2 = begin();
00585     const_iterator it = l.begin();
00586     for( ; it != l.end(); ++it, ++it2 )
00587         if ( !( *it == *it2 ) )
00588             return FALSE;
00589     return TRUE;
00590 }
00591 
00592 template <class T>
00593 Q_INLINE_TEMPLATES void QValueList<T>::clear()
00594 {
00595     if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QValueListPrivate<T>; }
00596 }
00597 
00598 template <class T>
00599 Q_INLINE_TEMPLATES Q_TYPENAME QValueList<T>::iterator QValueList<T>::erase( Q_TYPENAME QValueList<T>::iterator first, Q_TYPENAME QValueList<T>::iterator last )
00600 {
00601     while ( first != last )
00602         erase( first++ );
00603     return last;
00604 }
00605 
00606 
00607 template <class T>
00608 Q_INLINE_TEMPLATES void QValueList<T>::insert( Q_TYPENAME QValueList<T>::iterator pos, size_type n, const T& x )
00609 {
00610     for ( ; n > 0; --n )
00611         insert( pos, x );
00612 }
00613 
00614 template <class T>
00615 Q_INLINE_TEMPLATES QValueList<T> QValueList<T>::operator+ ( const QValueList<T>& l ) const
00616 {
00617     QValueList<T> l2( *this );
00618     for( const_iterator it = l.begin(); it != l.end(); ++it )
00619         l2.append( *it );
00620     return l2;
00621 }
00622 
00623 template <class T>
00624 Q_INLINE_TEMPLATES QValueList<T>& QValueList<T>::operator+= ( const QValueList<T>& l )
00625 {
00626     for( const_iterator it = l.begin(); it != l.end(); ++it )
00627         append( *it );
00628     return *this;
00629 }
00630 
00631 template <class T>
00632 Q_INLINE_TEMPLATES void QValueList<T>::detachInternal()
00633 {
00634     sh->deref(); sh = new QValueListPrivate<T>( *sh );
00635 }
00636 
00637 #ifndef QT_NO_DATASTREAM
00638 template <class T>
00639 Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QValueList<T>& l )
00640 {
00641     l.clear();
00642     Q_UINT32 c;
00643     s >> c;
00644     for( Q_UINT32 i = 0; i < c; ++i )
00645     {
00646         T t;
00647         s >> t;
00648         l.append( t );
00649         if ( s.atEnd() )
00650             break;
00651     }
00652     return s;
00653 }
00654 
00655 template <class T>
00656 Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QValueList<T>& l )
00657 {
00658     s << (Q_UINT32)l.size();
00659     QValueListConstIterator<T> it = l.begin();
00660     for( ; it != l.end(); ++it )
00661         s << *it;
00662     return s;
00663 }
00664 #endif // QT_NO_DATASTREAM
00665 #ifdef QT_QWINEXPORT
00666 #define Q_DEFINED_QVALUELIST
00667 #include "qwinexport.h"
00668 #endif /* QT_QWINEXPORT */
00669 #endif // QVALUELIST_H

Generated on Sat Nov 5 16:18:27 2005 for OPIE by  doxygen 1.4.2