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 "qglobal.h"
00039 #if defined(Q_CC_BOR)
00040
00041 # include "qplatformdefs.h"
00042 #elif defined(Q_WS_WIN)
00043
00044 # include "qt_windows.h"
00045 #endif
00046
00047 #define QGARRAY_CPP
00048 #include "qgarray.h"
00049 #include <stdlib.h>
00050 #include <string.h>
00051
00052 #ifdef QT_THREAD_SUPPORT
00053 # include <private/qmutexpool_p.h>
00054 #endif // QT_THREAD_SUPPORT
00055
00056
00057
00058
00059
00060
00061
00062 #define USE_MALLOC
00063
00064 #undef NEW
00065 #undef DELETE
00066
00067 #if defined(USE_MALLOC)
00068 #define NEW(type,size) ((type*)malloc(size*sizeof(type)))
00069 #define DELETE(array) (free((char*)array))
00070 #else
00071 #define NEW(type,size) (new type[size])
00072 #define DELETE(array) (delete[] array)
00073 #define DONT_USE_REALLOC // comment to use realloc()
00074 #endif
00075
00113 QGArray::QGArray()
00114 {
00115 shd = newData();
00116 Q_CHECK_PTR( shd );
00117 }
00118
00126 QGArray::QGArray( int, int )
00127 {
00128 }
00129
00134 QGArray::QGArray( int size )
00135 {
00136 if ( size < 0 ) {
00137 #if defined(QT_CHECK_RANGE)
00138 qWarning( "QGArray: Cannot allocate array with negative length" );
00139 #endif
00140 size = 0;
00141 }
00142 shd = newData();
00143 Q_CHECK_PTR( shd );
00144 if ( size == 0 )
00145 return;
00146 shd->data = NEW(char,size);
00147 Q_CHECK_PTR( shd->data );
00148 shd->len =
00149 #ifdef QT_QGARRAY_SPEED_OPTIM
00150 shd->maxl =
00151 #endif
00152 size;
00153 }
00154
00159 QGArray::QGArray( const QGArray &a )
00160 {
00161 shd = a.shd;
00162 shd->ref();
00163 }
00164
00170 QGArray::~QGArray()
00171 {
00172 if ( shd && shd->deref() ) {
00173 if ( shd->data )
00174 DELETE(shd->data);
00175 deleteData( shd );
00176 shd = 0;
00177 }
00178 }
00179
00180
00218 bool QGArray::isEqual( const QGArray &a ) const
00219 {
00220 if ( size() != a.size() )
00221 return FALSE;
00222 if ( data() == a.data() )
00223 return TRUE;
00224 return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0;
00225 }
00226
00227
00232 bool QGArray::resize( uint newsize, Optimization optim )
00233 {
00234 #ifndef QT_QGARRAY_SPEED_OPTIM
00235 Q_UNUSED(optim);
00236 #endif
00237
00238 if ( newsize == shd->len
00239 #ifdef QT_QGARRAY_SPEED_OPTIM
00240 && newsize == shd->maxl
00241 #endif
00242 )
00243 return TRUE;
00244 if ( newsize == 0 ) {
00245 duplicate( 0, 0 );
00246 return TRUE;
00247 }
00248
00249 uint newmaxl = newsize;
00250 #ifdef QT_QGARRAY_SPEED_OPTIM
00251 if ( optim == SpeedOptim ) {
00252 if ( newsize <= shd->maxl &&
00253 ( newsize * 4 > shd->maxl || shd->maxl <= 4 ) ) {
00254 shd->len = newsize;
00255 return TRUE;
00256 }
00257 newmaxl = 4;
00258 while ( newmaxl < newsize )
00259 newmaxl *= 2;
00260
00261 if ( newmaxl >= 1024 * 1024 && newsize <= newmaxl - (newmaxl >> 2) )
00262 newmaxl -= newmaxl >> 2;
00263 }
00264 shd->maxl = newmaxl;
00265 #endif
00266
00267 if ( shd->data ) {
00268 #if defined(DONT_USE_REALLOC)
00269 char *newdata = NEW(char,newsize);
00270 memcpy( newdata, shd->data, QMIN(shd->len,newmaxl) );
00271 DELETE(shd->data);
00272 shd->data = newdata;
00273 #else
00274 shd->data = (char *)realloc( shd->data, newmaxl );
00275 #endif
00276 } else {
00277 shd->data = NEW(char,newmaxl);
00278 }
00279 if ( !shd->data )
00280 return FALSE;
00281 shd->len = newsize;
00282 return TRUE;
00283 }
00284
00287 bool QGArray::resize( uint newsize )
00288 {
00289 return resize( newsize, MemOptim );
00290 }
00291
00292
00305 bool QGArray::fill( const char *d, int len, uint sz )
00306 {
00307 if ( len < 0 )
00308 len = shd->len/sz;
00309 else if ( !resize( len*sz ) )
00310 return FALSE;
00311 if ( sz == 1 )
00312 memset( data(), *d, len );
00313 else if ( sz == 4 ) {
00314 register Q_INT32 *x = (Q_INT32*)data();
00315 Q_INT32 v = *((Q_INT32*)d);
00316 while ( len-- )
00317 *x++ = v;
00318 } else if ( sz == 2 ) {
00319 register Q_INT16 *x = (Q_INT16*)data();
00320 Q_INT16 v = *((Q_INT16*)d);
00321 while ( len-- )
00322 *x++ = v;
00323 } else {
00324 register char *x = data();
00325 while ( len-- ) {
00326 memcpy( x, d, sz );
00327 x += sz;
00328 }
00329 }
00330 return TRUE;
00331 }
00332
00340 QGArray &QGArray::assign( const QGArray &a )
00341 {
00342 a.shd->ref();
00343 if ( shd->deref() ) {
00344 if ( shd->data )
00345 DELETE(shd->data);
00346 deleteData( shd );
00347 }
00348 shd = a.shd;
00349 return *this;
00350 }
00351
00360 QGArray &QGArray::assign( const char *d, uint len )
00361 {
00362 if ( shd->count > 1 ) {
00363 shd->count--;
00364 shd = newData();
00365 Q_CHECK_PTR( shd );
00366 } else {
00367 if ( shd->data )
00368 DELETE(shd->data);
00369 }
00370 shd->data = (char *)d;
00371 shd->len =
00372 #ifdef QT_QGARRAY_SPEED_OPTIM
00373 shd->maxl =
00374 #endif
00375 len;
00376 return *this;
00377 }
00378
00385 QGArray &QGArray::duplicate( const QGArray &a )
00386 {
00387 if ( a.shd == shd ) {
00388 if ( shd->count > 1 ) {
00389 shd->count--;
00390 register array_data *n = newData();
00391 Q_CHECK_PTR( n );
00392 if ( (n->len=shd->len) ) {
00393 n->data = NEW(char,n->len);
00394 Q_CHECK_PTR( n->data );
00395 if ( n->data )
00396 memcpy( n->data, shd->data, n->len );
00397 } else {
00398 n->data = 0;
00399 }
00400 shd = n;
00401 }
00402 return *this;
00403 }
00404 char *oldptr = 0;
00405 if ( shd->count > 1 ) {
00406 shd->count--;
00407 shd = newData();
00408 Q_CHECK_PTR( shd );
00409 } else {
00410 oldptr = shd->data;
00411 }
00412 if ( a.shd->len ) {
00413 shd->data = NEW(char,a.shd->len);
00414 Q_CHECK_PTR( shd->data );
00415 if ( shd->data )
00416 memcpy( shd->data, a.shd->data, a.shd->len );
00417 } else {
00418 shd->data = 0;
00419 }
00420 shd->len =
00421 #ifdef QT_QGARRAY_SPEED_OPTIM
00422 shd->maxl =
00423 #endif
00424 a.shd->len;
00425 if ( oldptr )
00426 DELETE(oldptr);
00427 return *this;
00428 }
00429
00438 QGArray &QGArray::duplicate( const char *d, uint len )
00439 {
00440 char *data;
00441 if ( d == 0 || len == 0 ) {
00442 data = 0;
00443 len = 0;
00444 } else {
00445 if ( shd->count == 1 && shd->len == len ) {
00446 memcpy( shd->data, d, len );
00447 return *this;
00448 }
00449 data = NEW(char,len);
00450 Q_CHECK_PTR( data );
00451 memcpy( data, d, len );
00452 }
00453 if ( shd->count > 1 ) {
00454 shd->count--;
00455 shd = newData();
00456 Q_CHECK_PTR( shd );
00457 } else {
00458 if ( shd->data )
00459 DELETE(shd->data);
00460 }
00461 shd->data = data;
00462 shd->len =
00463 #ifdef QT_QGARRAY_SPEED_OPTIM
00464 shd->maxl =
00465 #endif
00466 len;
00467 return *this;
00468 }
00469
00478 void QGArray::store( const char *d, uint len )
00479 {
00480 resize( len );
00481 memcpy( shd->data, d, len );
00482 }
00483
00484
00548 QGArray &QGArray::setRawData( const char *d, uint len )
00549 {
00550 duplicate( 0, 0 );
00551 shd->data = (char *)d;
00552 shd->len = len;
00553 return *this;
00554 }
00555
00563 void QGArray::resetRawData( const char *d, uint len )
00564 {
00565 if ( d != shd->data || len != shd->len ) {
00566 #if defined(QT_CHECK_STATE)
00567 qWarning( "QGArray::resetRawData: Inconsistent arguments" );
00568 #endif
00569 return;
00570 }
00571 shd->data = 0;
00572 shd->len = 0;
00573 }
00574
00575
00585 int QGArray::find( const char *d, uint index, uint sz ) const
00586 {
00587 index *= sz;
00588 if ( index >= shd->len ) {
00589 #if defined(QT_CHECK_RANGE)
00590 qWarning( "QGArray::find: Index %d out of range", index/sz );
00591 #endif
00592 return -1;
00593 }
00594 register uint i;
00595 uint ii;
00596 switch ( sz ) {
00597 case 1: {
00598 register char *x = data() + index;
00599 char v = *d;
00600 for ( i=index; i<shd->len; i++ ) {
00601 if ( *x++ == v )
00602 break;
00603 }
00604 ii = i;
00605 }
00606 break;
00607 case 2: {
00608 register Q_INT16 *x = (Q_INT16*)(data() + index);
00609 Q_INT16 v = *((Q_INT16*)d);
00610 for ( i=index; i<shd->len; i+=2 ) {
00611 if ( *x++ == v )
00612 break;
00613 }
00614 ii = i/2;
00615 }
00616 break;
00617 case 4: {
00618 register Q_INT32 *x = (Q_INT32*)(data() + index);
00619 Q_INT32 v = *((Q_INT32*)d);
00620 for ( i=index; i<shd->len; i+=4 ) {
00621 if ( *x++ == v )
00622 break;
00623 }
00624 ii = i/4;
00625 }
00626 break;
00627 default: {
00628 for ( i=index; i<shd->len; i+=sz ) {
00629 if ( memcmp( d, &shd->data[i], sz ) == 0 )
00630 break;
00631 }
00632 ii = i/sz;
00633 }
00634 break;
00635 }
00636 return i<shd->len ? (int)ii : -1;
00637 }
00638
00646 int QGArray::contains( const char *d, uint sz ) const
00647 {
00648 register uint i = shd->len;
00649 int count = 0;
00650 switch ( sz ) {
00651 case 1: {
00652 register char *x = data();
00653 char v = *d;
00654 while ( i-- ) {
00655 if ( *x++ == v )
00656 count++;
00657 }
00658 }
00659 break;
00660 case 2: {
00661 register Q_INT16 *x = (Q_INT16*)data();
00662 Q_INT16 v = *((Q_INT16*)d);
00663 i /= 2;
00664 while ( i-- ) {
00665 if ( *x++ == v )
00666 count++;
00667 }
00668 }
00669 break;
00670 case 4: {
00671 register Q_INT32 *x = (Q_INT32*)data();
00672 Q_INT32 v = *((Q_INT32*)d);
00673 i /= 4;
00674 while ( i-- ) {
00675 if ( *x++ == v )
00676 count++;
00677 }
00678 }
00679 break;
00680 default: {
00681 for ( i=0; i<shd->len; i+=sz ) {
00682 if ( memcmp(d, &shd->data[i], sz) == 0 )
00683 count++;
00684 }
00685 }
00686 break;
00687 }
00688 return count;
00689 }
00690
00691 static int cmp_item_size = 0;
00692
00693 #if defined(Q_C_CALLBACKS)
00694 extern "C" {
00695 #endif
00696
00697 #ifdef Q_OS_TEMP
00698 static int __cdecl cmp_arr( const void *n1, const void *n2 )
00699 #else
00700 static int cmp_arr( const void *n1, const void *n2 )
00701 #endif
00702 {
00703 return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size )
00704 : ( n1 ? 1 : ( n2 ? -1 : 0 ) );
00705
00706 }
00707
00708 #if defined(Q_C_CALLBACKS)
00709 }
00710 #endif
00711
00716 void QGArray::sort( uint sz )
00717 {
00718 int numItems = size() / sz;
00719 if ( numItems < 2 )
00720 return;
00721
00722 #ifdef QT_THREAD_SUPPORT
00723 QMutexLocker locker( qt_global_mutexpool ?
00724 qt_global_mutexpool->get( &cmp_item_size ) : 0 );
00725 #endif // QT_THREAD_SUPPORT
00726
00727 cmp_item_size = sz;
00728 qsort( shd->data, numItems, sz, cmp_arr );
00729 }
00730
00735 int QGArray::bsearch( const char *d, uint sz ) const
00736 {
00737 int numItems = size() / sz;
00738 if ( !numItems )
00739 return -1;
00740
00741 #ifdef QT_THREAD_SUPPORT
00742 QMutexLocker locker( qt_global_mutexpool ?
00743 qt_global_mutexpool->get( &cmp_item_size ) : 0 );
00744 #endif // QT_THREAD_SUPPORT
00745
00746 cmp_item_size = sz;
00747 char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr );
00748 if ( !r )
00749 return -1;
00750 while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) )
00751 r -= sz;
00752 return (int)(( r - shd->data ) / sz);
00753 }
00754
00755
00773 bool QGArray::setExpand( uint index, const char *d, uint sz )
00774 {
00775 index *= sz;
00776 if ( index >= shd->len ) {
00777 if ( !resize( index+sz ) )
00778 return FALSE;
00779 }
00780 memcpy( data() + index, d, sz );
00781 return TRUE;
00782 }
00783
00784
00789 void QGArray::msg_index( uint index )
00790 {
00791 #if defined(QT_CHECK_RANGE)
00792 qWarning( "QGArray::at: Absolute index %d out of range", index );
00793 #else
00794 Q_UNUSED( index )
00795 #endif
00796 }
00797
00798
00803 QGArray::array_data * QGArray::newData()
00804 {
00805 return new array_data;
00806 }
00807
00808
00813 void QGArray::deleteData( array_data *p )
00814 {
00815 delete p;
00816 p = 0;
00817 }