// // 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 #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 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 void WCBareVectorBase::base_assign( const WCBareVectorBase * orig ) { if( this != orig ) { resize( 0 ); base_construct( orig ); } }; template void WCBareVectorBase::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 int WCBareVectorBase::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 void WCBareVectorBase::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 WCBareVectorBase::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 WCBareVectorBase::~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 WCbool WCBareVectorBase::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 WCVectorBase : public WCBareVectorBase { 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( 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 void WCVectorBase::base_assign( const WCVectorBase * orig ) { if( this != orig ) { resize( 0 ); base_construct( orig ); } }; template void WCVectorBase::base_construct( const WCVectorBase * orig ) { WCBareVectorBase::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 int WCVectorBase::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 * const non_const_this = ( WCVectorBase * )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 WCbool WCVectorBase::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 void WCVectorBase::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 WCVectorBase::~WCVectorBase() {}; template WCbool WCVectorBase::contains( const Type &elem ) const { int index = 0; if( ( num_entries != 0 ) &&( base_find( elem, find_any, &index ) ) ) { return( TRUE ); } else { return( FALSE ); } } template WCbool WCVectorBase::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 int WCVectorBase::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 int WCVectorBase::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 WCbool WCVectorBase::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 unsigned WCVectorBase::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 WCbool WCVectorBase::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 WCbool WCVectorBase::resize( size_t new_length ) { WCbool return_val = WCBareVectorBase::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 WCOrderedVectorBase : public WCVectorBase { protected: virtual WCbool base_find( const Type &, find_type, int * ) const; public: inline WCOrderedVectorBase( size_t length, unsigned default_grow ) : WCVectorBase( 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 WCOrderedVectorBase::~WCOrderedVectorBase() {}; template WCbool WCOrderedVectorBase::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 WCSortedVectorBase : public WCVectorBase { 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( length, default_grow ) {}; inline virtual ~WCSortedVectorBase() = 0; WCbool insert( const Type& ); }; template WCSortedVectorBase::~WCSortedVectorBase() {}; template WCbool WCSortedVectorBase::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 WCbool WCSortedVectorBase::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 . 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 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 void WCPtrVectorBase::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 WCPtrVectorBase::~WCPtrVectorBase() {}; template void WCPtrVectorBase::clearAndDestroy() { for( unsigned i = 0; i < num_entries; i++ ) { delete( (Type *)vector[ i ] ); } clear(); }; template Type *WCPtrVectorBase::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 Type *WCPtrVectorBase::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 Type *WCPtrVectorBase::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