-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 | |||
@@ -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 | ||
103 | QGArray::QGArray() | 113 | QGArray::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 | ||
116 | QGArray::QGArray( int, int ) | 126 | QGArray::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 | ||
124 | QGArray::QGArray( int size ) | 134 | QGArray::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 | ||
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 | ||
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 | ||
156 | QGArray::~QGArray() | 170 | QGArray::~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 | ||
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 | ||
256 | bool QGArray::fill( const char *d, int len, uint sz ) | 305 | bool 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 | ||
291 | QGArray &QGArray::assign( const QGArray &a ) | 340 | QGArray &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 | ||
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) ! |
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 | ||
381 | QGArray &QGArray::duplicate( const char *d, uint len ) | 438 | QGArray &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 | ||
417 | void QGArray::store( const char *d, uint len ) | 478 | void 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 | ||
630 | static int cmp_item_size = 0; | 691 | static int cmp_item_size = 0; |
631 | 692 | ||
632 | #if defined(Q_C_CALLBACKS) | 693 | #if defined(Q_C_CALLBACKS) |
633 | extern "C" { | 694 | extern "C" { |
634 | #endif | 695 | #endif |
635 | 696 | ||
636 | #ifdef Q_OS_TEMP | 697 | #ifdef Q_OS_TEMP |
637 | static int __cdecl cmp_arr( const void *n1, const void *n2 ) | 698 | static int __cdecl cmp_arr( const void *n1, const void *n2 ) |
638 | #else | 699 | #else |
639 | static int cmp_arr( const void *n1, const void *n2 ) | 700 | static 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 | ||
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 | ||
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 | ||
710 | bool QGArray::setExpand( uint index, const char *d, uint sz ) | 773 | bool 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 | ||
726 | void QGArray::msg_index( uint index ) | 789 | void QGArray::msg_index( uint index ) |
727 | { | 790 | { |
728 | #if defined(QT_CHECK_RANGE) | 791 | #if defined(QT_CHECK_RANGE) |