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