-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 | |||
@@ -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 | ||
145 | QGArray::QGArray( const QGArray &a ) | 159 | QGArray::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 | ||
204 | bool QGArray::isEqual( const QGArray &a ) const | 218 | bool 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 | 232 | bool QGArray::resize( uint newsize, Optimization optim ) | |
218 | bool 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 | */ | ||
287 | bool 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 | ||
311 | QGArray &QGArray::assign( const char *d, uint len ) | 360 | QGArray &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 | ||
332 | QGArray &QGArray::duplicate( const QGArray &a ) | 385 | QGArray &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 | ||
417 | void QGArray::store( const char *d, uint len ) | 478 | void 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 | ||
655 | void QGArray::sort( uint sz ) | 716 | void 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 | ||
673 | int QGArray::bsearch( const char *d, uint sz ) const | 735 | int 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 | ||