1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the Qt 3 compatibility classes of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
31
// needed for qsort() because of a std namespace problem on Borland
32
# include "qplatformdefs.h"
33
#elif defined(Q_WS_WIN)
34
// needed for bsearch on some platforms
35
# include "qt_windows.h"
43
#ifdef QT_THREAD_SUPPORT
44
# include <private/qmutexpool_p.h>
45
#endif // QT_THREAD_SUPPORT
48
If USE_MALLOC isn't defined, we use new[] and delete[] to allocate
49
memory. The documentation for QMemArray<T>::assign() explicitly
50
mentions that the array is freed using free(), so don't mess around
51
with USE_MALLOC unless you know what you're doing.
58
#if defined(USE_MALLOC)
59
#define NEW(type,size) ((type*)malloc(size*sizeof(type)))
60
#define DELETE(array) (free((char*)array))
62
#define NEW(type,size) (new type[size])
63
#define DELETE(array) (delete[] array)
64
#define DONT_USE_REALLOC // comment to use realloc()
70
\brief The Q3GArray class is an internal class for implementing the QMemArray class.
74
Q3GArray is a strictly internal class that acts as base class for the
75
QMemArray template array.
77
It contains an array of bytes and has no notion of an array element.
82
Constructs a null array.
92
Dummy constructor; does not allocate any data.
94
This constructor does not initialize any array data so subclasses
95
must do it. The intention is to make the code more efficient.
98
Q3GArray::Q3GArray(int, int)
103
Constructs an array with room for \a size bytes.
106
Q3GArray::Q3GArray(int size)
109
#if defined(QT_CHECK_RANGE)
110
qWarning("Q3GArray: Cannot allocate array with negative length");
116
if (size == 0) // zero length
118
shd->data = NEW(char,size);
119
Q_CHECK_PTR(shd->data);
121
#ifdef QT_Q3GARRAY_SPEED_OPTIM
128
Constructs a shallow copy of \a a.
131
Q3GArray::Q3GArray(const Q3GArray &a)
138
Dereferences the array data and deletes it if this was the last
142
Q3GArray::~Q3GArray()
144
if (shd && shd->deref()) { // delete when last reference
145
if (shd->data) // is lost
154
\fn Q3GArray &Q3GArray::operator=(const Q3GArray &a)
156
Assigns a shallow copy of \a a to this array and returns a reference to
157
this array. Equivalent to assign().
161
\fn void Q3GArray::detach()
163
Detaches this array from shared array data.
167
\fn char *Q3GArray::data() const
169
Returns a pointer to the actual array data.
173
\fn uint Q3GArray::nrefs() const
175
Returns the reference count.
179
\fn uint Q3GArray::size() const
181
Returns the size of the array, in bytes.
186
Returns true if this array is equal to \a a, otherwise false.
187
The comparison is bitwise, of course.
190
bool Q3GArray::isEqual(const Q3GArray &a) const
192
if (size() != a.size()) // different size
194
if (data() == a.data()) // has same data
196
return (size() ? memcmp(data(), a.data(), size()) : 0) == 0;
201
Resizes the array to \a newsize bytes. \a optim is either
202
MemOptim (the default) or SpeedOptim.
204
bool Q3GArray::resize(uint newsize, Optimization optim)
206
#ifndef QT_Q3GARRAY_SPEED_OPTIM
210
if (newsize == shd->len
211
#ifdef QT_Q3GARRAY_SPEED_OPTIM
212
&& newsize == shd->maxl
216
if (newsize == 0) { // remove array
221
#ifdef QT_Q3GARRAY_SPEED_OPTIM
227
uint newmaxl = newsize;
228
#ifdef QT_Q3GARRAY_SPEED_OPTIM
229
if (optim == SpeedOptim) {
230
if (newsize <= shd->maxl &&
231
(newsize * 4 > shd->maxl || shd->maxl <= 4)) {
236
while (newmaxl < newsize)
238
// try to spare some memory
239
if (newmaxl >= 1024 * 1024 && newsize <= newmaxl - (newmaxl >> 2))
240
newmaxl -= newmaxl >> 2;
245
if (shd->data) { // existing data
246
#if defined(DONT_USE_REALLOC)
247
char *newdata = NEW(char,newsize); // manual realloc
248
memcpy(newdata, shd->data, QMIN(shd->len,newmaxl));
252
shd->data = (char *)realloc(shd->data, newmaxl);
255
shd->data = NEW(char,newmaxl);
257
if (!shd->data) // no memory
265
bool Q3GArray::resize(uint newsize)
267
return resize(newsize, MemOptim);
272
Fills the array with the repeated occurrences of \a d, which is
274
If \a len is specified as different from -1, then the array will be
275
resized to \a len*sz before it is filled.
277
Returns true if successful, or false if the memory cannot be allocated
278
(only when \a len != -1).
283
bool Q3GArray::fill(const char *d, int len, uint sz)
286
len = shd->len/sz; // default: use array length
287
else if (!resize(len*sz))
289
if (sz == 1) // 8 bit elements
290
memset(data(), *d, len);
291
else if (sz == 4) { // 32 bit elements
292
register Q_INT32 *x = (Q_INT32*)data();
293
Q_INT32 v = *((Q_INT32*)d);
296
} else if (sz == 2) { // 16 bit elements
297
register Q_INT16 *x = (Q_INT16*)data();
298
Q_INT16 v = *((Q_INT16*)d);
301
} else { // any other size elements
302
register char *x = data();
303
while (len--) { // more complicated
313
Shallow copy. Dereference the current array and references the data
314
contained in \a a instead. Returns a reference to this array.
318
Q3GArray &Q3GArray::assign(const Q3GArray &a)
320
a.shd->ref(); // avoid 'a = a'
321
if (shd->deref()) { // delete when last reference
322
if (shd->data) // is lost
331
Shallow copy. Dereference the current array and references the
332
array data \a d, which contains \a len bytes.
333
Returns a reference to this array.
335
Do not delete \a d later, because Q3GArray takes care of that.
338
Q3GArray &Q3GArray::assign(const char *d, uint len)
340
if (shd->count > 1) { // disconnect this
348
shd->data = (char *)d;
350
#ifdef QT_Q3GARRAY_SPEED_OPTIM
358
Deep copy. Dereference the current array and obtains a copy of the data
359
contained in \a a instead. Returns a reference to this array.
360
\sa assign(), operator=()
363
Q3GArray &Q3GArray::duplicate(const Q3GArray &a)
365
if (a.shd == shd) { // a.duplicate(a) !
366
if (shd->count > 1) {
368
register array_data *n = newData();
370
if ((n->len=shd->len)) {
371
n->data = NEW(char,n->len);
372
Q_CHECK_PTR(n->data);
374
memcpy(n->data, shd->data, n->len);
383
if (shd->count > 1) { // disconnect this
387
} else { // delete after copy was made
390
if (a.shd->len) { // duplicate data
391
shd->data = NEW(char,a.shd->len);
392
Q_CHECK_PTR(shd->data);
394
memcpy(shd->data, a.shd->data, a.shd->len);
399
#ifdef QT_Q3GARRAY_SPEED_OPTIM
410
Deep copy. Dereferences the current array and obtains a copy of
411
\a len characters from array data \a d instead. Returns a reference
413
\sa assign(), operator=()
416
Q3GArray &Q3GArray::duplicate(const char *d, uint len)
419
if (d == 0 || len == 0) {
423
if (shd->count == 1 && shd->len == len) {
424
if (shd->data != d) // avoid self-assignment
425
memcpy(shd->data, d, len); // use same buffer
428
data = NEW(char,len);
430
memcpy(data, d, len);
432
if (shd->count > 1) { // detach
436
} else { // just a single reference
442
#ifdef QT_Q3GARRAY_SPEED_OPTIM
450
Resizes this array to \a len bytes and copies the \a len bytes at
451
address \a d into it.
453
\warning This function disregards the reference count mechanism. If
454
other Q3GArrays reference the same data as this, all will be updated.
457
void Q3GArray::store(const char *d, uint len)
458
{ // store, but not deref
460
memcpy(shd->data, d, len);
465
\fn array_data *Q3GArray::sharedBlock() const
467
Returns a pointer to the shared array block.
471
Do not use this function. Using it is begging for trouble. We dare
472
not remove it, for fear of breaking code, but we \e strongly
473
discourage new use of it.
477
\fn void Q3GArray::setSharedBlock(array_data *p)
479
Sets the shared array block to \a p.
483
Do not use this function. Using it is begging for trouble. We dare
484
not remove it, for fear of breaking code, but we \e strongly
485
discourage new use of it.
490
Sets raw data and returns a reference to the array.
492
Dereferences the current array and sets the new array data to \a d and
493
the new array size to \a len. Do not attempt to resize or re-assign the
494
array data when raw data has been set.
495
Call resetRawData(d,len) to reset the array.
497
Setting raw data is useful because it sets QMemArray data without
498
allocating memory or copying data.
500
Example of intended use:
502
static uchar bindata[] = { 231, 1, 44, ... };
504
a.setRawData(bindata, sizeof(bindata)); // a points to bindata
505
QDataStream s(a, IO_ReadOnly); // open on a's data
506
s >> <something>; // read raw bindata
508
a.resetRawData(bindata, sizeof(bindata)); // finished
511
Example of misuse (do not do this):
513
static uchar bindata[] = { 231, 1, 44, ... };
515
a.setRawData(bindata, sizeof(bindata)); // a points to bindata
516
a.resize(8); // will crash
518
a[2] = 123; // might crash
519
// forget to resetRawData - will crash
522
\warning If you do not call resetRawData(), Q3GArray will attempt to
523
deallocate or reallocate the raw data, which might not be too good.
527
Q3GArray &Q3GArray::setRawData(const char *d, uint len)
529
duplicate(0, 0); // set null data
530
shd->data = (char *)d;
538
The arguments must be the data, \a d, and length \a len, that were
539
passed to setRawData(). This is for consistency checking.
542
void Q3GArray::resetRawData(const char *d, uint len)
544
if (d != shd->data || len != shd->len) {
545
#if defined(QT_CHECK_STATE)
546
qWarning("Q3GArray::resetRawData: Inconsistent arguments");
556
Finds the first occurrence of \a d in the array from position \a index,
557
where \a sz is the size of the \a d element.
559
Note that \a index is given in units of \a sz, not bytes.
561
This function only compares whole cells, not bytes.
564
int Q3GArray::find(const char *d, uint index, uint sz) const
567
if (index >= shd->len) {
568
#if defined(QT_CHECK_RANGE)
569
qWarning("Q3GArray::find: Index %d out of range", index/sz);
576
case 1: { // 8 bit elements
577
register char *x = data() + index;
579
for (i=index; i<shd->len; i++) {
586
case 2: { // 16 bit elements
587
register Q_INT16 *x = (Q_INT16*)(data() + index);
588
Q_INT16 v = *((Q_INT16*)d);
589
for (i=index; i<shd->len; i+=2) {
596
case 4: { // 32 bit elements
597
register Q_INT32 *x = (Q_INT32*)(data() + index);
598
Q_INT32 v = *((Q_INT32*)d);
599
for (i=index; i<shd->len; i+=4) {
606
default: { // any size elements
607
for (i=index; i<shd->len; i+=sz) {
608
if (memcmp(d, &shd->data[i], sz) == 0)
615
return i<shd->len ? (int)ii : -1;
619
Returns the number of occurrences of \a d in the array, where \a sz is
620
the size of the \a d element.
622
This function only compares whole cells, not bytes.
625
int Q3GArray::contains(const char *d, uint sz) const
627
register uint i = shd->len;
630
case 1: { // 8 bit elements
631
register char *x = data();
639
case 2: { // 16 bit elements
640
register Q_INT16 *x = (Q_INT16*)data();
641
Q_INT16 v = *((Q_INT16*)d);
649
case 4: { // 32 bit elements
650
register Q_INT32 *x = (Q_INT32*)data();
651
Q_INT32 v = *((Q_INT32*)d);
659
default: { // any size elements
660
for (i=0; i<shd->len; i+=sz) {
661
if (memcmp(d, &shd->data[i], sz) == 0)
670
static int cmp_item_size = 0;
672
#if defined(Q_C_CALLBACKS)
677
static int __cdecl cmp_arr(const void *n1, const void *n2)
679
static int cmp_arr(const void *n1, const void *n2)
682
return (n1 && n2) ? memcmp(n1, n2, cmp_item_size)
683
: (n1 ? 1 : (n2 ? -1 : 0));
684
// ### Qt 3.0: Add a virtual compareItems() method and call that instead
687
#if defined(Q_C_CALLBACKS)
692
Sorts the first \a sz items of the array.
695
void Q3GArray::sort(uint sz)
697
int numItems = size() / sz;
701
#ifdef QT_THREAD_SUPPORT
702
QMutexLocker locker(qt_global_mutexpool ?
703
qt_global_mutexpool->get(&cmp_item_size) : 0);
704
#endif // QT_THREAD_SUPPORT
707
qsort(shd->data, numItems, sz, cmp_arr);
711
Binary search; assumes that \a d is a sorted array of size \a sz.
714
int Q3GArray::bsearch(const char *d, uint sz) const
716
int numItems = size() / sz;
720
#ifdef QT_THREAD_SUPPORT
721
QMutexLocker locker(qt_global_mutexpool ?
722
qt_global_mutexpool->get(&cmp_item_size) : 0);
723
#endif // QT_THREAD_SUPPORT
726
char* r = (char*)::bsearch(d, shd->data, numItems, sz, cmp_arr);
729
while((r >= shd->data + sz) && (cmp_arr(r - sz, d) == 0))
730
r -= sz; // search to first of equal elements; bsearch is undef
731
return (int)((r - shd->data) / sz);
736
\fn char *Q3GArray::at(uint index) const
738
Returns a pointer to the byte at offset \a index in the array.
742
Expand the array if necessary, and copies (the first part of) its
743
contents from the \a index * \a sz bytes at \a d.
745
Returns true if the operation succeeds, false if it runs out of
748
\warning This function disregards the reference count mechanism. If
749
other Q3GArrays reference the same data as this, all will be changed.
752
bool Q3GArray::setExpand(uint index, const char *d, uint sz)
755
if (index >= shd->len) {
756
if (!resize(index+sz)) // no memory
759
memcpy(data() + index, d, sz);
765
Prints a warning message if at() or [] is given a bad index.
768
void Q3GArray::msg_index(uint index)
770
#if defined(QT_CHECK_RANGE)
771
qWarning("Q3GArray::at: Absolute index %d out of range", index);
779
Returns a new shared array block.
782
Q3GArray::array_data * Q3GArray::newData()
784
return new array_data;
789
Deletes the shared array block \a p.
792
void Q3GArray::deleteData(array_data *p)