Blame qtools/qgarray.cpp

Packit 1c1d7e
/****************************************************************************
Packit 1c1d7e
** 
Packit 1c1d7e
**
Packit 1c1d7e
** Implementation of QGArray class
Packit 1c1d7e
**
Packit 1c1d7e
** Created : 930906
Packit 1c1d7e
**
Packit 1c1d7e
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is part of the tools module of the Qt GUI Toolkit.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed under the terms of the Q Public License
Packit 1c1d7e
** as defined by Trolltech AS of Norway and appearing in the file
Packit 1c1d7e
** LICENSE.QPL included in the packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed and/or modified under the terms of the
Packit 1c1d7e
** GNU General Public License version 2 as published by the Free Software
Packit 1c1d7e
** Foundation and appearing in the file LICENSE.GPL included in the
Packit 1c1d7e
** packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
Packit 1c1d7e
** licenses may use this file in accordance with the Qt Commercial License
Packit 1c1d7e
** Agreement provided with the Software.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
Packit 1c1d7e
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Packit 1c1d7e
**
Packit 1c1d7e
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
Packit 1c1d7e
**   information about Qt Commercial License Agreements.
Packit 1c1d7e
** See http://www.trolltech.com/qpl/ for QPL licensing information.
Packit 1c1d7e
** See http://www.trolltech.com/gpl/ for GPL licensing information.
Packit 1c1d7e
**
Packit 1c1d7e
** Contact info@trolltech.com if any conditions of this licensing are
Packit 1c1d7e
** not clear to you.
Packit 1c1d7e
**
Packit 1c1d7e
**********************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#define	 QGARRAY_CPP
Packit 1c1d7e
#include "qgarray.h"
Packit 1c1d7e
#include "qstring.h"
Packit 1c1d7e
#include <stdlib.h>
Packit 1c1d7e
Packit 1c1d7e
#define USE_MALLOC				// comment to use new/delete
Packit 1c1d7e
Packit 1c1d7e
#undef NEW
Packit 1c1d7e
#undef DELETE
Packit 1c1d7e
Packit 1c1d7e
#if defined(USE_MALLOC)
Packit 1c1d7e
#define NEW(type,size)	((type*)malloc(size*sizeof(type)))
Packit 1c1d7e
#define DELETE(array)	(free((char*)array))
Packit 1c1d7e
#else
Packit 1c1d7e
#define NEW(type,size)	(new type[size])
Packit 1c1d7e
#define DELETE(array)	(delete[] array)
Packit 1c1d7e
#define DONT_USE_REALLOC			// comment to use realloc()
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
// NOT REVISED
Packit 1c1d7e
/*!
Packit 1c1d7e
  \class QShared qshared.h
Packit 1c1d7e
  \brief The QShared struct is internally used for implementing shared classes.
Packit 1c1d7e
Packit 1c1d7e
  It only contains a reference count and member functions to increment and
Packit 1c1d7e
  decrement it.
Packit 1c1d7e
Packit 1c1d7e
  Shared classes normally have internal classes that inherit QShared and
Packit 1c1d7e
  add the shared data.
Packit 1c1d7e
Packit 1c1d7e
  \sa \link shclass.html Shared Classes\endlink
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \class QGArray qgarray.h
Packit 1c1d7e
  \brief The QGArray class is an internal class for implementing the QArray class.
Packit 1c1d7e
Packit 1c1d7e
  QGArray is a strictly internal class that acts as base class for the
Packit 1c1d7e
  QArray template array.
Packit 1c1d7e
Packit 1c1d7e
  It contains an array of bytes and has no notion of an array element.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs a null array.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::QGArray()
Packit 1c1d7e
{
Packit 1c1d7e
    shd = newData();
Packit 1c1d7e
    CHECK_PTR( shd );
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Dummy constructor; does not allocate any data.
Packit 1c1d7e
Packit 1c1d7e
  This constructor does not initialize any array data so subclasses
Packit 1c1d7e
  must do it. The intention is to make the code more efficient.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::QGArray( int, int )
Packit 1c1d7e
{
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs an array with room for \e size bytes.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::QGArray( int size )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( size < 0 ) {
Packit 1c1d7e
#if defined(CHECK_RANGE)
Packit 1c1d7e
	qWarning( "QGArray: Cannot allocate array with negative length" );
Packit 1c1d7e
#endif
Packit 1c1d7e
	size = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
    shd = newData();
Packit 1c1d7e
    CHECK_PTR( shd );
Packit 1c1d7e
    if ( size == 0 )				// zero length
Packit 1c1d7e
	return;
Packit 1c1d7e
    shd->data = NEW(char,size);
Packit 1c1d7e
    CHECK_PTR( shd->data );
Packit 1c1d7e
    shd->len = size;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs a shallow copy of \e a.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::QGArray( const QGArray &a )
Packit 1c1d7e
{
Packit 1c1d7e
    shd = a.shd;
Packit 1c1d7e
    shd->ref();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Dereferences the array data and deletes it if this was the last
Packit 1c1d7e
  reference.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::~QGArray()
Packit 1c1d7e
{
Packit 1c1d7e
    if ( shd && shd->deref() ) {		// delete when last reference
Packit 1c1d7e
	if ( shd->data )			// is lost
Packit 1c1d7e
	    DELETE(shd->data);
Packit 1c1d7e
	deleteData( shd );
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn QGArray &QGArray::operator=( const QGArray &a )
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Assigns a shallow copy of \e a to this array and returns a reference to
Packit 1c1d7e
  this array.  Equivalent to assign().
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn void QGArray::detach()
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Detaches this array from shared array data.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn char *QGArray::data() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns a pointer to the actual array data.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn uint QGArray::nrefs() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the reference count.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn uint QGArray::size() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the size of the array, in bytes.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns TRUE if this array is equal to \e a, otherwise FALSE.
Packit 1c1d7e
  The comparison is bitwise, of course.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGArray::isEqual( const QGArray &a ) const
Packit 1c1d7e
{
Packit 1c1d7e
    if ( size() != a.size() )			// different size
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
    if ( data() == a.data() )			// has same data
Packit 1c1d7e
	return TRUE;
Packit 1c1d7e
    return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Resizes the array to \e newsize bytes.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGArray::resize( uint newsize )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( newsize == shd->len )			// nothing to do
Packit 1c1d7e
	return TRUE;
Packit 1c1d7e
    if ( newsize == 0 ) {			// remove array
Packit 1c1d7e
	duplicate( 0, 0 );
Packit 1c1d7e
	return TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
    if ( shd->data ) {				// existing data
Packit 1c1d7e
#if defined(DONT_USE_REALLOC)
Packit 1c1d7e
	char *newdata = NEW(char,newsize);	// manual realloc
Packit 1c1d7e
	memcpy( newdata, shd->data, QMIN(shd->len,newsize) );
Packit 1c1d7e
	DELETE(shd->data);
Packit 1c1d7e
	shd->data = newdata;
Packit 1c1d7e
#else
Packit 1c1d7e
	shd->data = (char *)realloc( shd->data, newsize );
Packit 1c1d7e
#endif
Packit 1c1d7e
    } else {
Packit 1c1d7e
	shd->data = NEW(char,newsize);
Packit 1c1d7e
    }
Packit 1c1d7e
    CHECK_PTR( shd->data );
Packit 1c1d7e
    if ( !shd->data )				// no memory
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
    shd->len = newsize;
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Fills the array with the repeated occurrences of \e d, which is
Packit 1c1d7e
  \e sz bytes long.
Packit 1c1d7e
  If \e len is specified as different from -1, then the array will be
Packit 1c1d7e
  resized to \e len*sz before it is filled.
Packit 1c1d7e
Packit 1c1d7e
  Returns TRUE if successful, or FALSE if the memory cannot be allocated
Packit 1c1d7e
  (only when \e len != -1).
Packit 1c1d7e
Packit 1c1d7e
  \sa resize()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGArray::fill( const char *d, int len, uint sz )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( len < 0 )
Packit 1c1d7e
	len = shd->len/sz;			// default: use array length
Packit 1c1d7e
    else if ( !resize( len*sz ) )
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
    if ( sz == 1 )				// 8 bit elements
Packit 1c1d7e
	memset( data(), *d, len );
Packit 1c1d7e
    else if ( sz == 4 ) {			// 32 bit elements
Packit 1c1d7e
	register Q_INT32 *x = (Q_INT32*)data();
Packit 1c1d7e
	Q_INT32 v = *((Q_INT32*)d);
Packit 1c1d7e
	while ( len-- )
Packit 1c1d7e
	    *x++ = v;
Packit 1c1d7e
    } else if ( sz == 2 ) {			// 16 bit elements
Packit 1c1d7e
	register Q_INT16 *x = (Q_INT16*)data();
Packit 1c1d7e
	Q_INT16 v = *((Q_INT16*)d);
Packit 1c1d7e
	while ( len-- )
Packit 1c1d7e
	    *x++ = v;
Packit 1c1d7e
    } else {					// any other size elements
Packit 1c1d7e
	register char *x = data();
Packit 1c1d7e
	while ( len-- ) {			// more complicated
Packit 1c1d7e
	    memcpy( x, d, sz );
Packit 1c1d7e
	    x += sz;
Packit 1c1d7e
	}
Packit 1c1d7e
    }
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Shallow copy. Dereference the current array and references the data
Packit 1c1d7e
  contained in \e a instead. Returns a reference to this array.
Packit 1c1d7e
  \sa operator=()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray &QGArray::assign( const QGArray &a )
Packit 1c1d7e
{
Packit 1c1d7e
    a.shd->ref();				// avoid 'a = a'
Packit 1c1d7e
    if ( shd->deref() ) {			// delete when last reference
Packit 1c1d7e
	if ( shd->data )			// is lost
Packit 1c1d7e
	    DELETE(shd->data);
Packit 1c1d7e
	deleteData( shd );
Packit 1c1d7e
    }
Packit 1c1d7e
    shd = a.shd;
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Shallow copy. Dereference the current array and references the
Packit 1c1d7e
  array data \e d, which contains \e len bytes.
Packit 1c1d7e
  Returns a reference to this array.
Packit 1c1d7e
Packit 1c1d7e
  Do not delete \e d later, because QGArray takes care of that.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray &QGArray::assign( const char *d, uint len )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( shd->count > 1 ) {			// disconnect this
Packit 1c1d7e
	shd->count--;
Packit 1c1d7e
	shd = newData();
Packit 1c1d7e
	CHECK_PTR( shd );
Packit 1c1d7e
    } else {
Packit 1c1d7e
	if ( shd->data )
Packit 1c1d7e
	    DELETE(shd->data);
Packit 1c1d7e
    }
Packit 1c1d7e
    shd->data = (char *)d;
Packit 1c1d7e
    shd->len = len;
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Deep copy. Dereference the current array and obtains a copy of the data
Packit 1c1d7e
  contained in \e a instead. Returns a reference to this array.
Packit 1c1d7e
  \sa assign(), operator=()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray &QGArray::duplicate( const QGArray &a )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( a.shd == shd ) {			// a.duplicate(a) !
Packit 1c1d7e
	if ( shd->count > 1 ) {
Packit 1c1d7e
	    shd->count--;
Packit 1c1d7e
	    register array_data *n = newData();
Packit 1c1d7e
	    CHECK_PTR( n );
Packit 1c1d7e
	    if ( (n->len=shd->len) ) {
Packit 1c1d7e
		n->data = NEW(char,n->len);
Packit 1c1d7e
		CHECK_PTR( n->data );
Packit 1c1d7e
		if ( n->data )
Packit 1c1d7e
		    memcpy( n->data, shd->data, n->len );
Packit 1c1d7e
	    } else {
Packit 1c1d7e
		n->data = 0;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    shd = n;
Packit 1c1d7e
	}
Packit 1c1d7e
	return *this;
Packit 1c1d7e
    }
Packit 1c1d7e
    char *oldptr = 0;
Packit 1c1d7e
    if ( shd->count > 1 ) {			// disconnect this
Packit 1c1d7e
	shd->count--;
Packit 1c1d7e
	shd = newData();
Packit 1c1d7e
	CHECK_PTR( shd );
Packit 1c1d7e
    } else {					// delete after copy was made
Packit 1c1d7e
	oldptr = shd->data;
Packit 1c1d7e
    }
Packit 1c1d7e
    if ( a.shd->len ) {				// duplicate data
Packit 1c1d7e
	shd->data = NEW(char,a.shd->len);
Packit 1c1d7e
	CHECK_PTR( shd->data );
Packit 1c1d7e
	if ( shd->data )
Packit 1c1d7e
	    memcpy( shd->data, a.shd->data, a.shd->len );
Packit 1c1d7e
    } else {
Packit 1c1d7e
	shd->data = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
    shd->len = a.shd->len;
Packit 1c1d7e
    if ( oldptr )
Packit 1c1d7e
	DELETE(oldptr);
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Deep copy. Dereferences the current array and obtains a copy of the
Packit 1c1d7e
  array data \e d instead.  Returns a reference to this array.
Packit 1c1d7e
  \sa assign(), operator=()
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray &QGArray::duplicate( const char *d, uint len )
Packit 1c1d7e
{
Packit 1c1d7e
    char *data;
Packit 1c1d7e
    if ( d == 0 || len == 0 ) {
Packit 1c1d7e
	data = 0;
Packit 1c1d7e
	len  = 0;
Packit 1c1d7e
    } else {
Packit 1c1d7e
	if ( shd->count == 1 && shd->len == len ) {
Packit 1c1d7e
	    memcpy( shd->data, d, len );	// use same buffer
Packit 1c1d7e
	    return *this;
Packit 1c1d7e
	}
Packit 1c1d7e
	data = NEW(char,len);
Packit 1c1d7e
	CHECK_PTR( data );
Packit 1c1d7e
	memcpy( data, d, len );
Packit 1c1d7e
    }
Packit 1c1d7e
    if ( shd->count > 1 ) {			// detach
Packit 1c1d7e
	shd->count--;
Packit 1c1d7e
	shd = newData();
Packit 1c1d7e
	CHECK_PTR( shd );
Packit 1c1d7e
    } else {					// just a single reference
Packit 1c1d7e
	if ( shd->data )
Packit 1c1d7e
	    DELETE(shd->data);
Packit 1c1d7e
    }
Packit 1c1d7e
    shd->data = data;
Packit 1c1d7e
    shd->len  = len;
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Resizes this array to \e len bytes and copies the \e len bytes at
Packit 1c1d7e
  address \e into it.
Packit 1c1d7e
Packit 1c1d7e
  \warning This function disregards the reference count mechanism.  If
Packit 1c1d7e
  other QGArrays reference the same data as this, all will be updated.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGArray::store( const char *d, uint len )
Packit 1c1d7e
{						// store, but not deref
Packit 1c1d7e
    resize( len );
Packit 1c1d7e
    memcpy( shd->data, d, len );
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn array_data *QGArray::sharedBlock() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns a pointer to the shared array block.
Packit 1c1d7e
Packit 1c1d7e
  \warning
Packit 1c1d7e
Packit 1c1d7e
  Do not use this function.  Using it is begging for trouble.  We dare
Packit 1c1d7e
  not remove it, for fear of breaking code, but we \e strongly
Packit 1c1d7e
  discourage new use of it.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn void QGArray::setSharedBlock( array_data *p )
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Sets the shared array block to \e p.
Packit 1c1d7e
Packit 1c1d7e
  \warning
Packit 1c1d7e
Packit 1c1d7e
  Do not use this function.  Using it is begging for trouble.  We dare
Packit 1c1d7e
  not remove it, for fear of breaking code, but we \e strongly
Packit 1c1d7e
  discourage new use of it.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Sets raw data and returns a reference to the array.
Packit 1c1d7e
Packit 1c1d7e
  Dereferences the current array and sets the new array data to \e d and
Packit 1c1d7e
  the new array size to \e len.	 Do not attempt to resize or re-assign the
Packit 1c1d7e
  array data when raw data has been set.
Packit 1c1d7e
  Call resetRawData(d,len) to reset the array.
Packit 1c1d7e
Packit 1c1d7e
  Setting raw data is useful because it set QArray data without allocating
Packit 1c1d7e
  memory or copying data.
Packit 1c1d7e
Packit 1c1d7e
  Example of intended use:
Packit 1c1d7e
  \code
Packit 1c1d7e
    static uchar bindata[] = { 231, 1, 44, ... };
Packit 1c1d7e
    QByteArray	a;
Packit 1c1d7e
    a.setRawData( bindata, sizeof(bindata) );	// a points to bindata
Packit 1c1d7e
    QDataStream s( a, IO_ReadOnly );		// open on a's data
Packit 1c1d7e
    s >> <something>;				// read raw bindata
Packit 1c1d7e
    s.close();
Packit 1c1d7e
    a.resetRawData( bindata, sizeof(bindata) ); // finished
Packit 1c1d7e
  \endcode
Packit 1c1d7e
Packit 1c1d7e
  Example of misuse (do not do this):
Packit 1c1d7e
  \code
Packit 1c1d7e
    static uchar bindata[] = { 231, 1, 44, ... };
Packit 1c1d7e
    QByteArray	a, b;
Packit 1c1d7e
    a.setRawData( bindata, sizeof(bindata) );	// a points to bindata
Packit 1c1d7e
    a.resize( 8 );				// will crash
Packit 1c1d7e
    b = a;					// will crash
Packit 1c1d7e
    a[2] = 123;					// might crash
Packit 1c1d7e
      // forget to resetRawData - will crash
Packit 1c1d7e
  \endcode
Packit 1c1d7e
Packit 1c1d7e
  \warning If you do not call resetRawData(), QGArray will attempt to
Packit 1c1d7e
  deallocate or reallocate the raw data, which might not be too good.
Packit 1c1d7e
  Be careful.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray &QGArray::setRawData( const char *d, uint len )
Packit 1c1d7e
{
Packit 1c1d7e
    duplicate( 0, 0 );				// set null data
Packit 1c1d7e
    shd->data = (char *)d;
Packit 1c1d7e
    shd->len  = len;
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Resets raw data.
Packit 1c1d7e
Packit 1c1d7e
  The arguments must be the data and length that were passed to
Packit 1c1d7e
  setRawData().  This is for consistency checking.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGArray::resetRawData( const char *d, uint len )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( d != shd->data || len != shd->len ) {
Packit 1c1d7e
#if defined(CHECK_STATE)
Packit 1c1d7e
	qWarning( "QGArray::resetRawData: Inconsistent arguments" );
Packit 1c1d7e
#endif
Packit 1c1d7e
	return;
Packit 1c1d7e
    }
Packit 1c1d7e
    shd->data = 0;
Packit 1c1d7e
    shd->len  = 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Finds the first occurrence of \e d in the array from position \e index,
Packit 1c1d7e
  where \e sz is the size of the \e d element.
Packit 1c1d7e
Packit 1c1d7e
  Note that \e index is given in units of \e sz, not bytes.
Packit 1c1d7e
Packit 1c1d7e
  This function only compares whole cells, not bytes.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
int QGArray::find( const char *d, uint index, uint sz ) const
Packit 1c1d7e
{
Packit 1c1d7e
    index *= sz;
Packit 1c1d7e
    if ( index >= shd->len ) {
Packit 1c1d7e
#if defined(CHECK_RANGE)
Packit 1c1d7e
	qWarning( "QGArray::find: Index %d out of range", index/sz );
Packit 1c1d7e
#endif
Packit 1c1d7e
	return -1;
Packit 1c1d7e
    }
Packit 1c1d7e
    register uint i;
Packit 1c1d7e
    uint ii;
Packit 1c1d7e
    switch ( sz ) {
Packit 1c1d7e
	case 1: {				// 8 bit elements
Packit 1c1d7e
	    register char *x = data() + index;
Packit 1c1d7e
	    char v = *d;
Packit 1c1d7e
	    for ( i=index; i<shd->len; i++ ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    break;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    ii = i;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	case 2: {				// 16 bit elements
Packit 1c1d7e
	    register Q_INT16 *x = (Q_INT16*)(data() + index);
Packit 1c1d7e
	    Q_INT16 v = *((Q_INT16*)d);
Packit 1c1d7e
	    for ( i=index; i<shd->len; i+=2 ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    break;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    ii = i/2;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	case 4: {				// 32 bit elements
Packit 1c1d7e
	    register Q_INT32 *x = (Q_INT32*)(data() + index);
Packit 1c1d7e
	    Q_INT32 v = *((Q_INT32*)d);
Packit 1c1d7e
	    for ( i=index; i<shd->len; i+=4 ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    break;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    ii = i/4;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	default: {				// any size elements
Packit 1c1d7e
	    for ( i=index; i<shd->len; i+=sz ) {
Packit 1c1d7e
		if ( memcmp( d, &shd->data[i], sz ) == 0 )
Packit 1c1d7e
		    break;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    ii = i/sz;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
    }
Packit 1c1d7e
    return i<shd->len ? (int)ii : -1;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the number of occurrences of \e d in the array, where \e sz is
Packit 1c1d7e
  the size of the \e d element.
Packit 1c1d7e
Packit 1c1d7e
  This function only compares whole cells, not bytes.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
int QGArray::contains( const char *d, uint sz ) const
Packit 1c1d7e
{
Packit 1c1d7e
    register uint i = shd->len;
Packit 1c1d7e
    int count = 0;
Packit 1c1d7e
    switch ( sz ) {
Packit 1c1d7e
	case 1: {				// 8 bit elements
Packit 1c1d7e
	    register char *x = data();
Packit 1c1d7e
	    char v = *d;
Packit 1c1d7e
	    while ( i-- ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    count++;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	case 2: {				// 16 bit elements
Packit 1c1d7e
	    register Q_INT16 *x = (Q_INT16*)data();
Packit 1c1d7e
	    Q_INT16 v = *((Q_INT16*)d);
Packit 1c1d7e
	    i /= 2;
Packit 1c1d7e
	    while ( i-- ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    count++;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	case 4: {				// 32 bit elements
Packit 1c1d7e
	    register Q_INT32 *x = (Q_INT32*)data();
Packit 1c1d7e
	    Q_INT32 v = *((Q_INT32*)d);
Packit 1c1d7e
	    i /= 4;
Packit 1c1d7e
	    while ( i-- ) {
Packit 1c1d7e
		if ( *x++ == v )
Packit 1c1d7e
		    count++;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
	default: {				// any size elements
Packit 1c1d7e
	    for ( i=0; i<shd->len; i+=sz ) {
Packit 1c1d7e
		if ( memcmp(d, &shd->data[i], sz) == 0 )
Packit 1c1d7e
		    count++;
Packit 1c1d7e
	    }
Packit 1c1d7e
	    }
Packit 1c1d7e
	    break;
Packit 1c1d7e
    }
Packit 1c1d7e
    return count;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static int cmp_item_size = 0;
Packit 1c1d7e
Packit 1c1d7e
#if defined(Q_C_CALLBACKS)
Packit 1c1d7e
extern "C" {
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
static int cmp_arr( const void *n1, const void *n2 )
Packit 1c1d7e
{
Packit 1c1d7e
    return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) 
Packit 1c1d7e
	                : (int)((intptr_t)n1 - (intptr_t)n2);
Packit 1c1d7e
    // Qt 3.0: Add a virtual compareItems() method and call that instead
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
#if defined(Q_C_CALLBACKS)
Packit 1c1d7e
}
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
Packit 1c1d7e
  Sort the array.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGArray::sort( uint sz )
Packit 1c1d7e
{
Packit 1c1d7e
    int numItems = size() / sz;
Packit 1c1d7e
    if ( numItems < 2 )
Packit 1c1d7e
	return;
Packit 1c1d7e
    cmp_item_size = sz;
Packit 1c1d7e
    qsort( shd->data, numItems, sz, cmp_arr );
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
Packit 1c1d7e
  Binary search; assumes sorted array
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
int QGArray::bsearch( const char *d, uint sz ) const
Packit 1c1d7e
{
Packit 1c1d7e
    int numItems = size() / sz;
Packit 1c1d7e
    if ( !numItems )
Packit 1c1d7e
	return -1;
Packit 1c1d7e
    cmp_item_size = sz;
Packit 1c1d7e
    char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr );
Packit 1c1d7e
    if ( !r )
Packit 1c1d7e
	return -1;
Packit 1c1d7e
    while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) )
Packit 1c1d7e
	r -= sz;	// search to first of equal elements; bsearch is undef 
Packit 1c1d7e
    return (int)(( r - shd->data ) / sz);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn char *QGArray::at( uint index ) const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns a pointer to the byte at offset \e index in the array.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Expand the array if necessary, and copies (the first part of) its
Packit 1c1d7e
  contents from the \e index*zx bytes at \e d.
Packit 1c1d7e
Packit 1c1d7e
  Returns TRUE if the operation succeeds, FALSE if it runs out of
Packit 1c1d7e
  memory.
Packit 1c1d7e
Packit 1c1d7e
  \warning This function disregards the reference count mechanism.  If
Packit 1c1d7e
  other QGArrays reference the same data as this, all will be changed.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGArray::setExpand( uint index, const char *d, uint sz )
Packit 1c1d7e
{
Packit 1c1d7e
    index *= sz;
Packit 1c1d7e
    if ( index >= shd->len ) {
Packit 1c1d7e
	if ( !resize( index+sz ) )		// no memory
Packit 1c1d7e
	    return FALSE;
Packit 1c1d7e
    }
Packit 1c1d7e
    memcpy( data() + index, d, sz );
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Prints a warning message if at() or [] is given a bad index.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGArray::msg_index( uint index )
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(CHECK_RANGE)
Packit 1c1d7e
    qWarning( "QGArray::at: Absolute index %d out of range", index );
Packit 1c1d7e
#else
Packit 1c1d7e
    Q_UNUSED( index )
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns a new shared array block.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGArray::array_data * QGArray::newData()
Packit 1c1d7e
{
Packit 1c1d7e
    return new array_data;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Deletes the shared array block.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGArray::deleteData( array_data *p )
Packit 1c1d7e
{
Packit 1c1d7e
    delete p;
Packit 1c1d7e
    p = 0;
Packit 1c1d7e
}