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

qgvector.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qgvector.cpp,v 1.2 2003/07/10 02:40:12 llornkcor Exp $
00003 **
00004 ** Implementation of QGVector class
00005 **
00006 ** Created : 930907
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 #include "qglobal.h"
00039 #if defined(Q_CC_BOR)
00040 // needed for qsort() because of a std namespace problem on Borland
00041 #include "qplatformdefs.h"
00042 #endif
00043 
00044 #define  QGVECTOR_CPP
00045 #include "qgvector.h"
00046 #include "qglist.h"
00047 #include "qstring.h"
00048 #include "qdatastream.h"
00049 #include <stdlib.h>
00050 
00051 #ifdef QT_THREAD_SUPPORT
00052 #  include <private/qmutexpool_p.h>
00053 #endif // QT_THREAD_SUPPORT
00054 
00055 #define USE_MALLOC                              // comment to use new/delete
00056 
00057 #undef NEW
00058 #undef DELETE
00059 
00060 #if defined(USE_MALLOC)
00061 #define NEW(type,size)  ((type*)malloc(size*sizeof(type)))
00062 #define DELETE(array)   (free((char*)array))
00063 #else
00064 #define NEW(type,size)  (new type[size])
00065 #define DELETE(array)   (delete[] array)
00066 #define DONT_USE_REALLOC                        // comment to use realloc()
00067 #endif
00068 
00092 /*****************************************************************************
00093   Default implementation of virtual functions
00094  *****************************************************************************/
00095 
00121 int QGVector::compareItems( Item d1, Item d2 )
00122 {
00123     return d1 != d2;                            // compare pointers
00124 }
00125 
00126 #ifndef QT_NO_DATASTREAM
00127 
00136 QDataStream &QGVector::read( QDataStream &s, Item &d )
00137 {                                               // read item from stream
00138     d = 0;
00139     return s;
00140 }
00141 
00151 QDataStream &QGVector::write( QDataStream &s, Item ) const
00152 {                                               // write item to stream
00153     return s;
00154 }
00155 #endif // QT_NO_DATASTREAM
00156 
00157 /*****************************************************************************
00158   QGVector member functions
00159  *****************************************************************************/
00160 
00161 QGVector::QGVector()                            // create empty vector
00162 {
00163     vec = 0;
00164     len = numItems = 0;
00165 }
00166 
00167 QGVector::QGVector( uint size )                 // create vectors with nullptrs
00168 {
00169     len = size;
00170     numItems = 0;
00171     if ( len == 0 ) {                           // zero length
00172         vec = 0;
00173         return;
00174     }
00175     vec = NEW(Item,len);
00176     Q_CHECK_PTR( vec );
00177     memset( (void*)vec, 0, len*sizeof(Item) );  // fill with nulls
00178 }
00179 
00180 QGVector::QGVector( const QGVector &a )         // make copy of other vector
00181     : QPtrCollection( a )
00182 {
00183     len = a.len;
00184     numItems = a.numItems;
00185     if ( len == 0 ) {
00186         vec = 0;
00187         return;
00188     }
00189     vec = NEW( Item, len );
00190     Q_CHECK_PTR( vec );
00191     for ( uint i = 0; i < len; i++ ) {
00192         if ( a.vec[i] ) {
00193             vec[i] = newItem( a.vec[i] );
00194             Q_CHECK_PTR( vec[i] );
00195         } else {
00196             vec[i] = 0;
00197         }
00198     }
00199 }
00200 
00201 QGVector::~QGVector()
00202 {
00203     clear();
00204 }
00205 
00206 QGVector& QGVector::operator=( const QGVector &v )
00207 {
00208     if ( &v == this )
00209         return *this;
00210 
00211     clear();
00212     len = v.len;
00213     numItems = v.numItems;
00214     if ( len == 0 ) {
00215         vec = 0;
00216         return *this;
00217     }
00218     vec = NEW( Item, len );
00219     Q_CHECK_PTR( vec );
00220     for ( uint i = 0; i < len; i++ ) {
00221         if ( v.vec[i] ) {
00222             vec[i] = newItem( v.vec[i] );
00223             Q_CHECK_PTR( vec[i] );
00224         } else {
00225             vec[i] = 0;
00226         }
00227     }
00228     return *this;
00229 }
00230 
00231 
00232 bool QGVector::insert( uint index, Item d )     // insert item at index
00233 {
00234 #if defined(QT_CHECK_RANGE)
00235     if ( index >= len ) {                       // range error
00236         qWarning( "QGVector::insert: Index %d out of range", index );
00237         return FALSE;
00238     }
00239 #endif
00240     if ( vec[index] ) {                         // remove old item
00241         deleteItem( vec[index] );
00242         numItems--;
00243     }
00244     if ( d ) {
00245         vec[index] = newItem( d );
00246         Q_CHECK_PTR( vec[index] );
00247         numItems++;
00248         return vec[index] != 0;
00249     } else {
00250         vec[index] = 0;                         // reset item
00251     }
00252     return TRUE;
00253 }
00254 
00255 bool QGVector::remove( uint index )             // remove item at index
00256 {
00257 #if defined(QT_CHECK_RANGE)
00258     if ( index >= len ) {                       // range error
00259         qWarning( "QGVector::remove: Index %d out of range", index );
00260         return FALSE;
00261     }
00262 #endif
00263     if ( vec[index] ) {                         // valid item
00264         deleteItem( vec[index] );               // delete it
00265         vec[index] = 0;                         // reset pointer
00266         numItems--;
00267     }
00268     return TRUE;
00269 }
00270 
00271 QPtrCollection::Item QGVector::take( uint index )               // take out item
00272 {
00273 #if defined(QT_CHECK_RANGE)
00274     if ( index >= len ) {                       // range error
00275         qWarning( "QGVector::take: Index %d out of range", index );
00276         return 0;
00277     }
00278 #endif
00279     Item d = vec[index];                                // don't delete item
00280     if ( d )
00281         numItems--;
00282     vec[index] = 0;
00283     return d;
00284 }
00285 
00286 void QGVector::clear()                          // clear vector
00287 {
00288     if ( vec ) {
00289         for ( uint i=0; i<len; i++ ) {          // delete each item
00290             if ( vec[i] )
00291                 deleteItem( vec[i] );
00292         }
00293         DELETE(vec);
00294         vec = 0;
00295         len = numItems = 0;
00296     }
00297 }
00298 
00299 bool QGVector::resize( uint newsize )           // resize array
00300 {
00301     if ( newsize == len )                       // nothing to do
00302         return TRUE;
00303     if ( vec ) {                                // existing data
00304         if ( newsize < len ) {                  // shrink vector
00305             uint i = newsize;
00306             while ( i < len ) {                 // delete lost items
00307                 if ( vec[i] ) {
00308                     deleteItem( vec[i] );
00309                     numItems--;
00310                 }
00311                 i++;
00312             }
00313         }
00314         if ( newsize == 0 ) {                   // vector becomes empty
00315             DELETE(vec);
00316             vec = 0;
00317             len = numItems = 0;
00318             return TRUE;
00319         }
00320 #if defined(DONT_USE_REALLOC)
00321         if ( newsize == 0 ) {
00322             DELETE(vec);
00323             vec = 0;
00324             return FALSE;
00325         }
00326         Item *newvec = NEW(Item,newsize);               // manual realloc
00327         memcpy( newvec, vec, (len < newsize ? len : newsize)*sizeof(Item) );
00328         DELETE(vec);
00329         vec = newvec;
00330 #else
00331         vec = (Item*)realloc( (char *)vec, newsize*sizeof(Item) );
00332 #endif
00333     } else {                                    // create new vector
00334         vec = NEW(Item,newsize);
00335         len = numItems = 0;
00336     }
00337     Q_CHECK_PTR( vec );
00338     if ( !vec )                                 // no memory
00339         return FALSE;
00340     if ( newsize > len )                        // init extra space added
00341         memset( (void*)&vec[len], 0, (newsize-len)*sizeof(Item) );
00342     len = newsize;
00343     return TRUE;
00344 }
00345 
00346 
00347 bool QGVector::fill( Item d, int flen )         // resize and fill vector
00348 {
00349     if ( flen < 0 )
00350         flen = len;                             // default: use vector length
00351     else if ( !resize( flen ) )
00352         return FALSE;
00353     for ( uint i=0; i<(uint)flen; i++ )         // insert d at every index
00354         insert( i, d );
00355     return TRUE;
00356 }
00357 
00358 
00359 static QGVector *sort_vec=0;                    // current sort vector
00360 
00361 
00362 #if defined(Q_C_CALLBACKS)
00363 extern "C" {
00364 #endif
00365 
00366 #ifdef Q_OS_TEMP
00367 static int _cdecl cmp_vec( const void *n1, const void *n2 )
00368 #else
00369 static int cmp_vec( const void *n1, const void *n2 )
00370 #endif
00371 {
00372     return sort_vec->compareItems( *((QPtrCollection::Item*)n1), *((QPtrCollection::Item*)n2) );
00373 }
00374 
00375 #if defined(Q_C_CALLBACKS)
00376 }
00377 #endif
00378 
00379 
00380 void QGVector::sort()                           // sort vector
00381 {
00382     if ( count() == 0 )                         // no elements
00383         return;
00384     register Item *start = &vec[0];
00385     register Item *end  = &vec[len-1];
00386     Item tmp;
00387     for (;;) {                          // put all zero elements behind
00388         while ( start < end && *start != 0 )
00389             start++;
00390         while ( end > start && *end == 0 )
00391             end--;
00392         if ( start < end ) {
00393             tmp = *start;
00394             *start = *end;
00395             *end = tmp;
00396         } else {
00397             break;
00398         }
00399     }
00400 
00401 #ifdef QT_THREAD_SUPPORT
00402     QMutexLocker locker( qt_global_mutexpool ?
00403                          qt_global_mutexpool->get( &sort_vec ) : 0 );
00404 #endif // QT_THREAD_SUPPORT
00405 
00406     sort_vec = (QGVector*)this;
00407     qsort( vec, count(), sizeof(Item), cmp_vec );
00408     sort_vec = 0;
00409 }
00410 
00411 int QGVector::bsearch( Item d ) const           // binary search; when sorted
00412 {
00413     if ( !len )
00414         return -1;
00415     if ( !d ) {
00416 #if defined(QT_CHECK_NULL)
00417         qWarning( "QGVector::bsearch: Cannot search for null object" );
00418 #endif
00419         return -1;
00420     }
00421     int n1 = 0;
00422     int n2 = len - 1;
00423     int mid = 0;
00424     bool found = FALSE;
00425     while ( n1 <= n2 ) {
00426         int  res;
00427         mid = (n1 + n2)/2;
00428         if ( vec[mid] == 0 )                    // null item greater
00429             res = -1;
00430         else
00431             res = ((QGVector*)this)->compareItems( d, vec[mid] );
00432         if ( res < 0 )
00433             n2 = mid - 1;
00434         else if ( res > 0 )
00435             n1 = mid + 1;
00436         else {                                  // found it
00437             found = TRUE;
00438             break;
00439         }
00440     }
00441     if ( !found )
00442         return -1;
00443     // search to first of equal items
00444     while ( (mid - 1 >= 0) && !((QGVector*)this)->compareItems(d, vec[mid-1]) )
00445         mid--;
00446     return mid;
00447 }
00448 
00449 int QGVector::findRef( Item d, uint index) const // find exact item in vector
00450 {
00451 #if defined(QT_CHECK_RANGE)
00452     if ( index > len ) {                        // range error
00453         qWarning( "QGVector::findRef: Index %d out of range", index );
00454         return -1;
00455     }
00456 #endif
00457     for ( uint i=index; i<len; i++ ) {
00458         if ( vec[i] == d )
00459             return i;
00460     }
00461     return -1;
00462 }
00463 
00464 int QGVector::find( Item d, uint index ) const  // find equal item in vector
00465 {
00466 #if defined(QT_CHECK_RANGE)
00467     if ( index >= len ) {                       // range error
00468         qWarning( "QGVector::find: Index %d out of range", index );
00469         return -1;
00470     }
00471 #endif
00472     for ( uint i=index; i<len; i++ ) {
00473         if ( vec[i] == 0 && d == 0 )            // found null item
00474             return i;
00475         if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 )
00476             return i;
00477     }
00478     return -1;
00479 }
00480 
00481 uint QGVector::containsRef( Item d ) const      // get number of exact matches
00482 {
00483     uint count = 0;
00484     for ( uint i=0; i<len; i++ ) {
00485         if ( vec[i] == d )
00486             count++;
00487     }
00488     return count;
00489 }
00490 
00491 uint QGVector::contains( Item d ) const         // get number of equal matches
00492 {
00493     uint count = 0;
00494     for ( uint i=0; i<len; i++ ) {
00495         if ( vec[i] == 0 && d == 0 )            // count null items
00496             count++;
00497         if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 )
00498             count++;
00499     }
00500     return count;
00501 }
00502 
00503 bool QGVector::insertExpand( uint index, Item d )// insert and grow if necessary
00504 {
00505     if ( index >= len ) {
00506         if ( !resize( index+1 ) )               // no memory
00507             return FALSE;
00508     }
00509     insert( index, d );
00510     return TRUE;
00511 }
00512 
00513 void QGVector::toList( QGList *list ) const     // store items in list
00514 {
00515     list->clear();
00516     for ( uint i=0; i<len; i++ ) {
00517         if ( vec[i] )
00518             list->append( vec[i] );
00519     }
00520 }
00521 
00522 
00523 void QGVector::warningIndexRange( uint i )
00524 {
00525 #if defined(QT_CHECK_RANGE)
00526     qWarning( "QGVector::operator[]: Index %d out of range", i );
00527 #else
00528     Q_UNUSED( i )
00529 #endif
00530 }
00531 
00532 
00533 /*****************************************************************************
00534   QGVector stream functions
00535  *****************************************************************************/
00536 #ifndef QT_NO_DATASTREAM
00537 QDataStream &operator>>( QDataStream &s, QGVector &vec )
00538 {                                               // read vector
00539     return vec.read( s );
00540 }
00541 
00542 QDataStream &operator<<( QDataStream &s, const QGVector &vec )
00543 {                                               // write vector
00544     return vec.write( s );
00545 }
00546 
00547 QDataStream &QGVector::read( QDataStream &s )   // read vector from stream
00548 {
00549     uint num;
00550     s >> num;                                   // read number of items
00551     clear();                                    // clear vector
00552     resize( num );
00553     for (uint i=0; i<num; i++) {                // read all items
00554         Item d;
00555         read( s, d );
00556         Q_CHECK_PTR( d );
00557         if ( !d )                               // no memory
00558             break;
00559         vec[i] = d;
00560     }
00561     return s;
00562 }
00563 
00564 QDataStream &QGVector::write( QDataStream &s ) const
00565 {                                               // write vector to stream
00566     uint num = count();
00567     s << num;                                   // number of items to write
00568     num = size();
00569     for (uint i=0; i<num; i++) {                // write non-null items
00570         if ( vec[i] )
00571             write( s, vec[i] );
00572     }
00573     return s;
00574 }
00575 
00576 /* Returns whether v equals this vector or not */
00577 
00578 bool QGVector::operator==( const QGVector &v ) const
00579 {
00580     if ( size() != v.size() )
00581         return FALSE;
00582     if ( count() != v.count() )
00583         return FALSE;
00584     for ( int i = 0; i < (int)size(); ++i ) {
00585         if ( ( (QGVector*)this )->compareItems( at( i ), v.at( i ) ) != 0 )
00586             return FALSE;
00587     }
00588     return TRUE;
00589 }
00590 
00591 #endif // QT_NO_DATASTREAM

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