home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1997 May
/
Pcwk0597.iso
/
sybase
/
starbuck
/
hpp.z
/
WARRAY.HPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-18
|
15KB
|
511 lines
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (C) 1994, by WATCOM International Inc. All rights %
% reserved. No part of this software may be reproduced or %
% used in any form or by any means - graphic, electronic or %
% mechanical, including photocopying, recording, taping or %
% information storage and retrieval systems - except with the %
% written permission of WATCOM International Inc. %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifndef _WARRAY_HPP_INCLUDED
#define _WARRAY_HPP_INCLUDED
#ifndef _WNO_PRAGMA_PUSH
#pragma pack(push,8);
#pragma enum int;
#endif
#ifndef _WOBJECT_HPP_INCLUDED
# include "wobject.hpp"
#endif
#ifndef _WDEBUG_HPP_INCLUDED
# include "wdebug.hpp"
#endif
#ifndef _WREFOBJ_HPP_INCLUDED
# include "wrefobj.hpp"
#endif
/*************************************************************************
*
* WArrayReference
*
*************************************************************************/
template <class T>
class WCMCLASS WArrayReference : public WReferenceObject {
/**********************************************************
* Constructors and Destructors
*********************************************************/
// This class is meant to be used as a reference class, with
// objects allocated via new. As such we don't allow
// copies to be made except via the MakeCopy method. New
// objects are allocated via the static function Allocate.
private:
WArrayReference( const WArrayReference & ar );
WArrayReference & operator=( const WArrayReference & ar );
protected:
WArrayReference( size_t count );
public:
~WArrayReference();
/**********************************************************
* Properties
*********************************************************/
// Count
int GetCount() const { return _count; }
WBool SetCount( int count );
// Data
T * GetData() const { return _objs; }
// RealCount
int GetRealCount() const;
/**********************************************************
* Methods
*********************************************************/
// Allocate
//
// Allocates a new object.
static WArrayReference *Allocate( size_t count );
// MakeCopy
//
// Creates a new memory object based on the current
// one, copying the data.
WArrayReference *MakeCopy( WInt newCount=-1 );
/**********************************************************
* Private
*********************************************************/
private:
T * _objs;
int _count;
int _realCount;
};
#if defined( _DEBUG ) && !defined( new )
#define _UNINCLUDE_NEW
#include "wnew.hpp"
#endif
template<class T> WArrayReference<T>::WArrayReference( size_t count ) {
_count = count;
_realCount = count;
_objs = NULL;
if( count > 0 ) {
_objs = new T[ count ];
}
}
template<class T> WArrayReference<T>::~WArrayReference() {
delete [] _objs;
_objs = NULL;
_count = 0;
_realCount = 0;
}
template<class T> int WArrayReference<T>::GetRealCount() const {
return _realCount;
}
template<class T> WBool WArrayReference<T>::SetCount( int count ) {
WASSERT( count <= _realCount && count >= 0 );
_count = count;
return TRUE;
}
template<class T> static WArrayReference<T> * WArrayReference<T>::Allocate( size_t count ){
WArrayReference * ref;
ref = new WArrayReference<T>( count );
if( ref != NULL ) {
ref->Reference();
return ref;
}
return NULL;
}
template<class T> WArrayReference<T>* WArrayReference<T>::MakeCopy( WInt newCount ){
WArrayReference * ref;
WInt oldRealCount = _realCount;
if( newCount < 0 ) {
newCount = _realCount;
}
ref = new WArrayReference<T>( newCount );
WASSERT( ref != NULL );
if( ref != NULL ){
ref->Reference();
if( _realCount != 0 ) {
T * oldData;
T * newData;
if( oldRealCount < newCount ) {
newCount = oldRealCount;
}
oldData = GetData();
newData = ref->GetData();
for( int i = 0; i < newCount; i++ ) {
newData[i] = oldData[i];
}
}
}
return ref;
}
/*************************************************************************
*
* WArray
*
*************************************************************************/
template<class T>
class WCMCLASS WArray {
public:
/**********************************************************
* Constructors and Destructors
*********************************************************/
WArray();
WArray( const T & t );
WArray( const WArray & array );
~WArray();
/**********************************************************
* Properties
*********************************************************/
// Count
//
// Returns the count of items in the array.
inline WInt GetCount() const;
WBool SetCount( WInt count );
// Size
//
// Returns the size (max # of items) of the array.
WInt GetSize() const;
/**********************************************************
* Operators
*********************************************************/
inline const T & operator[]( int index ) const;
T & operator[]( int index );
inline operator const T &() const;
operator T &();
WArray & operator=( const T & t );
WArray & operator=( const WArray & array );
/**********************************************************
* Methods
*********************************************************/
// Lock
//
// Lock the array for direct manipulation, possibly growing
// it at the same time. Ensures that no one else is
// referencing the array.
T* Lock( WInt count=-1 );
// Unlock
//
// Unlock the array after direct manipulation.
void Unlock();
/**********************************************************
* Other
*********************************************************/
WInt GetRealCount() const;
static const T & GetOutOfBoundsValue();
static T & GetDummyValue();
/**********************************************************
* Data Members
*********************************************************/
protected:
static T _outOfBoundsValue;
static T _dummyValue;
WArrayReference< T > *_arrRef;
};
template<class T> static T WArray<T>::_outOfBoundsValue;
template<class T> static T WArray<T>::_dummyValue;
template<class T> static const T & WArray<T>::GetOutOfBoundsValue(){
return _outOfBoundsValue;
}
template<class T> static T & WArray<T>::GetDummyValue(){
return _dummyValue;
}
template<class T> WArray<T>::WArray(){
_arrRef = WArrayReference<T>::Allocate( 0 );
WASSERT( _arrRef != NULL );
}
template<class T> WArray<T>::WArray( const T & t ) {
_arrRef = WArrayReference<T>::Allocate( 1 );
WASSERT( _arrRef != NULL );
if( _arrRef ) _arrRef->GetData()[0] = t;
}
template<class T> WArray<T>::WArray( const WArray<T> & array ) {
_arrRef = array._arrRef;
WASSERT( _arrRef != NULL );
if( _arrRef ) _arrRef->Reference();
}
template<class T> WArray<T>::~WArray() {
WASSERT( _arrRef != NULL );
_arrRef->Unreference();
}
template<class T> WBool WArray<T>::SetCount( WInt count ) {
WASSERT( _arrRef != NULL );
if( count <= GetSize() && _arrRef->GetReferenceCount() == 1 ) {
return _arrRef->SetCount( count );
} else {
WArrayReference<T> * newRef = _arrRef->MakeCopy( count );
_arrRef->Unreference();
_arrRef = newRef;
return TRUE;
}
}
template<class T> WInt WArray<T>::GetCount() const {
WASSERT( _arrRef != NULL );
return _arrRef->GetCount();
}
template<class T> WInt WArray<T>::GetRealCount() const {
return GetSize();
}
template<class T> WInt WArray<T>::GetSize() const {
WASSERT( _arrRef != NULL );
return _arrRef->GetRealCount();
}
template<class T> const T & WArray<T>::operator[]( int index ) const {
WASSERTEX( _arrRef && index < _arrRef->GetCount(), "Array index out of bounds" );
if( !_arrRef || index < 0 || index >= _arrRef->GetCount() ){
return GetOutOfBoundsValue();
}
return _arrRef->GetData()[index];
}
template<class T> T & WArray<T>::operator[]( int index ){
WASSERTEX( _arrRef && index < _arrRef->GetCount(), "Array index out of bounds" );
if( !_arrRef || index < 0 || index >= _arrRef->GetCount() ){
return GetDummyValue();
}
WArrayReference<T> * oldArrRef = _arrRef;
if( _arrRef->GetReferenceCount() > 1 ){
_arrRef = _arrRef->MakeCopy();
oldArrRef->Unreference();
}
return _arrRef->GetData()[index];
}
template<class T> WArray<T>::operator const T&() const {
WASSERTEX( _arrRef && _arrRef->GetCount() > 0, "Empty array" );
if( !_arrRef || _arrRef->GetCount() == 0 ){
return GetOutOfBoundsValue();
}
return _arrRef->GetData()[0];
}
template<class T> WArray<T>::operator T&(){
WASSERTEX( _arrRef && _arrRef->GetCount() > 0, "Empty array" );
if( !_arrRef || _arrRef->GetCount() == 0 ){
return GetDummyValue();
}
WArrayReference<T> * oldArrRef = _arrRef;
if( _arrRef->GetReferenceCount() > 1 ) {
_arrRef = _arrRef->MakeCopy();
oldArrRef->Unreference();
}
return _arrRef->GetData()[0];
}
template<class T> WArray<T> & WArray<T>::operator=( const T & t ){
if( _arrRef ) _arrRef->Unreference();
_arrRef = WArrayReference<T>::Allocate( 1 );
if( _arrRef ) _arrRef->GetData()[0] = t;
return *this;
}
template<class T> WArray<T> & WArray<T>::operator=( const WArray<T> & array ){
if( this != &array ){
WArrayReference<T> *old = _arrRef;
_arrRef = array._arrRef;
if( _arrRef) _arrRef->Reference();
if( old ) old->Unreference();
}
return *this;
}
template<class T> T* WArray<T>::Lock( WInt count ){
WASSERT( _arrRef );
if( count < 0 ){
count = GetCount();
}
if( count == 0 ){
count = 1;
}
SetCount( count );
WASSERT( _arrRef->GetReferenceCount() == 1 );
WASSERT( _arrRef->GetData() != NULL );
return _arrRef->GetData();
}
template<class T> void WArray<T>::Unlock(){
WASSERT( _arrRef );
// nothing to do...
}
typedef int WCMDEF (*WArraySysCompRtn)( const void *, const void * );
extern int WArrayCompare( const void *, const void * );
extern WArraySysCompRtn WArrayCompareRoutine;
extern void WArrayAcquire();
extern void WArrayRelease();
template<class T>
class WCMCLASS WSortableArray : public WArray<T> {
public:
typedef int WCMDEF (*WArrayCompareRoutine)( const T *, const T * );
public:
/**********************************************************
* Constructors and Destructors
*********************************************************/
WSortableArray();
WSortableArray( const T & t );
WSortableArray( const WArray & array );
~WSortableArray();
/**********************************************************
* Methods
*********************************************************/
// Sort
//
// Sorts the array using qsort. First locks it, then sorts.
// If no sort function is provided, sorts in ascending
// order using '<' and '==' operators.
void Sort( WArrayCompareRoutine routine=NULL );
static int DefaultCompare( const T *, const T * );
};
template<class T> WSortableArray<T>::WSortableArray() : WArray() {
}
template<class T> WSortableArray<T>::WSortableArray( const T & t )
: WArray( t ) {
}
template<class T> WSortableArray<T>::WSortableArray( const WArray & array )
: WArray( array ) {
}
template<class T> WSortableArray<T>::~WSortableArray() {
}
template<class T> static WSortableArray<T>::DefaultCompare( const T *l, const T *r ){
if( *l < *r ){
return -1;
} else if( *l == *r ){
return 0;
} else {
return 1;
}
}
template<class T> void WSortableArray<T>::Sort( WArrayCompareRoutine routine ){
int count = GetCount();
if( !_arrRef || count == 0 ) return;
if( !routine ) routine = DefaultCompare;
WArrayAcquire();
T *data = Lock();
WArrayCompareRoutine = (WArraySysCompRtn) routine;
qsort( data, count, sizeof( T ), WArrayCompare );
Unlock();
WArrayRelease();
}
//
// Standard array types
//
extern template WArrayReference<WInt>;
extern template WArray<WInt>;
typedef WArray<WInt> WIntArray;
extern template WArrayReference<WULong>;
extern template WArray<WULong>;
typedef WArray<WULong> WULongArray;
extern template WArrayReference<WLong>;
extern template WArray<WLong>;
typedef WArray<WLong> WLongArray;
extern template WArrayReference<WBool>;
extern template WArray<WBool>;
typedef WArray<WBool> WBoolArray;
#if defined( _UNINCLUDE_NEW )
#undef new
#undef delete
#undef WNew
#undef WDelete
#endif
#ifndef _WNO_PRAGMA_PUSH
#pragma enum pop;
#pragma pack(pop);
#endif
#endif // _WARRAY_HPP_INCLUDED