author | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
commit | 5042e3cf0d3514552769e441f5aad590c8eaf967 (patch) (unidiff) | |
tree | 4a5ea45f3519d981a172ab5275bf38c6fa778dec /qmake/tools/qgarray.cpp | |
parent | 108c1c753e74e989cc13923086996791428c9af4 (diff) | |
download | opie-5042e3cf0d3514552769e441f5aad590c8eaf967.zip opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.gz opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.bz2 |
Adding qmake in preperation for new build system
-rw-r--r-- | qmake/tools/qgarray.cpp | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/qmake/tools/qgarray.cpp b/qmake/tools/qgarray.cpp new file mode 100644 index 0000000..45c45ce --- a/dev/null +++ b/qmake/tools/qgarray.cpp | |||
@@ -0,0 +1,754 @@ | |||
1 | /**************************************************************************** | ||
2 | ** $Id$ | ||
3 | ** | ||
4 | ** Implementation of QGArray class | ||
5 | ** | ||
6 | ** Created : 930906 | ||
7 | ** | ||
8 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. | ||
9 | ** | ||
10 | ** This file is part of the tools module of the Qt GUI Toolkit. | ||
11 | ** | ||
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 | ||
14 | ** LICENSE.QPL included in the packaging of this file. | ||
15 | ** | ||
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 | ||
18 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
19 | ** packaging of this file. | ||
20 | ** | ||
21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
22 | ** licenses may use this file in accordance with the Qt Commercial License | ||
23 | ** Agreement provided with the Software. | ||
24 | ** | ||
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. | ||
27 | ** | ||
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
29 | ** information about Qt Commercial License Agreements. | ||
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information. | ||
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
32 | ** | ||
33 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
34 | ** not clear to you. | ||
35 | ** | ||
36 | **********************************************************************/ | ||
37 | |||
38 | #include "qglobal.h" // needed to define Q_WS_WIN | ||
39 | #ifdef Q_WS_WIN | ||
40 | #include "qt_windows.h" // needed for bsearch on some platforms | ||
41 | #endif | ||
42 | |||
43 | #define QGARRAY_CPP | ||
44 | #include "qgarray.h" | ||
45 | #include <stdlib.h> | ||
46 | #include <string.h> | ||
47 | |||
48 | #ifdef QT_THREAD_SUPPORT | ||
49 | # include <private/qmutexpool_p.h> | ||
50 | #endif // QT_THREAD_SUPPORT | ||
51 | |||
52 | #define USE_MALLOC // comment to use new/delete | ||
53 | |||
54 | #undef NEW | ||
55 | #undef DELETE | ||
56 | |||
57 | #if defined(USE_MALLOC) | ||
58 | #define NEW(type,size)((type*)malloc(size*sizeof(type))) | ||
59 | #define DELETE(array)(free((char*)array)) | ||
60 | #else | ||
61 | #define NEW(type,size)(new type[size]) | ||
62 | #define DELETE(array)(delete[] array) | ||
63 | #define DONT_USE_REALLOC // comment to use realloc() | ||
64 | #endif | ||
65 | |||
66 | /*! | ||
67 | \class QShared qshared.h | ||
68 | \reentrant | ||
69 | \ingroup shared | ||
70 | \brief The QShared class is used internally for implementing shared classes. | ||
71 | |||
72 | \internal | ||
73 | |||
74 | It only contains a reference count and member functions to increment and | ||
75 | decrement it. | ||
76 | |||
77 | Shared classes normally have internal classes that inherit QShared and | ||
78 | add the shared data. | ||
79 | |||
80 | \sa \link shclass.html Shared Classes\endlink | ||
81 | */ | ||
82 | |||
83 | /*! | ||
84 | \class QGArray qgarray.h | ||
85 | \reentrant | ||
86 | \ingroup shared | ||
87 | \ingroup collection | ||
88 | \brief The QGArray class is an internal class for implementing the QMemArray class. | ||
89 | |||
90 | \internal | ||
91 | |||
92 | QGArray is a strictly internal class that acts as base class for the | ||
93 | QMemArray template array. | ||
94 | |||
95 | It contains an array of bytes and has no notion of an array element. | ||
96 | */ | ||
97 | |||
98 | |||
99 | /*! | ||
100 | Constructs a null array. | ||
101 | */ | ||
102 | |||
103 | QGArray::QGArray() | ||
104 | { | ||
105 | shd = newData(); | ||
106 | Q_CHECK_PTR( shd ); | ||
107 | } | ||
108 | |||
109 | /*! | ||
110 | Dummy constructor; does not allocate any data. | ||
111 | |||
112 | This constructor does not initialize any array data so subclasses | ||
113 | must do it. The intention is to make the code more efficient. | ||
114 | */ | ||
115 | |||
116 | QGArray::QGArray( int, int ) | ||
117 | { | ||
118 | } | ||
119 | |||
120 | /*! | ||
121 | Constructs an array with room for \a size bytes. | ||
122 | */ | ||
123 | |||
124 | QGArray::QGArray( int size ) | ||
125 | { | ||
126 | if ( size < 0 ) { | ||
127 | #if defined(QT_CHECK_RANGE) | ||
128 | qWarning( "QGArray: Cannot allocate array with negative length" ); | ||
129 | #endif | ||
130 | size = 0; | ||
131 | } | ||
132 | shd = newData(); | ||
133 | Q_CHECK_PTR( shd ); | ||
134 | if ( size == 0 ) // zero length | ||
135 | return; | ||
136 | shd->data = NEW(char,size); | ||
137 | Q_CHECK_PTR( shd->data ); | ||
138 | shd->len = size; | ||
139 | } | ||
140 | |||
141 | /*! | ||
142 | Constructs a shallow copy of \a a. | ||
143 | */ | ||
144 | |||
145 | QGArray::QGArray( const QGArray &a ) | ||
146 | { | ||
147 | shd = a.shd; | ||
148 | shd->ref(); | ||
149 | } | ||
150 | |||
151 | /*! | ||
152 | Dereferences the array data and deletes it if this was the last | ||
153 | reference. | ||
154 | */ | ||
155 | |||
156 | QGArray::~QGArray() | ||
157 | { | ||
158 | if ( shd && shd->deref() ) { // delete when last reference | ||
159 | if ( shd->data ) // is lost | ||
160 | DELETE(shd->data); | ||
161 | deleteData( shd ); | ||
162 | shd = 0; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | /*! | ||
168 | \fn QGArray &QGArray::operator=( const QGArray &a ) | ||
169 | |||
170 | Assigns a shallow copy of \a a to this array and returns a reference to | ||
171 | this array. Equivalent to assign(). | ||
172 | */ | ||
173 | |||
174 | /*! | ||
175 | \fn void QGArray::detach() | ||
176 | |||
177 | Detaches this array from shared array data. | ||
178 | */ | ||
179 | |||
180 | /*! | ||
181 | \fn char *QGArray::data() const | ||
182 | |||
183 | Returns a pointer to the actual array data. | ||
184 | */ | ||
185 | |||
186 | /*! | ||
187 | \fn uint QGArray::nrefs() const | ||
188 | |||
189 | Returns the reference count. | ||
190 | */ | ||
191 | |||
192 | /*! | ||
193 | \fn uint QGArray::size() const | ||
194 | |||
195 | Returns the size of the array, in bytes. | ||
196 | */ | ||
197 | |||
198 | |||
199 | /*! | ||
200 | Returns TRUE if this array is equal to \a a, otherwise FALSE. | ||
201 | The comparison is bitwise, of course. | ||
202 | */ | ||
203 | |||
204 | bool QGArray::isEqual( const QGArray &a ) const | ||
205 | { | ||
206 | if ( size() != a.size() ) // different size | ||
207 | return FALSE; | ||
208 | if ( data() == a.data() ) // has same data | ||
209 | return TRUE; | ||
210 | return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0; | ||
211 | } | ||
212 | |||
213 | |||
214 | /*! | ||
215 | Resizes the array to \a newsize bytes. | ||
216 | */ | ||
217 | |||
218 | bool QGArray::resize( uint newsize ) | ||
219 | { | ||
220 | if ( newsize == shd->len ) // nothing to do | ||
221 | return TRUE; | ||
222 | if ( newsize == 0 ) { // remove array | ||
223 | duplicate( 0, 0 ); | ||
224 | return TRUE; | ||
225 | } | ||
226 | if ( shd->data ) { // existing data | ||
227 | #if defined(DONT_USE_REALLOC) | ||
228 | char *newdata = NEW(char,newsize);// manual realloc | ||
229 | memcpy( newdata, shd->data, QMIN(shd->len,newsize) ); | ||
230 | DELETE(shd->data); | ||
231 | shd->data = newdata; | ||
232 | #else | ||
233 | shd->data = (char *)realloc( shd->data, newsize ); | ||
234 | #endif | ||
235 | } else { | ||
236 | shd->data = NEW(char,newsize); | ||
237 | } | ||
238 | if ( !shd->data ) // no memory | ||
239 | return FALSE; | ||
240 | shd->len = newsize; | ||
241 | return TRUE; | ||
242 | } | ||
243 | |||
244 | /*! | ||
245 | Fills the array with the repeated occurrences of \a d, which is | ||
246 | \a sz bytes long. | ||
247 | If \a len is specified as different from -1, then the array will be | ||
248 | resized to \a len*sz before it is filled. | ||
249 | |||
250 | Returns TRUE if successful, or FALSE if the memory cannot be allocated | ||
251 | (only when \a len != -1). | ||
252 | |||
253 | \sa resize() | ||
254 | */ | ||
255 | |||
256 | bool QGArray::fill( const char *d, int len, uint sz ) | ||
257 | { | ||
258 | if ( len < 0 ) | ||
259 | len = shd->len/sz; // default: use array length | ||
260 | else if ( !resize( len*sz ) ) | ||
261 | return FALSE; | ||
262 | if ( sz == 1 ) // 8 bit elements | ||
263 | memset( data(), *d, len ); | ||
264 | else if ( sz == 4 ) { // 32 bit elements | ||
265 | register Q_INT32 *x = (Q_INT32*)data(); | ||
266 | Q_INT32 v = *((Q_INT32*)d); | ||
267 | while ( len-- ) | ||
268 | *x++ = v; | ||
269 | } else if ( sz == 2 ) { // 16 bit elements | ||
270 | register Q_INT16 *x = (Q_INT16*)data(); | ||
271 | Q_INT16 v = *((Q_INT16*)d); | ||
272 | while ( len-- ) | ||
273 | *x++ = v; | ||
274 | } else { // any other size elements | ||
275 | register char *x = data(); | ||
276 | while ( len-- ) { // more complicated | ||
277 | memcpy( x, d, sz ); | ||
278 | x += sz; | ||
279 | } | ||
280 | } | ||
281 | return TRUE; | ||
282 | } | ||
283 | |||
284 | /*! | ||
285 | \overload | ||
286 | Shallow copy. Dereference the current array and references the data | ||
287 | contained in \a a instead. Returns a reference to this array. | ||
288 | \sa operator=() | ||
289 | */ | ||
290 | |||
291 | QGArray &QGArray::assign( const QGArray &a ) | ||
292 | { | ||
293 | a.shd->ref(); // avoid 'a = a' | ||
294 | if ( shd->deref() ) { // delete when last reference | ||
295 | if ( shd->data ) // is lost | ||
296 | DELETE(shd->data); | ||
297 | deleteData( shd ); | ||
298 | } | ||
299 | shd = a.shd; | ||
300 | return *this; | ||
301 | } | ||
302 | |||
303 | /*! | ||
304 | Shallow copy. Dereference the current array and references the | ||
305 | array data \a d, which contains \a len bytes. | ||
306 | Returns a reference to this array. | ||
307 | |||
308 | Do not delete \a d later, because QGArray takes care of that. | ||
309 | */ | ||
310 | |||
311 | QGArray &QGArray::assign( const char *d, uint len ) | ||
312 | { | ||
313 | if ( shd->count > 1 ) { // disconnect this | ||
314 | shd->count--; | ||
315 | shd = newData(); | ||
316 | Q_CHECK_PTR( shd ); | ||
317 | } else { | ||
318 | if ( shd->data ) | ||
319 | DELETE(shd->data); | ||
320 | } | ||
321 | shd->data = (char *)d; | ||
322 | shd->len = len; | ||
323 | return *this; | ||
324 | } | ||
325 | |||
326 | /*! | ||
327 | 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. | ||
329 | \sa assign(), operator=() | ||
330 | */ | ||
331 | |||
332 | QGArray &QGArray::duplicate( const QGArray &a ) | ||
333 | { | ||
334 | if ( a.shd == shd ) { // a.duplicate(a) ! | ||
335 | if ( shd->count > 1 ) { | ||
336 | shd->count--; | ||
337 | register array_data *n = newData(); | ||
338 | Q_CHECK_PTR( n ); | ||
339 | if ( (n->len=shd->len) ) { | ||
340 | n->data = NEW(char,n->len); | ||
341 | Q_CHECK_PTR( n->data ); | ||
342 | if ( n->data ) | ||
343 | memcpy( n->data, shd->data, n->len ); | ||
344 | } else { | ||
345 | n->data = 0; | ||
346 | } | ||
347 | shd = n; | ||
348 | } | ||
349 | return *this; | ||
350 | } | ||
351 | char *oldptr = 0; | ||
352 | if ( shd->count > 1 ) { // disconnect this | ||
353 | shd->count--; | ||
354 | shd = newData(); | ||
355 | Q_CHECK_PTR( shd ); | ||
356 | } else { // delete after copy was made | ||
357 | oldptr = shd->data; | ||
358 | } | ||
359 | if ( a.shd->len ) { // duplicate data | ||
360 | shd->data = NEW(char,a.shd->len); | ||
361 | Q_CHECK_PTR( shd->data ); | ||
362 | if ( shd->data ) | ||
363 | memcpy( shd->data, a.shd->data, a.shd->len ); | ||
364 | } else { | ||
365 | shd->data = 0; | ||
366 | } | ||
367 | shd->len = a.shd->len; | ||
368 | if ( oldptr ) | ||
369 | DELETE(oldptr); | ||
370 | return *this; | ||
371 | } | ||
372 | |||
373 | /*! | ||
374 | \overload | ||
375 | Deep copy. Dereferences the current array and obtains a copy of | ||
376 | \a len characters from array data \a d instead. Returns a reference | ||
377 | to this array. | ||
378 | \sa assign(), operator=() | ||
379 | */ | ||
380 | |||
381 | QGArray &QGArray::duplicate( const char *d, uint len ) | ||
382 | { | ||
383 | char *data; | ||
384 | if ( d == 0 || len == 0 ) { | ||
385 | data = 0; | ||
386 | len = 0; | ||
387 | } else { | ||
388 | if ( shd->count == 1 && shd->len == len ) { | ||
389 | memcpy( shd->data, d, len );// use same buffer | ||
390 | return *this; | ||
391 | } | ||
392 | data = NEW(char,len); | ||
393 | Q_CHECK_PTR( data ); | ||
394 | memcpy( data, d, len ); | ||
395 | } | ||
396 | if ( shd->count > 1 ) { // detach | ||
397 | shd->count--; | ||
398 | shd = newData(); | ||
399 | Q_CHECK_PTR( shd ); | ||
400 | } else { // just a single reference | ||
401 | if ( shd->data ) | ||
402 | DELETE(shd->data); | ||
403 | } | ||
404 | shd->data = data; | ||
405 | shd->len = len; | ||
406 | return *this; | ||
407 | } | ||
408 | |||
409 | /*! | ||
410 | Resizes this array to \a len bytes and copies the \a len bytes at | ||
411 | address \a d into it. | ||
412 | |||
413 | \warning This function disregards the reference count mechanism. If | ||
414 | other QGArrays reference the same data as this, all will be updated. | ||
415 | */ | ||
416 | |||
417 | void QGArray::store( const char *d, uint len ) | ||
418 | { // store, but not deref | ||
419 | resize( len ); | ||
420 | memcpy( shd->data, d, len ); | ||
421 | } | ||
422 | |||
423 | |||
424 | /*! | ||
425 | \fn array_data *QGArray::sharedBlock() const | ||
426 | |||
427 | Returns a pointer to the shared array block. | ||
428 | |||
429 | \warning | ||
430 | |||
431 | 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 | ||
433 | discourage new use of it. | ||
434 | */ | ||
435 | |||
436 | /*! | ||
437 | \fn void QGArray::setSharedBlock( array_data *p ) | ||
438 | |||
439 | Sets the shared array block to \a p. | ||
440 | |||
441 | \warning | ||
442 | |||
443 | 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 | ||
445 | discourage new use of it. | ||
446 | */ | ||
447 | |||
448 | |||
449 | /*! | ||
450 | Sets raw data and returns a reference to the array. | ||
451 | |||
452 | 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 | ||
454 | array data when raw data has been set. | ||
455 | Call resetRawData(d,len) to reset the array. | ||
456 | |||
457 | Setting raw data is useful because it sets QMemArray data without | ||
458 | allocating memory or copying data. | ||
459 | |||
460 | Example of intended use: | ||
461 | \code | ||
462 | static uchar bindata[] = { 231, 1, 44, ... }; | ||
463 | QByteArraya; | ||
464 | a.setRawData( bindata, sizeof(bindata) );// a points to bindata | ||
465 | QDataStream s( a, IO_ReadOnly ); // open on a's data | ||
466 | s >> <something>; // read raw bindata | ||
467 | s.close(); | ||
468 | a.resetRawData( bindata, sizeof(bindata) ); // finished | ||
469 | \endcode | ||
470 | |||
471 | Example of misuse (do not do this): | ||
472 | \code | ||
473 | static uchar bindata[] = { 231, 1, 44, ... }; | ||
474 | QByteArraya, b; | ||
475 | a.setRawData( bindata, sizeof(bindata) );// a points to bindata | ||
476 | a.resize( 8 ); // will crash | ||
477 | b = a; // will crash | ||
478 | a[2] = 123; // might crash | ||
479 | // forget to resetRawData - will crash | ||
480 | \endcode | ||
481 | |||
482 | \warning If you do not call resetRawData(), QGArray will attempt to | ||
483 | deallocate or reallocate the raw data, which might not be too good. | ||
484 | Be careful. | ||
485 | */ | ||
486 | |||
487 | QGArray &QGArray::setRawData( const char *d, uint len ) | ||
488 | { | ||
489 | duplicate( 0, 0 ); // set null data | ||
490 | shd->data = (char *)d; | ||
491 | shd->len = len; | ||
492 | return *this; | ||
493 | } | ||
494 | |||
495 | /*! | ||
496 | Resets raw data. | ||
497 | |||
498 | The arguments must be the data, \a d, and length \a len, that were | ||
499 | passed to setRawData(). This is for consistency checking. | ||
500 | */ | ||
501 | |||
502 | void QGArray::resetRawData( const char *d, uint len ) | ||
503 | { | ||
504 | if ( d != shd->data || len != shd->len ) { | ||
505 | #if defined(QT_CHECK_STATE) | ||
506 | qWarning( "QGArray::resetRawData: Inconsistent arguments" ); | ||
507 | #endif | ||
508 | return; | ||
509 | } | ||
510 | shd->data = 0; | ||
511 | shd->len = 0; | ||
512 | } | ||
513 | |||
514 | |||
515 | /*! | ||
516 | Finds the first occurrence of \a d in the array from position \a index, | ||
517 | where \a sz is the size of the \a d element. | ||
518 | |||
519 | Note that \a index is given in units of \a sz, not bytes. | ||
520 | |||
521 | This function only compares whole cells, not bytes. | ||
522 | */ | ||
523 | |||
524 | int QGArray::find( const char *d, uint index, uint sz ) const | ||
525 | { | ||
526 | index *= sz; | ||
527 | if ( index >= shd->len ) { | ||
528 | #if defined(QT_CHECK_RANGE) | ||
529 | qWarning( "QGArray::find: Index %d out of range", index/sz ); | ||
530 | #endif | ||
531 | return -1; | ||
532 | } | ||
533 | register uint i; | ||
534 | uint ii; | ||
535 | switch ( sz ) { | ||
536 | case 1: { // 8 bit elements | ||
537 | register char *x = data() + index; | ||
538 | char v = *d; | ||
539 | for ( i=index; i<shd->len; i++ ) { | ||
540 | if ( *x++ == v ) | ||
541 | break; | ||
542 | } | ||
543 | ii = i; | ||
544 | } | ||
545 | break; | ||
546 | case 2: { // 16 bit elements | ||
547 | register Q_INT16 *x = (Q_INT16*)(data() + index); | ||
548 | Q_INT16 v = *((Q_INT16*)d); | ||
549 | for ( i=index; i<shd->len; i+=2 ) { | ||
550 | if ( *x++ == v ) | ||
551 | break; | ||
552 | } | ||
553 | ii = i/2; | ||
554 | } | ||
555 | break; | ||
556 | case 4: { // 32 bit elements | ||
557 | register Q_INT32 *x = (Q_INT32*)(data() + index); | ||
558 | Q_INT32 v = *((Q_INT32*)d); | ||
559 | for ( i=index; i<shd->len; i+=4 ) { | ||
560 | if ( *x++ == v ) | ||
561 | break; | ||
562 | } | ||
563 | ii = i/4; | ||
564 | } | ||
565 | break; | ||
566 | default: { // any size elements | ||
567 | for ( i=index; i<shd->len; i+=sz ) { | ||
568 | if ( memcmp( d, &shd->data[i], sz ) == 0 ) | ||
569 | break; | ||
570 | } | ||
571 | ii = i/sz; | ||
572 | } | ||
573 | break; | ||
574 | } | ||
575 | return i<shd->len ? (int)ii : -1; | ||
576 | } | ||
577 | |||
578 | /*! | ||
579 | Returns the number of occurrences of \a d in the array, where \a sz is | ||
580 | the size of the \a d element. | ||
581 | |||
582 | This function only compares whole cells, not bytes. | ||
583 | */ | ||
584 | |||
585 | int QGArray::contains( const char *d, uint sz ) const | ||
586 | { | ||
587 | register uint i = shd->len; | ||
588 | int count = 0; | ||
589 | switch ( sz ) { | ||
590 | case 1: { // 8 bit elements | ||
591 | register char *x = data(); | ||
592 | char v = *d; | ||
593 | while ( i-- ) { | ||
594 | if ( *x++ == v ) | ||
595 | count++; | ||
596 | } | ||
597 | } | ||
598 | break; | ||
599 | case 2: { // 16 bit elements | ||
600 | register Q_INT16 *x = (Q_INT16*)data(); | ||
601 | Q_INT16 v = *((Q_INT16*)d); | ||
602 | i /= 2; | ||
603 | while ( i-- ) { | ||
604 | if ( *x++ == v ) | ||
605 | count++; | ||
606 | } | ||
607 | } | ||
608 | break; | ||
609 | case 4: { // 32 bit elements | ||
610 | register Q_INT32 *x = (Q_INT32*)data(); | ||
611 | Q_INT32 v = *((Q_INT32*)d); | ||
612 | i /= 4; | ||
613 | while ( i-- ) { | ||
614 | if ( *x++ == v ) | ||
615 | count++; | ||
616 | } | ||
617 | } | ||
618 | break; | ||
619 | default: { // any size elements | ||
620 | for ( i=0; i<shd->len; i+=sz ) { | ||
621 | if ( memcmp(d, &shd->data[i], sz) == 0 ) | ||
622 | count++; | ||
623 | } | ||
624 | } | ||
625 | break; | ||
626 | } | ||
627 | return count; | ||
628 | } | ||
629 | |||
630 | static int cmp_item_size = 0; | ||
631 | |||
632 | #if defined(Q_C_CALLBACKS) | ||
633 | extern "C" { | ||
634 | #endif | ||
635 | |||
636 | #ifdef Q_OS_TEMP | ||
637 | static int __cdecl cmp_arr( const void *n1, const void *n2 ) | ||
638 | #else | ||
639 | static int cmp_arr( const void *n1, const void *n2 ) | ||
640 | #endif | ||
641 | { | ||
642 | return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) | ||
643 | : ( n1 ? 1 : ( n2 ? -1 : 0 ) ); | ||
644 | // ### Qt 3.0: Add a virtual compareItems() method and call that instead | ||
645 | } | ||
646 | |||
647 | #if defined(Q_C_CALLBACKS) | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | /*! | ||
652 | Sorts the first \a sz items of the array. | ||
653 | */ | ||
654 | |||
655 | void QGArray::sort( uint sz ) | ||
656 | { | ||
657 | int numItems = size() / sz; | ||
658 | if ( numItems < 2 ) | ||
659 | return; | ||
660 | |||
661 | #ifdef QT_THREAD_SUPPORT | ||
662 | QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); | ||
663 | #endif // QT_THREAD_SUPPORT | ||
664 | |||
665 | cmp_item_size = sz; | ||
666 | qsort( shd->data, numItems, sz, cmp_arr ); | ||
667 | } | ||
668 | |||
669 | /*! | ||
670 | Binary search; assumes that \a d is a sorted array of size \a sz. | ||
671 | */ | ||
672 | |||
673 | int QGArray::bsearch( const char *d, uint sz ) const | ||
674 | { | ||
675 | int numItems = size() / sz; | ||
676 | if ( !numItems ) | ||
677 | return -1; | ||
678 | |||
679 | #ifdef QT_THREAD_SUPPORT | ||
680 | QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); | ||
681 | #endif // QT_THREAD_SUPPORT | ||
682 | |||
683 | cmp_item_size = sz; | ||
684 | char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr ); | ||
685 | if ( !r ) | ||
686 | return -1; | ||
687 | while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) ) | ||
688 | r -= sz;// search to first of equal elements; bsearch is undef | ||
689 | return (int)(( r - shd->data ) / sz); | ||
690 | } | ||
691 | |||
692 | |||
693 | /*! | ||
694 | \fn char *QGArray::at( uint index ) const | ||
695 | |||
696 | Returns a pointer to the byte at offset \a index in the array. | ||
697 | */ | ||
698 | |||
699 | /*! | ||
700 | Expand the array if necessary, and copies (the first part of) its | ||
701 | contents from the \a index * \a sz bytes at \a d. | ||
702 | |||
703 | Returns TRUE if the operation succeeds, FALSE if it runs out of | ||
704 | memory. | ||
705 | |||
706 | \warning This function disregards the reference count mechanism. If | ||
707 | other QGArrays reference the same data as this, all will be changed. | ||
708 | */ | ||
709 | |||
710 | bool QGArray::setExpand( uint index, const char *d, uint sz ) | ||
711 | { | ||
712 | index *= sz; | ||
713 | if ( index >= shd->len ) { | ||
714 | if ( !resize( index+sz ) ) // no memory | ||
715 | return FALSE; | ||
716 | } | ||
717 | memcpy( data() + index, d, sz ); | ||
718 | return TRUE; | ||
719 | } | ||
720 | |||
721 | |||
722 | /*! | ||
723 | Prints a warning message if at() or [] is given a bad index. | ||
724 | */ | ||
725 | |||
726 | void QGArray::msg_index( uint index ) | ||
727 | { | ||
728 | #if defined(QT_CHECK_RANGE) | ||
729 | qWarning( "QGArray::at: Absolute index %d out of range", index ); | ||
730 | #else | ||
731 | Q_UNUSED( index ) | ||
732 | #endif | ||
733 | } | ||
734 | |||
735 | |||
736 | /*! | ||
737 | Returns a new shared array block. | ||
738 | */ | ||
739 | |||
740 | QGArray::array_data * QGArray::newData() | ||
741 | { | ||
742 | return new array_data; | ||
743 | } | ||
744 | |||
745 | |||
746 | /*! | ||
747 | Deletes the shared array block, \a p. | ||
748 | */ | ||
749 | |||
750 | void QGArray::deleteData( array_data *p ) | ||
751 | { | ||
752 | delete p; | ||
753 | p = 0; | ||
754 | } | ||