-rw-r--r-- | qmake/tools/qgarray.cpp | 97 |
1 files changed, 80 insertions, 17 deletions
diff --git a/qmake/tools/qgarray.cpp b/qmake/tools/qgarray.cpp index 45c45ce..0a522e4 100644 --- a/qmake/tools/qgarray.cpp +++ b/qmake/tools/qgarray.cpp @@ -14,63 +14,73 @@ ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#include "qglobal.h" // needed to define Q_WS_WIN -#ifdef Q_WS_WIN -#include "qt_windows.h" // needed for bsearch on some platforms +#include "qglobal.h" +#if defined(Q_CC_BOR) + // needed for qsort() because of a std namespace problem on Borland +# include "qplatformdefs.h" +#elif defined(Q_WS_WIN) + // needed for bsearch on some platforms +# include "qt_windows.h" #endif #define QGARRAY_CPP #include "qgarray.h" #include <stdlib.h> #include <string.h> #ifdef QT_THREAD_SUPPORT # include <private/qmutexpool_p.h> #endif // QT_THREAD_SUPPORT -#define USE_MALLOC // comment to use new/delete +/* + If USE_MALLOC isn't defined, we use new[] and delete[] to allocate + memory. The documentation for QMemArray<T>::assign() explicitly + mentions that the array is freed using free(), so don't mess around + with USE_MALLOC unless you know what you're doing. +*/ +#define USE_MALLOC #undef NEW #undef DELETE #if defined(USE_MALLOC) #define NEW(type,size) ((type*)malloc(size*sizeof(type))) #define DELETE(array) (free((char*)array)) #else #define NEW(type,size) (new type[size]) #define DELETE(array) (delete[] array) #define DONT_USE_REALLOC // comment to use realloc() #endif /*! \class QShared qshared.h \reentrant \ingroup shared \brief The QShared class is used internally for implementing shared classes. \internal It only contains a reference count and member functions to increment and decrement it. @@ -114,49 +124,53 @@ QGArray::QGArray() */ QGArray::QGArray( int, int ) { } /*! Constructs an array with room for \a size bytes. */ QGArray::QGArray( int size ) { if ( size < 0 ) { #if defined(QT_CHECK_RANGE) qWarning( "QGArray: Cannot allocate array with negative length" ); #endif size = 0; } shd = newData(); Q_CHECK_PTR( shd ); if ( size == 0 ) // zero length return; shd->data = NEW(char,size); Q_CHECK_PTR( shd->data ); - shd->len = size; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + size; } /*! Constructs a shallow copy of \a a. */ QGArray::QGArray( const QGArray &a ) { shd = a.shd; shd->ref(); } /*! Dereferences the array data and deletes it if this was the last reference. */ QGArray::~QGArray() { if ( shd && shd->deref() ) { // delete when last reference if ( shd->data ) // is lost DELETE(shd->data); deleteData( shd ); shd = 0; @@ -191,77 +205,112 @@ QGArray::~QGArray() /*! \fn uint QGArray::size() const Returns the size of the array, in bytes. */ /*! Returns TRUE if this array is equal to \a a, otherwise FALSE. The comparison is bitwise, of course. */ bool QGArray::isEqual( const QGArray &a ) const { if ( size() != a.size() ) // different size return FALSE; if ( data() == a.data() ) // has same data return TRUE; return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0; } /*! - Resizes the array to \a newsize bytes. + Resizes the array to \a newsize bytes. \a optim is either + MemOptim (the default) or SpeedOptim. */ - -bool QGArray::resize( uint newsize ) +bool QGArray::resize( uint newsize, Optimization optim ) { - if ( newsize == shd->len ) // nothing to do +#ifndef QT_QGARRAY_SPEED_OPTIM + Q_UNUSED(optim); +#endif + + if ( newsize == shd->len +#ifdef QT_QGARRAY_SPEED_OPTIM + && newsize == shd->maxl +#endif + ) // nothing to do return TRUE; if ( newsize == 0 ) { // remove array duplicate( 0, 0 ); return TRUE; } + + uint newmaxl = newsize; +#ifdef QT_QGARRAY_SPEED_OPTIM + if ( optim == SpeedOptim ) { + if ( newsize <= shd->maxl && + ( newsize * 4 > shd->maxl || shd->maxl <= 4 ) ) { + shd->len = newsize; + return TRUE; + } + newmaxl = 4; + while ( newmaxl < newsize ) + newmaxl *= 2; + // try to spare some memory + if ( newmaxl >= 1024 * 1024 && newsize <= newmaxl - (newmaxl >> 2) ) + newmaxl -= newmaxl >> 2; + } + shd->maxl = newmaxl; +#endif + if ( shd->data ) { // existing data #if defined(DONT_USE_REALLOC) char *newdata = NEW(char,newsize); // manual realloc - memcpy( newdata, shd->data, QMIN(shd->len,newsize) ); + memcpy( newdata, shd->data, QMIN(shd->len,newmaxl) ); DELETE(shd->data); shd->data = newdata; #else - shd->data = (char *)realloc( shd->data, newsize ); + shd->data = (char *)realloc( shd->data, newmaxl ); #endif } else { - shd->data = NEW(char,newsize); + shd->data = NEW(char,newmaxl); } if ( !shd->data ) // no memory return FALSE; shd->len = newsize; return TRUE; } +/*!\overload +*/ +bool QGArray::resize( uint newsize ) +{ + return resize( newsize, MemOptim ); +} + + /*! Fills the array with the repeated occurrences of \a d, which is \a sz bytes long. If \a len is specified as different from -1, then the array will be resized to \a len*sz before it is filled. Returns TRUE if successful, or FALSE if the memory cannot be allocated (only when \a len != -1). \sa resize() */ bool QGArray::fill( const char *d, int len, uint sz ) { if ( len < 0 ) len = shd->len/sz; // default: use array length else if ( !resize( len*sz ) ) return FALSE; if ( sz == 1 ) // 8 bit elements memset( data(), *d, len ); else if ( sz == 4 ) { // 32 bit elements register Q_INT32 *x = (Q_INT32*)data(); Q_INT32 v = *((Q_INT32*)d); while ( len-- ) @@ -298,132 +347,144 @@ QGArray &QGArray::assign( const QGArray &a ) } shd = a.shd; return *this; } /*! Shallow copy. Dereference the current array and references the array data \a d, which contains \a len bytes. Returns a reference to this array. Do not delete \a d later, because QGArray takes care of that. */ QGArray &QGArray::assign( const char *d, uint len ) { if ( shd->count > 1 ) { // disconnect this shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { if ( shd->data ) DELETE(shd->data); } shd->data = (char *)d; - shd->len = len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + len; return *this; } /*! Deep copy. Dereference the current array and obtains a copy of the data contained in \a a instead. Returns a reference to this array. \sa assign(), operator=() */ QGArray &QGArray::duplicate( const QGArray &a ) { if ( a.shd == shd ) { // a.duplicate(a) ! if ( shd->count > 1 ) { shd->count--; register array_data *n = newData(); Q_CHECK_PTR( n ); if ( (n->len=shd->len) ) { n->data = NEW(char,n->len); Q_CHECK_PTR( n->data ); if ( n->data ) memcpy( n->data, shd->data, n->len ); } else { n->data = 0; } shd = n; } return *this; } char *oldptr = 0; if ( shd->count > 1 ) { // disconnect this shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { // delete after copy was made oldptr = shd->data; } if ( a.shd->len ) { // duplicate data shd->data = NEW(char,a.shd->len); Q_CHECK_PTR( shd->data ); if ( shd->data ) memcpy( shd->data, a.shd->data, a.shd->len ); } else { shd->data = 0; } - shd->len = a.shd->len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + a.shd->len; if ( oldptr ) DELETE(oldptr); return *this; } /*! \overload Deep copy. Dereferences the current array and obtains a copy of \a len characters from array data \a d instead. Returns a reference to this array. \sa assign(), operator=() */ QGArray &QGArray::duplicate( const char *d, uint len ) { char *data; if ( d == 0 || len == 0 ) { data = 0; len = 0; } else { if ( shd->count == 1 && shd->len == len ) { memcpy( shd->data, d, len ); // use same buffer return *this; } data = NEW(char,len); Q_CHECK_PTR( data ); memcpy( data, d, len ); } if ( shd->count > 1 ) { // detach shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { // just a single reference if ( shd->data ) DELETE(shd->data); } shd->data = data; - shd->len = len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + len; return *this; } /*! Resizes this array to \a len bytes and copies the \a len bytes at address \a d into it. \warning This function disregards the reference count mechanism. If other QGArrays reference the same data as this, all will be updated. */ void QGArray::store( const char *d, uint len ) { // store, but not deref resize( len ); memcpy( shd->data, d, len ); } /*! \fn array_data *QGArray::sharedBlock() const Returns a pointer to the shared array block. \warning @@ -638,67 +699,69 @@ static int __cdecl cmp_arr( const void *n1, const void *n2 ) #else static int cmp_arr( const void *n1, const void *n2 ) #endif { return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) : ( n1 ? 1 : ( n2 ? -1 : 0 ) ); // ### Qt 3.0: Add a virtual compareItems() method and call that instead } #if defined(Q_C_CALLBACKS) } #endif /*! Sorts the first \a sz items of the array. */ void QGArray::sort( uint sz ) { int numItems = size() / sz; if ( numItems < 2 ) return; #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &cmp_item_size ) : 0 ); #endif // QT_THREAD_SUPPORT cmp_item_size = sz; qsort( shd->data, numItems, sz, cmp_arr ); } /*! Binary search; assumes that \a d is a sorted array of size \a sz. */ int QGArray::bsearch( const char *d, uint sz ) const { int numItems = size() / sz; if ( !numItems ) return -1; #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &cmp_item_size ) : 0 ); #endif // QT_THREAD_SUPPORT cmp_item_size = sz; char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr ); if ( !r ) return -1; while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) ) r -= sz; // search to first of equal elements; bsearch is undef return (int)(( r - shd->data ) / sz); } /*! \fn char *QGArray::at( uint index ) const Returns a pointer to the byte at offset \a index in the array. */ /*! Expand the array if necessary, and copies (the first part of) its contents from the \a index * \a sz bytes at \a d. Returns TRUE if the operation succeeds, FALSE if it runs out of memory. |