925 lines
26 KiB
C++
925 lines
26 KiB
C++
//
|
|
// wcvbase.h Definitions for the base classes used by
|
|
// the WATCOM Container Vector Class
|
|
//
|
|
// =========================================================================
|
|
//
|
|
// Open Watcom Project
|
|
//
|
|
// Copyright (c) 2002-2010 Open Watcom Contributors. All Rights Reserved.
|
|
// Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
|
//
|
|
// This file is automatically generated. Do not edit directly.
|
|
//
|
|
// =========================================================================
|
|
//
|
|
#ifndef _WCVBASE_H_INCLUDED
|
|
#define _WCVBASE_H_INCLUDED
|
|
|
|
#ifndef _ENABLE_AUTODEPEND
|
|
#pragma read_only_file;
|
|
#endif
|
|
|
|
#ifndef __cplusplus
|
|
#error This header file requires C++
|
|
#endif
|
|
|
|
#ifndef _WCEXCEPT_H_INCLUDED
|
|
#include <wcexcept.h>
|
|
#endif
|
|
|
|
// "Warning! W549: 'sizeof' operand contains compiler generated information"
|
|
#pragma warning 549 9
|
|
|
|
#if defined( new ) && defined( _WNEW_OPERATOR )
|
|
#undef new
|
|
#endif
|
|
#if defined( delete ) && defined( _WDELETE_OPERATOR )
|
|
#undef delete
|
|
#endif
|
|
|
|
//
|
|
// constants used by vector classes
|
|
//
|
|
|
|
//
|
|
// The default number of elements a vector is created to store. Specifying
|
|
// the first parameter to the vector constructors will override this value.
|
|
//
|
|
const size_t WCDEFAULT_VECTOR_LENGTH = 10;
|
|
|
|
//
|
|
// The default number of elements a vector will grow by when an element is
|
|
// inserted into a full vector (the number of entries in the vector is
|
|
// the same as the vector length). This growth is performed using the
|
|
// resize member function.
|
|
// This constant applies only ordered and sorted vectors with the
|
|
// resize_required exception disabled.
|
|
// Specifying the second paramter to the ordered and sorted vector
|
|
// constructors will override this value.
|
|
//
|
|
const size_t WCDEFAULT_VECTOR_RESIZE_GROW = 5;
|
|
|
|
|
|
|
|
//
|
|
// Implementation note:
|
|
// From the user's view, all vector elements have been constructed
|
|
// (possibly with only the default constructor).
|
|
//
|
|
// In order to avoid any overhead from default intializing and then
|
|
// immediately assigning a value to a vector element, the C-array used
|
|
// to implement arrays is uninitialized (contains raw memory with none
|
|
// of Type's constuctors called) until it needs to be. This means
|
|
// more efficient copy constucters can be used, and default constuctors
|
|
// do not get called unless they need to. This is especially helpfull
|
|
// for the resize member function.
|
|
// Initializing previously allocated chunks of memory requires calling the
|
|
// new operator with the allocated memory as a placement syntax parameter.
|
|
// If Type defines an operator new with any parameters, then Type must
|
|
// provide the following operator new for the vector classes:
|
|
// void *operator new( size_t, void *ptr ) { return ptr; }
|
|
// WCValVector and WCPtrVector are implemented so that whenever the user
|
|
// accesses an element which has not been initialized, all uninitalized
|
|
// elements upto and including the accessed element are initialized using
|
|
// Type's default constructor.
|
|
// ordered and sorted vectors do not have this "random access" issue, since
|
|
// the index operator can only index previously initialized elements. The
|
|
// last element in a vector is copied in using the copy constructor on and
|
|
// each insert, and the last element(s) in a vector is/are destructed after
|
|
// a remove is performed, so that the number of initialized elements in a
|
|
// vector is always equal to the number of entries in the vector.
|
|
//
|
|
|
|
|
|
|
|
|
|
//
|
|
// This class is the base class for all vector container classes.
|
|
// WCExcept provides common exception handling for all vectors.
|
|
//
|
|
// It is an abstract base class to prevent objects of this class
|
|
// from being created.
|
|
//
|
|
|
|
template<class Type>
|
|
class WCBareVectorBase : public WCExcept {
|
|
protected:
|
|
Type *vector;
|
|
int vector_len;
|
|
int num_init;
|
|
|
|
// WCValVector, WCPtrVector assignment operator base
|
|
void base_assign( const WCBareVectorBase * );
|
|
// WCValVector, WCPtrVector copy constructor base
|
|
void base_construct( const WCBareVectorBase * );
|
|
int base_index_check( int ) const;
|
|
virtual void base_init_upto( int );
|
|
public:
|
|
WCBareVectorBase( size_t length );
|
|
virtual ~WCBareVectorBase() = 0;
|
|
|
|
int operator==( const WCBareVectorBase & rhs ) const {
|
|
return( this == &rhs );
|
|
};
|
|
|
|
inline void clear() {
|
|
resize( 0 );
|
|
};
|
|
|
|
WCbool resize( size_t new_length );
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
void WCBareVectorBase<Type>::base_assign( const WCBareVectorBase * orig ) {
|
|
if( this != orig ) {
|
|
resize( 0 );
|
|
base_construct( orig );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
void WCBareVectorBase<Type>::base_construct( const WCBareVectorBase * orig ) {
|
|
WCExcept::base_construct( orig );
|
|
num_init = orig->num_init;
|
|
vector_len = orig->vector_len;
|
|
if( vector_len > 0 ) {
|
|
// get the raw memory for the vector's C-array
|
|
vector = ( Type * )new char[ sizeof( Type ) * vector_len ];
|
|
if( vector != 0 ) {
|
|
for( int i = 0; i < num_init; i++ ) {
|
|
// Copy all initialized elements from orig to vector, using
|
|
// Type's copy constructor. The placement parameter is used
|
|
// so that the C-array's raw memory is initialized, instead
|
|
// of allocating a new chunck of memory.
|
|
new( &( vector[ i ] ) ) Type( orig->vector[ i ] );
|
|
}
|
|
} else {
|
|
num_init = 0;
|
|
vector_len = 0;
|
|
base_throw_out_of_memory();
|
|
}
|
|
} else {
|
|
vector = 0;
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
int WCBareVectorBase<Type>::base_index_check( int index ) const {
|
|
int entry_index = vector_len - 1;
|
|
if( index < 0 || index > entry_index ) {
|
|
base_throw_index_range();
|
|
if( index < 0 ) {
|
|
index = 0;
|
|
} else {
|
|
if( entry_index <= 0 ) {
|
|
index = 0;
|
|
} else {
|
|
index = entry_index;
|
|
}
|
|
}
|
|
}
|
|
return( index );
|
|
};
|
|
|
|
|
|
//
|
|
// Initialize all unintialized elements upto and including the index'th
|
|
// element using Type's default constructor.
|
|
//
|
|
|
|
template<class Type>
|
|
void WCBareVectorBase<Type>::base_init_upto( int index ) {
|
|
if( index >= num_init ){
|
|
for( int i = num_init; i <= index; i++ ){
|
|
// initialize elements using Type's default constructor. The
|
|
// placement parameter is used so that the C-array's raw memory
|
|
// is initialized, instead of allocating a new chunck of memory.
|
|
new( &( vector[ i ] ) ) Type();
|
|
}
|
|
num_init = index + 1;
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
WCBareVectorBase<Type>::WCBareVectorBase( size_t length ){
|
|
vector_len = length;
|
|
num_init = 0;
|
|
if( length > 0 ){
|
|
// get the raw memory for the vector's C-array
|
|
vector = ( Type * )new char[ sizeof( Type ) * length ];
|
|
if( vector == 0 ) {
|
|
vector_len = 0;
|
|
}
|
|
} else {
|
|
vector = 0;
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
WCBareVectorBase<Type>::~WCBareVectorBase() {
|
|
if( vector ) {
|
|
base_throw_not_empty();
|
|
// call destructors for any initialized elements
|
|
for( int i = 0; i < num_init; i++ ){
|
|
vector[ i ].~Type();
|
|
}
|
|
// delete the C-array (now just raw memory)
|
|
delete [] (char *)vector;
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCBareVectorBase<Type>::resize( size_t new_length ) {
|
|
Type *new_vector;
|
|
int max_index = num_init < new_length ? num_init : new_length;
|
|
|
|
if( new_length > 0 ) {
|
|
// get the raw memory for the vector's C-array
|
|
new_vector = ( Type * )new char[ sizeof( Type ) * new_length ];
|
|
if( new_vector == 0 ){
|
|
base_throw_out_of_memory();
|
|
return( FALSE );
|
|
}
|
|
// Copy all initialized elements from vector (the old C-array) to
|
|
// new_vector (the new C-array), using Type's copy constructor.
|
|
// The placement parameter is used so that the C-array's raw memory
|
|
// is initialized, instead of allocating a new chunck of memory.
|
|
for( int i = 0; i < max_index; i++ ){
|
|
new( &( new_vector[ i ] ) ) Type( vector[ i ] );
|
|
}
|
|
} else {
|
|
new_vector = 0;
|
|
}
|
|
// call destructors for any initialized elements in the old vector
|
|
for( int i = 0; i < num_init; i++ ){
|
|
vector[ i ].~Type();
|
|
}
|
|
// delete the old C-array (now just raw memory)
|
|
delete [] (char *) vector;
|
|
num_init = max_index;
|
|
vector = new_vector;
|
|
vector_len = new_length;
|
|
return( TRUE );
|
|
};
|
|
|
|
|
|
//
|
|
// This class is the base class for Ptr and Val OrderedVector and SortedVector
|
|
// container classes.
|
|
//
|
|
// It is an abstract base class to prevent objects of this class
|
|
// from being created.
|
|
//
|
|
|
|
template<class Type>
|
|
class WCVectorBase : public WCBareVectorBase<Type> {
|
|
protected:
|
|
unsigned num_entries;
|
|
unsigned resize_grow; // the number of elements to grow a vector
|
|
// when inserting into a full vector
|
|
|
|
enum find_type { // for the base_find function
|
|
find_any, // find any matching element in the vector
|
|
find_first, // find first matching element in vector
|
|
next_mult_find, // find next matching element in vector
|
|
find_for_insert }; // find index to insert element in sorted vector
|
|
|
|
// the assignment operator base
|
|
void base_assign( const WCVectorBase * );
|
|
// the copy constructor base
|
|
void base_construct( const WCVectorBase * );
|
|
virtual int base_equivalent( const Type &elem1
|
|
, const Type &elem2 ) const = 0;
|
|
// find first parm in vector, with specified find_type. index passes
|
|
// in where to start the search, and returns the index where first param
|
|
// found if returns true
|
|
virtual WCbool base_find( const Type &, find_type, int * index ) const = 0;
|
|
int base_index_check( int ) const;
|
|
WCbool base_insert_at( int, const Type& );
|
|
void base_remove_at( int );
|
|
|
|
public:
|
|
inline WCVectorBase( size_t length, unsigned grow )
|
|
: num_entries( 0 ), resize_grow( grow ),
|
|
WCBareVectorBase<Type>( length ) {};
|
|
inline virtual ~WCVectorBase() = 0;
|
|
|
|
inline void clear() {
|
|
WCBareVectorBase::clear();
|
|
num_entries = 0;
|
|
};
|
|
|
|
WCbool contains( const Type & ) const;
|
|
|
|
inline unsigned entries() const {
|
|
return( num_entries );
|
|
};
|
|
|
|
WCbool find( const Type &elem, Type &ret_val ) const;
|
|
|
|
inline Type first() const {
|
|
return( vector[ base_index_check( 0 ) ] );
|
|
}
|
|
|
|
int index( const Type & ) const;
|
|
|
|
inline WCbool isEmpty() const {
|
|
return( num_entries == 0 );
|
|
};
|
|
|
|
inline Type last() const {
|
|
return( vector[ base_index_check( num_entries - 1 ) ] );
|
|
}
|
|
|
|
int occurrencesOf( const Type & elem ) const;
|
|
|
|
WCbool remove( const Type & elem );
|
|
|
|
unsigned removeAll( const Type & elem );
|
|
|
|
WCbool removeAt( int );
|
|
|
|
inline WCbool removeFirst() {
|
|
return( removeAt( 0 ) );
|
|
};
|
|
|
|
inline WCbool removeLast() {
|
|
return( removeAt( num_entries - 1 ) );
|
|
};
|
|
|
|
WCbool resize( size_t );
|
|
|
|
inline Type& operator[] ( int index ) {
|
|
return( vector[ base_index_check( index ) ] );
|
|
};
|
|
|
|
inline const Type& operator[] ( int index ) const {
|
|
return( vector[ base_index_check( index ) ] );
|
|
};
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
void WCVectorBase<Type>::base_assign( const WCVectorBase * orig ) {
|
|
if( this != orig ) {
|
|
resize( 0 );
|
|
base_construct( orig );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
void WCVectorBase<Type>::base_construct( const WCVectorBase * orig ) {
|
|
WCBareVectorBase<Type>::base_construct( orig );
|
|
resize_grow = orig->resize_grow;
|
|
if( vector != 0 ) {
|
|
num_entries = orig->num_entries;
|
|
} else {
|
|
num_entries = 0;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check to see if index is valid, and return the closest valid index.
|
|
// If index is invalid then exceptions are thrown if enabled, and if
|
|
// exceptions are disabled and the vector has no entries, then the first
|
|
// element is default initialized, effectively inserting a first element
|
|
// (this is done for the index operators and first and last member
|
|
// functions)
|
|
//
|
|
template<class Type>
|
|
int WCVectorBase<Type>::base_index_check( int index ) const {
|
|
int entry_index = num_entries - 1;
|
|
if( index < 0 || index > entry_index ) {
|
|
if( num_entries == 0 ) {
|
|
base_throw_empty_container();
|
|
base_throw_index_range();
|
|
// insert the first element as a default intialized element
|
|
WCVectorBase<Type> * const non_const_this
|
|
= ( WCVectorBase<Type> * )this;
|
|
if( vector_len == 0 ) {
|
|
if( !non_const_this->resize( 1 ) ) {
|
|
// An invalid operation on an empty vector, and out memory.
|
|
// return the first element of a NULL C-array.
|
|
return( 0 );
|
|
}
|
|
}
|
|
non_const_this->base_init_upto( 0 );
|
|
non_const_this->num_entries = 1;
|
|
index = 0;
|
|
} else if( index < 0 ) {
|
|
index = 0;
|
|
base_throw_index_range();
|
|
} else {
|
|
index = entry_index;
|
|
base_throw_index_range();
|
|
}
|
|
}
|
|
return( index );
|
|
};
|
|
|
|
|
|
//
|
|
// insert new_entry before the element currently at index. If index is the
|
|
// number of entries, insert new_entry as the last element.
|
|
//
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::base_insert_at( int index, const Type& new_entry ) {
|
|
if( index > (int)num_entries ) {
|
|
base_throw_index_range();
|
|
index = num_entries;
|
|
} else if( index < 0 ) {
|
|
base_throw_index_range();
|
|
index = 0;
|
|
}
|
|
if( num_entries == vector_len ){
|
|
base_throw_resize_required();
|
|
// automatically grow the vector if it was full, the resize_required
|
|
// exception is disabled, and the amount to grow the vector is greater
|
|
// than zero.
|
|
if( ( resize_grow == 0 )
|
|
||( !resize( vector_len + resize_grow ) ) ) {
|
|
return( FALSE );
|
|
}
|
|
}
|
|
// the last entry in the vector must be copied in, since it was previously
|
|
// unused, and unused elements are unitialized.
|
|
if( index == num_entries ){
|
|
new( &( vector[ index ] ) ) Type( new_entry );
|
|
} else {
|
|
new( &( vector[ num_entries ] ) ) Type( vector[ num_entries - 1 ] );
|
|
for( int i = num_entries - 2; i >= index; i-- ) {
|
|
vector[ i + 1 ] = vector[ i ];
|
|
}
|
|
vector[ index ] = new_entry;
|
|
}
|
|
num_entries++;
|
|
num_init++;
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
void WCVectorBase<Type>::base_remove_at( int index ) {
|
|
for( int i = index; i < num_entries - 1; i++ ) {
|
|
vector[ i ] = vector[ i + 1 ];
|
|
}
|
|
// destruct the last element in the array, so that unused elements are
|
|
// unitialized.
|
|
vector[ num_entries - 1 ].~Type();
|
|
num_entries--;
|
|
num_init--;
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
WCVectorBase<Type>::~WCVectorBase() {};
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::contains( const Type &elem ) const {
|
|
int index = 0;
|
|
|
|
if( ( num_entries != 0 )
|
|
&&( base_find( elem, find_any, &index ) ) ) {
|
|
return( TRUE );
|
|
} else {
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::find( const Type &elem, Type &ret_val ) const {
|
|
int index = 0;
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( elem, find_first, &index ) ) ) {
|
|
ret_val = vector[ index ];
|
|
return( TRUE );
|
|
} else {
|
|
Type temp;
|
|
ret_val = temp;
|
|
return( FALSE );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
int WCVectorBase<Type>::index( const Type & elem ) const {
|
|
int ret_index = 0;
|
|
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( elem, find_first, &ret_index ) ) ) {
|
|
return( ret_index );
|
|
} else {
|
|
return( -1 );
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
int WCVectorBase<Type>::occurrencesOf( const Type & elem ) const {
|
|
int index = 0;
|
|
int count = 0;
|
|
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( elem, find_first, &index ) ) ) {
|
|
do {
|
|
count++;
|
|
index++;
|
|
} while( base_find( elem, next_mult_find, &index ) );
|
|
}
|
|
return( count );
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::remove( const Type & elem ) {
|
|
int index = 0;
|
|
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( elem, find_first, &index ) ) ) {
|
|
base_remove_at( index );
|
|
return( TRUE );
|
|
} else {
|
|
return( FALSE );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
unsigned WCVectorBase<Type>::removeAll( const Type & elem ) {
|
|
int found_index = 0;
|
|
int count = 0;
|
|
|
|
// make sure only elements which need to be moved are moved
|
|
// no element is moved more than once
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( elem, find_first, &found_index ) ) ) {
|
|
// at least one element is being removed
|
|
int curr_index = found_index;
|
|
count++;
|
|
found_index++;
|
|
while( base_find( elem, next_mult_find, &found_index ) ) {
|
|
// move entries which were between any occurrances of elem
|
|
for( ;curr_index < found_index - count; curr_index++ ){
|
|
vector[ curr_index ] = vector[ curr_index + count ];
|
|
}
|
|
count++;
|
|
found_index++;
|
|
};
|
|
// move entries after any occurances of elem
|
|
for( ;curr_index < num_entries - count; curr_index++ ){
|
|
vector[ curr_index ] = vector[ curr_index + count ];
|
|
}
|
|
// destruct elements at the end of the vector which were copied or
|
|
// removed, so that unused elements are unitialized
|
|
for( ;curr_index < num_entries; curr_index++ ){
|
|
vector[ curr_index ].~Type();
|
|
}
|
|
num_entries -= count;
|
|
num_init -= count;
|
|
}
|
|
return( count );
|
|
}
|
|
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::removeAt( int index ) {
|
|
if( num_entries == 0 ) {
|
|
base_throw_empty_container();
|
|
return( FALSE );
|
|
} else {
|
|
index = base_index_check( index );
|
|
base_remove_at( index );
|
|
return( TRUE );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type>
|
|
WCbool WCVectorBase<Type>::resize( size_t new_length ) {
|
|
WCbool return_val = WCBareVectorBase<Type>::resize( new_length );
|
|
if( return_val && num_entries > new_length ){
|
|
num_entries = new_length;
|
|
}
|
|
return( return_val );
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// WCOrderedVectorBase - this is the base class for WCValOrderedVector and
|
|
// WCPtrOrderedVector.
|
|
//
|
|
// This is a abstract class to prevent objects of this type being created
|
|
//
|
|
|
|
template <class Type>
|
|
class WCOrderedVectorBase : public WCVectorBase<Type> {
|
|
protected:
|
|
virtual WCbool base_find( const Type &, find_type, int * ) const;
|
|
public:
|
|
inline WCOrderedVectorBase( size_t length, unsigned default_grow )
|
|
: WCVectorBase<Type>( length, default_grow ) {};
|
|
|
|
inline virtual ~WCOrderedVectorBase() = 0;
|
|
|
|
inline WCbool append( const Type& new_elem ){
|
|
return( insert( new_elem ) );
|
|
};
|
|
|
|
inline WCbool insert( const Type& new_elem ){
|
|
return( base_insert_at( num_entries, new_elem ) );
|
|
};
|
|
|
|
inline WCbool insertAt( int index, const Type& new_elem ){
|
|
return( base_insert_at( index, new_elem ) );
|
|
};
|
|
|
|
inline WCbool prepend( const Type& new_elem ){
|
|
return( base_insert_at( 0, new_elem ) );
|
|
};
|
|
|
|
};
|
|
|
|
|
|
template <class Type>
|
|
WCOrderedVectorBase<Type>::~WCOrderedVectorBase() {};
|
|
|
|
|
|
template <class Type>
|
|
WCbool WCOrderedVectorBase<Type>::base_find( const Type &elem, find_type
|
|
, int *st_found_index ) const {
|
|
int index = *st_found_index;
|
|
|
|
while( index < num_entries ) {
|
|
if( base_equivalent( vector[ index ], elem ) ) {
|
|
*st_found_index = index;
|
|
return( TRUE );
|
|
}
|
|
index++;
|
|
}
|
|
return( FALSE );
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// WCSortedVectorBase - this is the base class for WCValSortedVector and
|
|
// WCPtrSortedVector.
|
|
//
|
|
// This is a abstract class to prevent objects of this type being created
|
|
//
|
|
|
|
template <class Type>
|
|
class WCSortedVectorBase : public WCVectorBase<Type> {
|
|
protected:
|
|
virtual WCbool base_find( const Type &, find_type, int * ) const;
|
|
virtual int base_less_than( const Type& elem1
|
|
, const Type& elem2 ) const = 0;
|
|
public:
|
|
inline WCSortedVectorBase( size_t length, unsigned default_grow )
|
|
: WCVectorBase<Type>( length, default_grow ) {};
|
|
|
|
inline virtual ~WCSortedVectorBase() = 0;
|
|
|
|
WCbool insert( const Type& );
|
|
};
|
|
|
|
|
|
template <class Type>
|
|
WCSortedVectorBase<Type>::~WCSortedVectorBase() {};
|
|
|
|
|
|
template <class Type>
|
|
WCbool WCSortedVectorBase<Type>::base_find( const Type &elem, find_type type
|
|
, int * st_found_index ) const {
|
|
// for multiple searches, check to see next element also matches
|
|
if( type == next_mult_find ) {
|
|
int index = *st_found_index;
|
|
if( ( index < num_entries )
|
|
&&( base_equivalent( vector[ index ], elem ) ) ) {
|
|
return( TRUE );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
// the binary search
|
|
int low_bound = 0;
|
|
int up_bound = num_entries - 1;
|
|
int bisector;
|
|
while( low_bound < up_bound ) {
|
|
// bisector must be calculated so that it is less than up_bound
|
|
bisector = ( up_bound - low_bound ) / 2 + low_bound;
|
|
if( base_less_than( vector[ bisector ], elem ) ) {
|
|
low_bound = bisector + 1;
|
|
} else {
|
|
up_bound = bisector;
|
|
}
|
|
}
|
|
|
|
bisector = low_bound;
|
|
// if we found elem, the first match is at index bisector
|
|
|
|
if( base_equivalent( elem, vector[ bisector ] ) ) {
|
|
// found match, bisector is the first match
|
|
if( type == find_for_insert ) {
|
|
while( ( bisector < num_entries )
|
|
&&( base_equivalent( vector[ bisector ], elem ) ) ) {
|
|
bisector++;
|
|
}
|
|
}
|
|
*st_found_index = bisector;
|
|
return( TRUE );
|
|
}
|
|
|
|
// search failed, if find for insert make sure we are *after* elem
|
|
if( type == find_for_insert ){
|
|
if( base_less_than( vector[ bisector ], elem ) ) {
|
|
bisector++;
|
|
}
|
|
*st_found_index = bisector;
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
template <class Type>
|
|
WCbool WCSortedVectorBase<Type>::insert( const Type& elem ) {
|
|
int index = 0;
|
|
|
|
if( num_entries > 0 ) {
|
|
base_find( elem, find_for_insert, &index );
|
|
}
|
|
return( base_insert_at( index, elem ) );
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// WCPtrVectorBase - this is a base class for WCPtrOrderedVector and
|
|
// WCPtrSortedVector.
|
|
//
|
|
// This is a abstract class to prevent objects of this type being created
|
|
//
|
|
// Implementation note:
|
|
// All WCPtrOrdered vectors and WCPtrSorted vectors inherit from WCVectorBase
|
|
// templated over <void *>. This saves most of the vector code being
|
|
// generated for pointer vectors templated over different types, speeding
|
|
// up compile time, and reducing code size.
|
|
//
|
|
|
|
template <class Type, class BaseClass>
|
|
class WCPtrVectorBase : public BaseClass {
|
|
protected:
|
|
typedef Type * __Type_Ptr;
|
|
typedef void * __Stored_Ptr;
|
|
|
|
inline Type *base_ptr_remove_at( int index ) {
|
|
Type *ret_ptr = (Type *)vector[ index ];
|
|
base_remove_at( index );
|
|
return( ret_ptr );
|
|
}
|
|
|
|
virtual void base_init_upto( int );
|
|
|
|
public:
|
|
inline WCPtrVectorBase( size_t length, unsigned default_grow )
|
|
: BaseClass( length, default_grow ) {};
|
|
|
|
inline virtual ~WCPtrVectorBase() = 0;
|
|
|
|
void clearAndDestroy();
|
|
|
|
inline WCbool contains( const Type * elem ) const {
|
|
return( BaseClass::contains( (const __Type_Ptr)elem ) );
|
|
};
|
|
|
|
Type *find( const Type * elem ) const;
|
|
|
|
inline Type *first() const {
|
|
return( (Type *)BaseClass::first() );
|
|
}
|
|
|
|
inline int index( const Type * elem ) const {
|
|
return( BaseClass::index( (const __Type_Ptr)elem ) );
|
|
};
|
|
|
|
inline Type *last() const {
|
|
return( (Type *)BaseClass::last() );
|
|
}
|
|
|
|
int occurrencesOf( const Type * elem ) const {
|
|
return( BaseClass::occurrencesOf( (const __Type_Ptr)elem ) );
|
|
};
|
|
|
|
Type *remove( const Type * elem );
|
|
|
|
unsigned removeAll( const Type * elem ) {
|
|
return( BaseClass::removeAll( (const __Type_Ptr)elem ) );
|
|
};
|
|
|
|
Type *removeAt( int index );
|
|
|
|
inline Type *removeFirst() {
|
|
return( removeAt( 0 ) );
|
|
};
|
|
|
|
inline Type *removeLast() {
|
|
return( removeAt( num_entries - 1 ) );
|
|
};
|
|
|
|
inline Type * &operator[] ( int index ) {
|
|
return( (Type * &)BaseClass::operator[]( index ) );
|
|
};
|
|
|
|
inline Type * const & operator[] ( int index ) const {
|
|
return( (Type * const &)BaseClass::operator[]( index ) );
|
|
};
|
|
};
|
|
|
|
|
|
template<class Type, class BaseClass>
|
|
void WCPtrVectorBase<Type, BaseClass>::base_init_upto( int index ) {
|
|
if( index >= num_init ){
|
|
// intialize the vector by NULLing out unitialized elements
|
|
memset( &vector[ num_init ], 0
|
|
, ( index + 1 - num_init ) * sizeof( void * ) );
|
|
num_init = index + 1;
|
|
}
|
|
}
|
|
|
|
|
|
template <class Type, class BaseClass>
|
|
WCPtrVectorBase<Type, BaseClass>::~WCPtrVectorBase() {};
|
|
|
|
|
|
template<class Type, class BaseClass>
|
|
void WCPtrVectorBase<Type, BaseClass>::clearAndDestroy() {
|
|
for( unsigned i = 0; i < num_entries; i++ ) {
|
|
delete( (Type *)vector[ i ] );
|
|
}
|
|
clear();
|
|
};
|
|
|
|
|
|
template<class Type, class BaseClass>
|
|
Type *WCPtrVectorBase<Type, BaseClass>::find( const Type * elem ) const {
|
|
int index = 0;
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( (const __Type_Ptr)elem, find_any, &index ) ) ) {
|
|
return( (Type *)vector[ index ] );
|
|
} else {
|
|
return( 0 );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type, class BaseClass>
|
|
Type *WCPtrVectorBase<Type, BaseClass>::remove( const Type *elem ) {
|
|
int index = 0;
|
|
|
|
if( ( num_entries > 0 )
|
|
&&( base_find( (const __Type_Ptr)elem, find_first, &index ) ) ) {
|
|
return( base_ptr_remove_at( index ) );
|
|
} else {
|
|
return( 0 );
|
|
}
|
|
};
|
|
|
|
|
|
template<class Type, class BaseClass>
|
|
Type *WCPtrVectorBase<Type, BaseClass>::removeAt( int index ) {
|
|
if( num_entries == 0 ) {
|
|
base_throw_empty_container();
|
|
return( 0 );
|
|
} else {
|
|
index = base_index_check( index );
|
|
return( base_ptr_remove_at( index ) );
|
|
}
|
|
};
|
|
|
|
|
|
#ifdef _WNEW_OPERATOR
|
|
#define new _WNEW_OPERATOR
|
|
#endif
|
|
#ifdef _WDELETE_OPERATOR
|
|
#define delete _WDELETE_OPERATOR
|
|
#endif
|
|
|
|
#endif
|