summaryrefslogtreecommitdiff
path: root/qmake/tools/qgarray.cpp
Unidiff
Diffstat (limited to 'qmake/tools/qgarray.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/tools/qgarray.cpp97
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
@@ -26,39 +26,49 @@
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27** 27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements. 29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information. 30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information. 31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32** 32**
33** Contact info@trolltech.com if any conditions of this licensing are 33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you. 34** not clear to you.
35** 35**
36**********************************************************************/ 36**********************************************************************/
37 37
38 #include "qglobal.h" // needed to define Q_WS_WIN 38#include "qglobal.h"
39#ifdef Q_WS_WIN 39#if defined(Q_CC_BOR)
40 #include "qt_windows.h" // needed for bsearch on some platforms 40 // needed for qsort() because of a std namespace problem on Borland
41# include "qplatformdefs.h"
42#elif defined(Q_WS_WIN)
43 // needed for bsearch on some platforms
44# include "qt_windows.h"
41#endif 45#endif
42 46
43 #define QGARRAY_CPP 47 #define QGARRAY_CPP
44#include "qgarray.h" 48#include "qgarray.h"
45#include <stdlib.h> 49#include <stdlib.h>
46#include <string.h> 50#include <string.h>
47 51
48#ifdef QT_THREAD_SUPPORT 52#ifdef QT_THREAD_SUPPORT
49# include <private/qmutexpool_p.h> 53# include <private/qmutexpool_p.h>
50#endif // QT_THREAD_SUPPORT 54#endif // QT_THREAD_SUPPORT
51 55
52 #define USE_MALLOC // comment to use new/delete 56/*
57 If USE_MALLOC isn't defined, we use new[] and delete[] to allocate
58 memory. The documentation for QMemArray<T>::assign() explicitly
59 mentions that the array is freed using free(), so don't mess around
60 with USE_MALLOC unless you know what you're doing.
61*/
62#define USE_MALLOC
53 63
54#undef NEW 64#undef NEW
55#undef DELETE 65#undef DELETE
56 66
57#if defined(USE_MALLOC) 67#if defined(USE_MALLOC)
58 #define NEW(type,size)((type*)malloc(size*sizeof(type))) 68 #define NEW(type,size)((type*)malloc(size*sizeof(type)))
59 #define DELETE(array)(free((char*)array)) 69 #define DELETE(array)(free((char*)array))
60#else 70#else
61 #define NEW(type,size)(new type[size]) 71 #define NEW(type,size)(new type[size])
62 #define DELETE(array)(delete[] array) 72 #define DELETE(array)(delete[] array)
63 #define DONT_USE_REALLOC // comment to use realloc() 73 #define DONT_USE_REALLOC // comment to use realloc()
64#endif 74#endif
@@ -126,25 +136,29 @@ QGArray::QGArray( int size )
126 if ( size < 0 ) { 136 if ( size < 0 ) {
127#if defined(QT_CHECK_RANGE) 137#if defined(QT_CHECK_RANGE)
128 qWarning( "QGArray: Cannot allocate array with negative length" ); 138 qWarning( "QGArray: Cannot allocate array with negative length" );
129#endif 139#endif
130 size = 0; 140 size = 0;
131 } 141 }
132 shd = newData(); 142 shd = newData();
133 Q_CHECK_PTR( shd ); 143 Q_CHECK_PTR( shd );
134 if ( size == 0 ) // zero length 144 if ( size == 0 ) // zero length
135 return; 145 return;
136 shd->data = NEW(char,size); 146 shd->data = NEW(char,size);
137 Q_CHECK_PTR( shd->data ); 147 Q_CHECK_PTR( shd->data );
138 shd->len = size; 148 shd->len =
149#ifdef QT_QGARRAY_SPEED_OPTIM
150 shd->maxl =
151#endif
152 size;
139} 153}
140 154
141/*! 155/*!
142 Constructs a shallow copy of \a a. 156 Constructs a shallow copy of \a a.
143*/ 157*/
144 158
145QGArray::QGArray( const QGArray &a ) 159QGArray::QGArray( const QGArray &a )
146{ 160{
147 shd = a.shd; 161 shd = a.shd;
148 shd->ref(); 162 shd->ref();
149} 163}
150 164
@@ -203,53 +217,88 @@ QGArray::~QGArray()
203 217
204bool QGArray::isEqual( const QGArray &a ) const 218bool QGArray::isEqual( const QGArray &a ) const
205{ 219{
206 if ( size() != a.size() ) // different size 220 if ( size() != a.size() ) // different size
207 return FALSE; 221 return FALSE;
208 if ( data() == a.data() ) // has same data 222 if ( data() == a.data() ) // has same data
209 return TRUE; 223 return TRUE;
210 return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0; 224 return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0;
211} 225}
212 226
213 227
214/*! 228/*!
215 Resizes the array to \a newsize bytes. 229 Resizes the array to \a newsize bytes. \a optim is either
230 MemOptim (the default) or SpeedOptim.
216*/ 231*/
217 232bool QGArray::resize( uint newsize, Optimization optim )
218bool QGArray::resize( uint newsize )
219{ 233{
220 if ( newsize == shd->len ) // nothing to do 234#ifndef QT_QGARRAY_SPEED_OPTIM
235 Q_UNUSED(optim);
236#endif
237
238 if ( newsize == shd->len
239#ifdef QT_QGARRAY_SPEED_OPTIM
240 && newsize == shd->maxl
241#endif
242 ) // nothing to do
221 return TRUE; 243 return TRUE;
222 if ( newsize == 0 ) { // remove array 244 if ( newsize == 0 ) { // remove array
223 duplicate( 0, 0 ); 245 duplicate( 0, 0 );
224 return TRUE; 246 return TRUE;
225 } 247 }
248
249 uint newmaxl = newsize;
250#ifdef QT_QGARRAY_SPEED_OPTIM
251 if ( optim == SpeedOptim ) {
252 if ( newsize <= shd->maxl &&
253 ( newsize * 4 > shd->maxl || shd->maxl <= 4 ) ) {
254 shd->len = newsize;
255 return TRUE;
256 }
257 newmaxl = 4;
258 while ( newmaxl < newsize )
259 newmaxl *= 2;
260 // try to spare some memory
261 if ( newmaxl >= 1024 * 1024 && newsize <= newmaxl - (newmaxl >> 2) )
262 newmaxl -= newmaxl >> 2;
263 }
264 shd->maxl = newmaxl;
265#endif
266
226 if ( shd->data ) { // existing data 267 if ( shd->data ) { // existing data
227#if defined(DONT_USE_REALLOC) 268#if defined(DONT_USE_REALLOC)
228 char *newdata = NEW(char,newsize);// manual realloc 269 char *newdata = NEW(char,newsize);// manual realloc
229 memcpy( newdata, shd->data, QMIN(shd->len,newsize) ); 270 memcpy( newdata, shd->data, QMIN(shd->len,newmaxl) );
230 DELETE(shd->data); 271 DELETE(shd->data);
231 shd->data = newdata; 272 shd->data = newdata;
232#else 273#else
233 shd->data = (char *)realloc( shd->data, newsize ); 274 shd->data = (char *)realloc( shd->data, newmaxl );
234#endif 275#endif
235 } else { 276 } else {
236 shd->data = NEW(char,newsize); 277 shd->data = NEW(char,newmaxl);
237 } 278 }
238 if ( !shd->data ) // no memory 279 if ( !shd->data ) // no memory
239 return FALSE; 280 return FALSE;
240 shd->len = newsize; 281 shd->len = newsize;
241 return TRUE; 282 return TRUE;
242} 283}
243 284
285/*!\overload
286*/
287bool QGArray::resize( uint newsize )
288{
289 return resize( newsize, MemOptim );
290}
291
292
244/*! 293/*!
245 Fills the array with the repeated occurrences of \a d, which is 294 Fills the array with the repeated occurrences of \a d, which is
246 \a sz bytes long. 295 \a sz bytes long.
247 If \a len is specified as different from -1, then the array will be 296 If \a len is specified as different from -1, then the array will be
248 resized to \a len*sz before it is filled. 297 resized to \a len*sz before it is filled.
249 298
250 Returns TRUE if successful, or FALSE if the memory cannot be allocated 299 Returns TRUE if successful, or FALSE if the memory cannot be allocated
251 (only when \a len != -1). 300 (only when \a len != -1).
252 301
253 \sa resize() 302 \sa resize()
254*/ 303*/
255 304
@@ -310,25 +359,29 @@ QGArray &QGArray::assign( const QGArray &a )
310 359
311QGArray &QGArray::assign( const char *d, uint len ) 360QGArray &QGArray::assign( const char *d, uint len )
312{ 361{
313 if ( shd->count > 1 ) { // disconnect this 362 if ( shd->count > 1 ) { // disconnect this
314 shd->count--; 363 shd->count--;
315 shd = newData(); 364 shd = newData();
316 Q_CHECK_PTR( shd ); 365 Q_CHECK_PTR( shd );
317 } else { 366 } else {
318 if ( shd->data ) 367 if ( shd->data )
319 DELETE(shd->data); 368 DELETE(shd->data);
320 } 369 }
321 shd->data = (char *)d; 370 shd->data = (char *)d;
322 shd->len = len; 371 shd->len =
372#ifdef QT_QGARRAY_SPEED_OPTIM
373 shd->maxl =
374#endif
375 len;
323 return *this; 376 return *this;
324} 377}
325 378
326/*! 379/*!
327 Deep copy. Dereference the current array and obtains a copy of the data 380 Deep copy. Dereference the current array and obtains a copy of the data
328 contained in \a a instead. Returns a reference to this array. 381 contained in \a a instead. Returns a reference to this array.
329 \sa assign(), operator=() 382 \sa assign(), operator=()
330*/ 383*/
331 384
332QGArray &QGArray::duplicate( const QGArray &a ) 385QGArray &QGArray::duplicate( const QGArray &a )
333{ 386{
334 if ( a.shd == shd ) { // a.duplicate(a) ! 387 if ( a.shd == shd ) { // a.duplicate(a) !
@@ -355,25 +408,29 @@ QGArray &QGArray::duplicate( const QGArray &a )
355 Q_CHECK_PTR( shd ); 408 Q_CHECK_PTR( shd );
356 } else { // delete after copy was made 409 } else { // delete after copy was made
357 oldptr = shd->data; 410 oldptr = shd->data;
358 } 411 }
359 if ( a.shd->len ) { // duplicate data 412 if ( a.shd->len ) { // duplicate data
360 shd->data = NEW(char,a.shd->len); 413 shd->data = NEW(char,a.shd->len);
361 Q_CHECK_PTR( shd->data ); 414 Q_CHECK_PTR( shd->data );
362 if ( shd->data ) 415 if ( shd->data )
363 memcpy( shd->data, a.shd->data, a.shd->len ); 416 memcpy( shd->data, a.shd->data, a.shd->len );
364 } else { 417 } else {
365 shd->data = 0; 418 shd->data = 0;
366 } 419 }
367 shd->len = a.shd->len; 420 shd->len =
421#ifdef QT_QGARRAY_SPEED_OPTIM
422 shd->maxl =
423#endif
424 a.shd->len;
368 if ( oldptr ) 425 if ( oldptr )
369 DELETE(oldptr); 426 DELETE(oldptr);
370 return *this; 427 return *this;
371} 428}
372 429
373/*! 430/*!
374 \overload 431 \overload
375 Deep copy. Dereferences the current array and obtains a copy of 432 Deep copy. Dereferences the current array and obtains a copy of
376 \a len characters from array data \a d instead. Returns a reference 433 \a len characters from array data \a d instead. Returns a reference
377 to this array. 434 to this array.
378 \sa assign(), operator=() 435 \sa assign(), operator=()
379*/ 436*/
@@ -393,25 +450,29 @@ QGArray &QGArray::duplicate( const char *d, uint len )
393 Q_CHECK_PTR( data ); 450 Q_CHECK_PTR( data );
394 memcpy( data, d, len ); 451 memcpy( data, d, len );
395 } 452 }
396 if ( shd->count > 1 ) { // detach 453 if ( shd->count > 1 ) { // detach
397 shd->count--; 454 shd->count--;
398 shd = newData(); 455 shd = newData();
399 Q_CHECK_PTR( shd ); 456 Q_CHECK_PTR( shd );
400 } else { // just a single reference 457 } else { // just a single reference
401 if ( shd->data ) 458 if ( shd->data )
402 DELETE(shd->data); 459 DELETE(shd->data);
403 } 460 }
404 shd->data = data; 461 shd->data = data;
405 shd->len = len; 462 shd->len =
463#ifdef QT_QGARRAY_SPEED_OPTIM
464 shd->maxl =
465#endif
466 len;
406 return *this; 467 return *this;
407} 468}
408 469
409/*! 470/*!
410 Resizes this array to \a len bytes and copies the \a len bytes at 471 Resizes this array to \a len bytes and copies the \a len bytes at
411 address \a d into it. 472 address \a d into it.
412 473
413 \warning This function disregards the reference count mechanism. If 474 \warning This function disregards the reference count mechanism. If
414 other QGArrays reference the same data as this, all will be updated. 475 other QGArrays reference the same data as this, all will be updated.
415*/ 476*/
416 477
417void QGArray::store( const char *d, uint len ) 478void QGArray::store( const char *d, uint len )
@@ -650,43 +711,45 @@ static int cmp_arr( const void *n1, const void *n2 )
650 711
651/*! 712/*!
652 Sorts the first \a sz items of the array. 713 Sorts the first \a sz items of the array.
653*/ 714*/
654 715
655void QGArray::sort( uint sz ) 716void QGArray::sort( uint sz )
656{ 717{
657 int numItems = size() / sz; 718 int numItems = size() / sz;
658 if ( numItems < 2 ) 719 if ( numItems < 2 )
659 return; 720 return;
660 721
661#ifdef QT_THREAD_SUPPORT 722#ifdef QT_THREAD_SUPPORT
662 QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); 723 QMutexLocker locker( qt_global_mutexpool ?
724 qt_global_mutexpool->get( &cmp_item_size ) : 0 );
663#endif // QT_THREAD_SUPPORT 725#endif // QT_THREAD_SUPPORT
664 726
665 cmp_item_size = sz; 727 cmp_item_size = sz;
666 qsort( shd->data, numItems, sz, cmp_arr ); 728 qsort( shd->data, numItems, sz, cmp_arr );
667} 729}
668 730
669/*! 731/*!
670 Binary search; assumes that \a d is a sorted array of size \a sz. 732 Binary search; assumes that \a d is a sorted array of size \a sz.
671*/ 733*/
672 734
673int QGArray::bsearch( const char *d, uint sz ) const 735int QGArray::bsearch( const char *d, uint sz ) const
674{ 736{
675 int numItems = size() / sz; 737 int numItems = size() / sz;
676 if ( !numItems ) 738 if ( !numItems )
677 return -1; 739 return -1;
678 740
679#ifdef QT_THREAD_SUPPORT 741#ifdef QT_THREAD_SUPPORT
680 QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); 742 QMutexLocker locker( qt_global_mutexpool ?
743 qt_global_mutexpool->get( &cmp_item_size ) : 0 );
681#endif // QT_THREAD_SUPPORT 744#endif // QT_THREAD_SUPPORT
682 745
683 cmp_item_size = sz; 746 cmp_item_size = sz;
684 char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr ); 747 char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr );
685 if ( !r ) 748 if ( !r )
686 return -1; 749 return -1;
687 while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) ) 750 while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) )
688 r -= sz;// search to first of equal elements; bsearch is undef 751 r -= sz;// search to first of equal elements; bsearch is undef
689 return (int)(( r - shd->data ) / sz); 752 return (int)(( r - shd->data ) / sz);
690} 753}
691 754
692 755