Blame qtools/qgarray.cpp

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