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
@@ -1,453 +1,514 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2** $Id$
3** 3**
4** Implementation of QGArray class 4** Implementation of QGArray class
5** 5**
6** Created : 930906 6** Created : 930906
7** 7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. 8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9** 9**
10** This file is part of the tools module of the Qt GUI Toolkit. 10** This file is part of the tools module of the Qt GUI Toolkit.
11** 11**
12** This file may be distributed under the terms of the Q Public License 12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file 13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file. 14** LICENSE.QPL included in the packaging of this file.
15** 15**
16** This file may be distributed and/or modified under the terms of the 16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software 17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the 18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file. 19** packaging of this file.
20** 20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition 21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License 22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software. 23** Agreement provided with the Software.
24** 24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
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
65 75
66/*! 76/*!
67 \class QShared qshared.h 77 \class QShared qshared.h
68 \reentrant 78 \reentrant
69 \ingroup shared 79 \ingroup shared
70 \brief The QShared class is used internally for implementing shared classes. 80 \brief The QShared class is used internally for implementing shared classes.
71 81
72 \internal 82 \internal
73 83
74 It only contains a reference count and member functions to increment and 84 It only contains a reference count and member functions to increment and
75 decrement it. 85 decrement it.
76 86
77 Shared classes normally have internal classes that inherit QShared and 87 Shared classes normally have internal classes that inherit QShared and
78 add the shared data. 88 add the shared data.
79 89
80 \sa \link shclass.html Shared Classes\endlink 90 \sa \link shclass.html Shared Classes\endlink
81*/ 91*/
82 92
83/*! 93/*!
84 \class QGArray qgarray.h 94 \class QGArray qgarray.h
85 \reentrant 95 \reentrant
86 \ingroup shared 96 \ingroup shared
87 \ingroup collection 97 \ingroup collection
88 \brief The QGArray class is an internal class for implementing the QMemArray class. 98 \brief The QGArray class is an internal class for implementing the QMemArray class.
89 99
90 \internal 100 \internal
91 101
92 QGArray is a strictly internal class that acts as base class for the 102 QGArray is a strictly internal class that acts as base class for the
93 QMemArray template array. 103 QMemArray template array.
94 104
95 It contains an array of bytes and has no notion of an array element. 105 It contains an array of bytes and has no notion of an array element.
96*/ 106*/
97 107
98 108
99/*! 109/*!
100 Constructs a null array. 110 Constructs a null array.
101*/ 111*/
102 112
103QGArray::QGArray() 113QGArray::QGArray()
104{ 114{
105 shd = newData(); 115 shd = newData();
106 Q_CHECK_PTR( shd ); 116 Q_CHECK_PTR( shd );
107} 117}
108 118
109/*! 119/*!
110 Dummy constructor; does not allocate any data. 120 Dummy constructor; does not allocate any data.
111 121
112 This constructor does not initialize any array data so subclasses 122 This constructor does not initialize any array data so subclasses
113 must do it. The intention is to make the code more efficient. 123 must do it. The intention is to make the code more efficient.
114*/ 124*/
115 125
116QGArray::QGArray( int, int ) 126QGArray::QGArray( int, int )
117{ 127{
118} 128}
119 129
120/*! 130/*!
121 Constructs an array with room for \a size bytes. 131 Constructs an array with room for \a size bytes.
122*/ 132*/
123 133
124QGArray::QGArray( int size ) 134QGArray::QGArray( int size )
125{ 135{
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
151/*! 165/*!
152 Dereferences the array data and deletes it if this was the last 166 Dereferences the array data and deletes it if this was the last
153 reference. 167 reference.
154*/ 168*/
155 169
156QGArray::~QGArray() 170QGArray::~QGArray()
157{ 171{
158 if ( shd && shd->deref() ) { // delete when last reference 172 if ( shd && shd->deref() ) { // delete when last reference
159 if ( shd->data ) // is lost 173 if ( shd->data ) // is lost
160 DELETE(shd->data); 174 DELETE(shd->data);
161 deleteData( shd ); 175 deleteData( shd );
162 shd = 0; 176 shd = 0;
163 } 177 }
164} 178}
165 179
166 180
167/*! 181/*!
168 \fn QGArray &QGArray::operator=( const QGArray &a ) 182 \fn QGArray &QGArray::operator=( const QGArray &a )
169 183
170 Assigns a shallow copy of \a a to this array and returns a reference to 184 Assigns a shallow copy of \a a to this array and returns a reference to
171 this array. Equivalent to assign(). 185 this array. Equivalent to assign().
172*/ 186*/
173 187
174/*! 188/*!
175 \fn void QGArray::detach() 189 \fn void QGArray::detach()
176 190
177 Detaches this array from shared array data. 191 Detaches this array from shared array data.
178*/ 192*/
179 193
180/*! 194/*!
181 \fn char *QGArray::data() const 195 \fn char *QGArray::data() const
182 196
183 Returns a pointer to the actual array data. 197 Returns a pointer to the actual array data.
184*/ 198*/
185 199
186/*! 200/*!
187 \fn uint QGArray::nrefs() const 201 \fn uint QGArray::nrefs() const
188 202
189 Returns the reference count. 203 Returns the reference count.
190*/ 204*/
191 205
192/*! 206/*!
193 \fn uint QGArray::size() const 207 \fn uint QGArray::size() const
194 208
195 Returns the size of the array, in bytes. 209 Returns the size of the array, in bytes.
196*/ 210*/
197 211
198 212
199/*! 213/*!
200 Returns TRUE if this array is equal to \a a, otherwise FALSE. 214 Returns TRUE if this array is equal to \a a, otherwise FALSE.
201 The comparison is bitwise, of course. 215 The comparison is bitwise, of course.
202*/ 216*/
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
256bool QGArray::fill( const char *d, int len, uint sz ) 305bool QGArray::fill( const char *d, int len, uint sz )
257{ 306{
258 if ( len < 0 ) 307 if ( len < 0 )
259 len = shd->len/sz; // default: use array length 308 len = shd->len/sz; // default: use array length
260 else if ( !resize( len*sz ) ) 309 else if ( !resize( len*sz ) )
261 return FALSE; 310 return FALSE;
262 if ( sz == 1 ) // 8 bit elements 311 if ( sz == 1 ) // 8 bit elements
263 memset( data(), *d, len ); 312 memset( data(), *d, len );
264 else if ( sz == 4 ) { // 32 bit elements 313 else if ( sz == 4 ) { // 32 bit elements
265 register Q_INT32 *x = (Q_INT32*)data(); 314 register Q_INT32 *x = (Q_INT32*)data();
266 Q_INT32 v = *((Q_INT32*)d); 315 Q_INT32 v = *((Q_INT32*)d);
267 while ( len-- ) 316 while ( len-- )
268 *x++ = v; 317 *x++ = v;
269 } else if ( sz == 2 ) { // 16 bit elements 318 } else if ( sz == 2 ) { // 16 bit elements
270 register Q_INT16 *x = (Q_INT16*)data(); 319 register Q_INT16 *x = (Q_INT16*)data();
271 Q_INT16 v = *((Q_INT16*)d); 320 Q_INT16 v = *((Q_INT16*)d);
272 while ( len-- ) 321 while ( len-- )
273 *x++ = v; 322 *x++ = v;
274 } else { // any other size elements 323 } else { // any other size elements
275 register char *x = data(); 324 register char *x = data();
276 while ( len-- ) { // more complicated 325 while ( len-- ) { // more complicated
277 memcpy( x, d, sz ); 326 memcpy( x, d, sz );
278 x += sz; 327 x += sz;
279 } 328 }
280 } 329 }
281 return TRUE; 330 return TRUE;
282} 331}
283 332
284/*! 333/*!
285 \overload 334 \overload
286 Shallow copy. Dereference the current array and references the data 335 Shallow copy. Dereference the current array and references the data
287 contained in \a a instead. Returns a reference to this array. 336 contained in \a a instead. Returns a reference to this array.
288 \sa operator=() 337 \sa operator=()
289*/ 338*/
290 339
291QGArray &QGArray::assign( const QGArray &a ) 340QGArray &QGArray::assign( const QGArray &a )
292{ 341{
293 a.shd->ref(); // avoid 'a = a' 342 a.shd->ref(); // avoid 'a = a'
294 if ( shd->deref() ) { // delete when last reference 343 if ( shd->deref() ) { // delete when last reference
295 if ( shd->data ) // is lost 344 if ( shd->data ) // is lost
296 DELETE(shd->data); 345 DELETE(shd->data);
297 deleteData( shd ); 346 deleteData( shd );
298 } 347 }
299 shd = a.shd; 348 shd = a.shd;
300 return *this; 349 return *this;
301} 350}
302 351
303/*! 352/*!
304 Shallow copy. Dereference the current array and references the 353 Shallow copy. Dereference the current array and references the
305 array data \a d, which contains \a len bytes. 354 array data \a d, which contains \a len bytes.
306 Returns a reference to this array. 355 Returns a reference to this array.
307 356
308 Do not delete \a d later, because QGArray takes care of that. 357 Do not delete \a d later, because QGArray takes care of that.
309*/ 358*/
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) !
335 if ( shd->count > 1 ) { 388 if ( shd->count > 1 ) {
336 shd->count--; 389 shd->count--;
337 register array_data *n = newData(); 390 register array_data *n = newData();
338 Q_CHECK_PTR( n ); 391 Q_CHECK_PTR( n );
339 if ( (n->len=shd->len) ) { 392 if ( (n->len=shd->len) ) {
340 n->data = NEW(char,n->len); 393 n->data = NEW(char,n->len);
341 Q_CHECK_PTR( n->data ); 394 Q_CHECK_PTR( n->data );
342 if ( n->data ) 395 if ( n->data )
343 memcpy( n->data, shd->data, n->len ); 396 memcpy( n->data, shd->data, n->len );
344 } else { 397 } else {
345 n->data = 0; 398 n->data = 0;
346 } 399 }
347 shd = n; 400 shd = n;
348 } 401 }
349 return *this; 402 return *this;
350 } 403 }
351 char *oldptr = 0; 404 char *oldptr = 0;
352 if ( shd->count > 1 ) { // disconnect this 405 if ( shd->count > 1 ) { // disconnect this
353 shd->count--; 406 shd->count--;
354 shd = newData(); 407 shd = newData();
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*/
380 437
381QGArray &QGArray::duplicate( const char *d, uint len ) 438QGArray &QGArray::duplicate( const char *d, uint len )
382{ 439{
383 char *data; 440 char *data;
384 if ( d == 0 || len == 0 ) { 441 if ( d == 0 || len == 0 ) {
385 data = 0; 442 data = 0;
386 len = 0; 443 len = 0;
387 } else { 444 } else {
388 if ( shd->count == 1 && shd->len == len ) { 445 if ( shd->count == 1 && shd->len == len ) {
389 memcpy( shd->data, d, len );// use same buffer 446 memcpy( shd->data, d, len );// use same buffer
390 return *this; 447 return *this;
391 } 448 }
392 data = NEW(char,len); 449 data = NEW(char,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 )
418 { // store, but not deref 479 { // store, but not deref
419 resize( len ); 480 resize( len );
420 memcpy( shd->data, d, len ); 481 memcpy( shd->data, d, len );
421} 482}
422 483
423 484
424/*! 485/*!
425 \fn array_data *QGArray::sharedBlock() const 486 \fn array_data *QGArray::sharedBlock() const
426 487
427 Returns a pointer to the shared array block. 488 Returns a pointer to the shared array block.
428 489
429 \warning 490 \warning
430 491
431 Do not use this function. Using it is begging for trouble. We dare 492 Do not use this function. Using it is begging for trouble. We dare
432 not remove it, for fear of breaking code, but we \e strongly 493 not remove it, for fear of breaking code, but we \e strongly
433 discourage new use of it. 494 discourage new use of it.
434*/ 495*/
435 496
436/*! 497/*!
437 \fn void QGArray::setSharedBlock( array_data *p ) 498 \fn void QGArray::setSharedBlock( array_data *p )
438 499
439 Sets the shared array block to \a p. 500 Sets the shared array block to \a p.
440 501
441 \warning 502 \warning
442 503
443 Do not use this function. Using it is begging for trouble. We dare 504 Do not use this function. Using it is begging for trouble. We dare
444 not remove it, for fear of breaking code, but we \e strongly 505 not remove it, for fear of breaking code, but we \e strongly
445 discourage new use of it. 506 discourage new use of it.
446*/ 507*/
447 508
448 509
449/*! 510/*!
450 Sets raw data and returns a reference to the array. 511 Sets raw data and returns a reference to the array.
451 512
452 Dereferences the current array and sets the new array data to \a d and 513 Dereferences the current array and sets the new array data to \a d and
453 the new array size to \a len. Do not attempt to resize or re-assign the 514 the new array size to \a len. Do not attempt to resize or re-assign the
@@ -614,115 +675,117 @@ int QGArray::contains( const char *d, uint sz ) const
614 if ( *x++ == v ) 675 if ( *x++ == v )
615 count++; 676 count++;
616 } 677 }
617 } 678 }
618 break; 679 break;
619 default: { // any size elements 680 default: { // any size elements
620 for ( i=0; i<shd->len; i+=sz ) { 681 for ( i=0; i<shd->len; i+=sz ) {
621 if ( memcmp(d, &shd->data[i], sz) == 0 ) 682 if ( memcmp(d, &shd->data[i], sz) == 0 )
622 count++; 683 count++;
623 } 684 }
624 } 685 }
625 break; 686 break;
626 } 687 }
627 return count; 688 return count;
628} 689}
629 690
630static int cmp_item_size = 0; 691static int cmp_item_size = 0;
631 692
632#if defined(Q_C_CALLBACKS) 693#if defined(Q_C_CALLBACKS)
633extern "C" { 694extern "C" {
634#endif 695#endif
635 696
636#ifdef Q_OS_TEMP 697#ifdef Q_OS_TEMP
637static int __cdecl cmp_arr( const void *n1, const void *n2 ) 698static int __cdecl cmp_arr( const void *n1, const void *n2 )
638#else 699#else
639static int cmp_arr( const void *n1, const void *n2 ) 700static int cmp_arr( const void *n1, const void *n2 )
640#endif 701#endif
641{ 702{
642 return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) 703 return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size )
643 : ( n1 ? 1 : ( n2 ? -1 : 0 ) ); 704 : ( n1 ? 1 : ( n2 ? -1 : 0 ) );
644 // ### Qt 3.0: Add a virtual compareItems() method and call that instead 705 // ### Qt 3.0: Add a virtual compareItems() method and call that instead
645} 706}
646 707
647#if defined(Q_C_CALLBACKS) 708#if defined(Q_C_CALLBACKS)
648} 709}
649#endif 710#endif
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
693/*! 756/*!
694 \fn char *QGArray::at( uint index ) const 757 \fn char *QGArray::at( uint index ) const
695 758
696 Returns a pointer to the byte at offset \a index in the array. 759 Returns a pointer to the byte at offset \a index in the array.
697*/ 760*/
698 761
699/*! 762/*!
700 Expand the array if necessary, and copies (the first part of) its 763 Expand the array if necessary, and copies (the first part of) its
701 contents from the \a index * \a sz bytes at \a d. 764 contents from the \a index * \a sz bytes at \a d.
702 765
703 Returns TRUE if the operation succeeds, FALSE if it runs out of 766 Returns TRUE if the operation succeeds, FALSE if it runs out of
704 memory. 767 memory.
705 768
706 \warning This function disregards the reference count mechanism. If 769 \warning This function disregards the reference count mechanism. If
707 other QGArrays reference the same data as this, all will be changed. 770 other QGArrays reference the same data as this, all will be changed.
708*/ 771*/
709 772
710bool QGArray::setExpand( uint index, const char *d, uint sz ) 773bool QGArray::setExpand( uint index, const char *d, uint sz )
711{ 774{
712 index *= sz; 775 index *= sz;
713 if ( index >= shd->len ) { 776 if ( index >= shd->len ) {
714 if ( !resize( index+sz ) ) // no memory 777 if ( !resize( index+sz ) ) // no memory
715 return FALSE; 778 return FALSE;
716 } 779 }
717 memcpy( data() + index, d, sz ); 780 memcpy( data() + index, d, sz );
718 return TRUE; 781 return TRUE;
719} 782}
720 783
721 784
722/*! 785/*!
723 Prints a warning message if at() or [] is given a bad index. 786 Prints a warning message if at() or [] is given a bad index.
724*/ 787*/
725 788
726void QGArray::msg_index( uint index ) 789void QGArray::msg_index( uint index )
727{ 790{
728#if defined(QT_CHECK_RANGE) 791#if defined(QT_CHECK_RANGE)