OpenFPGA/vpr7_x2p/libprinthandler/SRC/TC_Common/TCT_DynamicVector.h

641 lines
21 KiB
C
Raw Normal View History

2018-07-26 12:28:21 -05:00
//===========================================================================//
// Purpose : Template version for a TCT_DynamicVector dynamic vector class.
// This vector class dynamically expands and shrinks the total
// memory usage requirements based on current vector length.
//
// Inline methods include:
// - SetCapacity
// - ResetCapacity
// - GetCapacity
// - GetLength
// - Set
// - Add
// - Delete
// - Clear
// - IsValid
//
// Public methods include:
// - TCT_DynamicVector_c, ~TCT_DynamicVector_c
// - operator=
// - operator==, operator!=
// - operator[]
// - Print
//
// Protected methods include:
// - Init_
// - Set_
// - Add_
// - Delete_
// - Clear_
// - Expand_
// - Shrink_
//
//===========================================================================//
#ifndef TCT_DYNAMIC_VECTOR_H
#define TCT_DYNAMIC_VECTOR_H
#include <stdio.h>
#include "TIO_PrintHandler.h"
#include "TCT_Generic.h"
#include "TC_Typedefs.h"
//===========================================================================//
// Purpose : Class declaration
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > class TCT_DynamicVector_c
{
public:
TCT_DynamicVector_c( size_t allocLen = 1,
size_t reallocLen = 1 );
TCT_DynamicVector_c( const TCT_DynamicVector_c& dynamicVector );
~TCT_DynamicVector_c( void );
TCT_DynamicVector_c< T >& operator=( const TCT_DynamicVector_c& dynamicVector );
bool operator==( const TCT_DynamicVector_c& dynamicVector ) const;
bool operator!=( const TCT_DynamicVector_c& dynamicVector ) const;
T* operator[]( size_t i );
T* operator[]( size_t i ) const;
void Print( FILE* pfile = stdout, size_t spaceLen = 0 ) const;
void SetCapacity( size_t capacity );
void SetCapacity( size_t allocLen,
size_t reallocLen );
void ResetCapacity( size_t capacity );
void ResetCapacity( size_t allocLen,
size_t reallocLen );
size_t GetCapacity( void ) const;
size_t GetLength( void ) const;
bool Set( size_t i, const T& data );
T* Add( const T& data );
void Delete( size_t i );
void Clear( void );
bool IsValid( void ) const;
protected:
bool Init_( size_t allocLen, size_t reallocLen );
bool Init_( const TCT_DynamicVector_c& dynamicVector );
bool Set_( size_t i, const T& data );
T* Add_( const T& data );
void Delete_( size_t i );
void Clear_( void );
bool Expand_( void );
bool Shrink_( void );
protected:
T* padata_; // Ptr to a dynamic vector of <T> data elements
size_t curLen_; // Current dynamic vector size
// (ie. defines count of elements currently in use)
size_t maxLen_; // Max dynamic vector size (w/o memory reallocate)
// (ie. assume curLen_ <= maxLen_)
size_t allocLen_; // Initial allocate/deallocate size
// (ie. used for dynamic memory expand/shrink)
size_t reallocLen_; // Reallocate allocate/deallocate size
// (ie. used for dynamic memory expand/shrink)
size_t addCount_; // Track number of adds made to this dynamic vector
size_t deleteCount_; // Track number of deletes made to this dynamic vector
};
//===========================================================================//
// Purpose : Class inline definition(s)
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::SetCapacity(
size_t capacity )
{
this->Clear_( );
this->Init_( capacity, capacity );
}
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::SetCapacity(
size_t allocLen,
size_t reallocLen )
{
this->Clear_( );
this->Init_( allocLen, reallocLen );
}
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::ResetCapacity(
size_t capacity )
{
this->maxLen_ = capacity;
this->Init_( capacity, capacity );
}
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::ResetCapacity(
size_t allocLen,
size_t reallocLen )
{
this->maxLen_ = TCT_Max( allocLen, reallocLen );
this->Init_( allocLen, reallocLen );
}
//===========================================================================//
template< class T > inline size_t TCT_DynamicVector_c< T >::GetCapacity(
void ) const
{
return( TCT_Max( this->allocLen_, this->reallocLen_ ));
}
//===========================================================================//
template< class T > inline size_t TCT_DynamicVector_c< T >::GetLength(
void ) const
{
return( this->curLen_ );
}
//===========================================================================//
template< class T > inline bool TCT_DynamicVector_c< T >::Set(
size_t i,
const T& data )
{
return( this->Set_( i, data ));
}
//===========================================================================//
template< class T > inline T* TCT_DynamicVector_c< T >::Add(
const T& data )
{
return( this->Add_( data ));
}
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::Delete(
size_t i )
{
this->Delete_( i );
}
//===========================================================================//
template< class T > inline void TCT_DynamicVector_c< T >::Clear(
void )
{
this->Clear_( );
}
//===========================================================================//
template< class T > inline bool TCT_DynamicVector_c< T >::IsValid(
void ) const
{
return( this->GetLength( ) > 0 ? true : false );
}
//===========================================================================//
// Method : TCT_DynamicVector_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > TCT_DynamicVector_c< T >::TCT_DynamicVector_c(
size_t allocLen,
size_t reallocLen )
:
padata_( 0 ),
curLen_( 0 ),
maxLen_( 0 ),
allocLen_( 0 ),
reallocLen_( 0 ),
addCount_( 0 ),
deleteCount_( 0 )
{
this->Init_( allocLen, reallocLen );
}
//===========================================================================//
template< class T > TCT_DynamicVector_c< T >::TCT_DynamicVector_c(
const TCT_DynamicVector_c& dynamicVector )
:
padata_( 0 ),
curLen_( 0 ),
maxLen_( 0 ),
allocLen_( 0 ),
reallocLen_( 0 ),
addCount_( 0 ),
deleteCount_( 0 )
{
this->Init_( dynamicVector );
}
//===========================================================================//
// Method : ~TCT_DynamicVector_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > TCT_DynamicVector_c< T >::~TCT_DynamicVector_c(
void )
{
this->curLen_ = 0;
this->Shrink_( );
}
//===========================================================================//
// Method : operator=
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > TCT_DynamicVector_c< T >& TCT_DynamicVector_c< T >::operator=(
const TCT_DynamicVector_c& dynamicVector )
{
if ( &dynamicVector != this )
{
this->Init_( dynamicVector );
}
return( *this );
}
//===========================================================================//
// Method : operator==
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::operator==(
const TCT_DynamicVector_c& dynamicVector ) const
{
bool isEqual = this->GetLength( ) == dynamicVector.GetLength( ) ?
true : false;
if ( isEqual )
{
for ( size_t i = 0; i < this->GetLength( ); ++i )
{
isEqual = *this->operator[]( i ) == *dynamicVector.operator[]( i ) ?
true : false;
if ( !isEqual )
break;
}
}
return( isEqual );
}
//===========================================================================//
// Method : operator!=
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::operator!=(
const TCT_DynamicVector_c& dynamicVector ) const
{
return( !this->operator==( dynamicVector ) ? true : false );
}
//===========================================================================//
// Method : operator[]
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > T* TCT_DynamicVector_c< T >::operator[](
size_t i )
{
return( i < this->maxLen_ ? this->padata_ + i : 0 );
}
//===========================================================================//
template< class T > T* TCT_DynamicVector_c< T >::operator[](
size_t i ) const
{
return( i < this->maxLen_ ? this->padata_ + i : 0 );
}
//===========================================================================//
// Method : Print
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > void TCT_DynamicVector_c< T >::Print(
FILE* pfile,
size_t spaceLen ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
printHandler.Write( pfile, spaceLen, "// %u/%u [%u/%u] (+%u/-%u)",
this->curLen_, this->maxLen_,
this->allocLen_, this->reallocLen_,
this->addCount_, this->deleteCount_ );
for ( size_t i = 0; i < this->GetLength( ); ++i )
{
const T& data = *this->operator[]( i );
data.Print( pfile, spaceLen );
}
}
//===========================================================================//
// Method : Init_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::Init_(
size_t allocLen,
size_t reallocLen )
{
bool ok = true;
// Init alloc and realloc lengths per given values
this->allocLen_ = allocLen;
this->reallocLen_ = reallocLen;
// Force alloc and realloc lengths to minimum acceptable values
this->allocLen_ = TCT_Max( this->allocLen_, static_cast< size_t >( 1 ));
this->reallocLen_ = TCT_Max( this->allocLen_, this->reallocLen_ );
// And force alloc length to a multiple of realloc length
// (for easier subsequent dynamic vector memory expand/shrink)
this->allocLen_ = (( this->allocLen_ - 1 ) / this->reallocLen_ ) + 1;
this->allocLen_ *= this->reallocLen_;
return( ok );
}
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::Init_(
const TCT_DynamicVector_c& dynamicVector )
{
bool ok = true;
this->Clear_( );
this->allocLen_ = dynamicVector.allocLen_;
this->reallocLen_ = dynamicVector.reallocLen_;
this->curLen_ = dynamicVector.curLen_;
this->maxLen_ = dynamicVector.maxLen_;
if ( this->maxLen_ > 0 )
{
this->padata_ = new TC_NOTHROW T[ this->maxLen_ ];
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.IsValidNew( this->padata_,
sizeof( T ) * this->maxLen_,
"TCT_DynamicVector_c< T >::Init_" );
if ( ok )
{
for ( size_t i = 0; i < this->maxLen_; ++i )
{
// Need to copy each element into the newly allocated list
// (using 'deep' copy, instead of a faster 'shallow' memcpy)
*( this->padata_ + i ) = *( dynamicVector.padata_ + i );
}
}
}
return( ok );
}
//===========================================================================//
// Method : Set_
// Purpose : Sets a new data element in this dynamic vector.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::Set_(
size_t i,
const T& data )
{
bool ok = true;
while ( i >= this->curLen_ )
{
ok = this->Expand_( );
if ( !ok )
break;
}
if ( ok )
{
*( this->padata_ + i ) = data;
}
return( ok );
}
//===========================================================================//
// Method : Add_
// Purpose : Adds a new data element to this dynamic vector. The
// vector length is automatically expanded, if needed.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > T* TCT_DynamicVector_c< T >::Add_(
const T& data )
{
T* pdata = 0;
// Expand dynamic vector to accommodate new data element, if needed
if ( this->Expand_( ))
{
// Add new data element to end of vector
pdata = this->operator[]( this->curLen_ );
*pdata = data;
// Update current length to reflect new vector size
++this->curLen_;
// Track total number of add operations made to this vector too
++this->addCount_;
}
return( pdata );
}
//===========================================================================//
// Method : Delete_
// Purpose : Deletes an existing data element from this dynamic
// vector. The vector length is automatically shrunk, if
// needed.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > void TCT_DynamicVector_c< T >::Delete_(
size_t i )
{
if ( i < this->curLen_ )
{
// Delete existing data element by shifting subsequent data elements
while ( i < this->curLen_ - 1 )
{
// Need to copy each element into the newly allocated list
// (using 'deep' copy, instead of a faster 'shallow' memcpy)
*( this->padata_ + i ) = *( this->padata_ + i + 1 );
++i;
}
// Update current length to reflect new vector size
--this->curLen_;
// Track total number of delete operations made to this vector too
++this->deleteCount_;
// Shrink dynamic vector to account for deleted data element, if needed
this->Shrink_( );
}
}
//===========================================================================//
// Method : Clear_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > void TCT_DynamicVector_c< T >::Clear_(
void )
{
this->curLen_ = 0;
this->Shrink_( );
this->padata_ = 0;
this->addCount_ = 0;
this->deleteCount_ = 0;
}
//===========================================================================//
// Method : Expand_
// Purpose : Expands this dynamic vector whenever the current length
// exceeds the maximum length. The new vector length is
// adjusted based on the current alloc/realloc length.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::Expand_(
void )
{
bool ok = true;
// Test if current length requires expanding dynamic vector max length
if ( this->curLen_ >= this->maxLen_ )
{
// Increase max length based on either alloc or realloc length
size_t incLen = ( this->maxLen_ == 0 ?
this->allocLen_ : this->reallocLen_ );
this->maxLen_ += incLen;
// Make local copy of current vector, then allocate and copy new vector
T* padata = new TC_NOTHROW T[ this->maxLen_ ];
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.IsValidNew( padata,
sizeof( T ) * this->maxLen_,
"TCT_DynamicVector_c< T >::Expand_" );
if ( ok )
{
for ( size_t i = 0; i < this->curLen_; ++i )
{
// Need to copy each element into the newly allocated list
// (using 'deep' copy, instead of a faster 'shallow' memcpy)
*( padata + i ) = *( this->padata_ + i );
}
}
else
{
this->curLen_ = this->maxLen_ = 0;
}
delete[] this->padata_;
this->padata_ = padata;
}
return( ok );
}
//===========================================================================//
// Method : Shrink_
// Purpose : Shrink this dynamic vector length when the current length
// has been reduced to the maximum length less the realloc
// length. The new vector length is adjusted based on the
// given realloc length.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/20/12 jeffr : Original
//===========================================================================//
template< class T > bool TCT_DynamicVector_c< T >::Shrink_(
void )
{
bool ok = true;
// Test if dynamic vector length can be constracted based on current length
if (( this->maxLen_ > 0 ) &&
( this->curLen_ <= ( this->maxLen_ - this->reallocLen_ )))
{
// Ready to deallocate a portion of dynamic vector
this->maxLen_ = ( this->curLen_ / this->reallocLen_ ) + 1;
this->maxLen_ = ( this->curLen_ ? this->maxLen_ : 0 );
this->maxLen_ *= this->reallocLen_;
if ( this->maxLen_ != 0 )
{
T* padata = new TC_NOTHROW T[ this->maxLen_ ];
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.IsValidNew( padata,
sizeof( T ) * this->maxLen_,
"TCT_DynamicVector_c< T >::Shrink_" );
if ( ok )
{
// Need to copy each element into the newly allocated list
// (using 'deep' copy, instead of a faster 'shallow' memcpy)
for ( size_t i = 0; i < this->maxLen_; ++i )
{
*( padata + i ) = *( this->padata_ + i );
}
}
else
{
this->curLen_ = this->maxLen_ = 0;
}
delete[] this->padata_;
this->padata_ = padata;
}
else
{
delete[] this->padata_;
this->padata_ = 0;
}
}
return( ok );
}
#endif