2020-02-23 12:21:28 +01:00
//*************************************************************************************************
//*************************************************************************************************
//
// XArray
//
// Developed by jief666, from 1997.
//
//*************************************************************************************************
//*************************************************************************************************
# if !defined(__XARRAY_H__)
# define __XARRAY_H__
# include "XToolsCommon.h"
#if 0
# define XArray_DBG(...) DebugLog(2, __VA_ARGS__)
# else
# define XArray_DBG(...)
# endif
template < class TYPE >
class XArray
{
protected :
TYPE * m_data ;
xsize m_len ;
2020-03-09 02:12:24 +01:00
xsize m_allocatedSize ;
2020-02-23 12:21:28 +01:00
xsize _GrowBy ;
public :
void Init ( ) ;
XArray ( ) { Init ( ) ; }
XArray ( const XArray < TYPE > & anArray ) ;
const XArray < TYPE > & operator = ( const XArray < TYPE > & anArray ) ;
virtual ~ XArray ( ) ;
public :
2020-03-12 15:40:38 +01:00
const TYPE * data ( ) const { return m_data ; }
TYPE * data ( ) { return m_data ; }
2020-02-23 12:21:28 +01:00
public :
2020-03-09 02:12:24 +01:00
xsize AllocatedSize ( ) const { return m_allocatedSize ; }
xsize size ( ) const { return m_len ; }
void setSize ( xsize l ) ;
2020-02-23 12:21:28 +01:00
2020-02-27 10:17:50 +01:00
//low case functions like in std::vector
2020-03-09 02:12:24 +01:00
2020-02-27 10:17:50 +01:00
const TYPE & begin ( ) const { return ElementAt ( 0 ) ; }
TYPE & begin ( ) { return ElementAt ( 0 ) ; }
const TYPE & end ( ) const { return ElementAt ( m_len - 1 ) ; }
TYPE & end ( ) { return ElementAt ( m_len - 1 ) ; }
xsize insert ( const TYPE newElement , xsize pos , xsize count = 1 ) { return Insert ( newElement , pos , count ) ; }
2020-02-27 14:11:03 +01:00
2020-02-27 10:17:50 +01:00
//--------------------------------------------------
2020-02-23 12:21:28 +01:00
const TYPE & ElementAt ( xsize nIndex ) const ;
TYPE & ElementAt ( xsize nIndex ) ;
2020-03-11 15:23:58 +01:00
const TYPE & ElementAt ( int nIndex ) const ;
TYPE & ElementAt ( int nIndex ) ;
2020-02-23 12:21:28 +01:00
const TYPE & operator [ ] ( xsize nIndex ) const { return ElementAt ( nIndex ) ; }
TYPE & operator [ ] ( xsize nIndex ) { return ElementAt ( nIndex ) ; }
2020-02-27 10:17:50 +01:00
const TYPE & operator [ ] ( int nIndex ) const { return ElementAt ( nIndex ) ; }
TYPE & operator [ ] ( int nIndex ) { return ElementAt ( nIndex ) ; }
2020-02-23 12:21:28 +01:00
operator const void * ( ) const { return m_data ; } ;
operator void * ( ) { return m_data ; } ;
operator const TYPE * ( ) const { return m_data ; } ;
operator TYPE * ( ) { return m_data ; } ;
const TYPE * operator + ( int i ) const { return m_data + i ; } ;
TYPE * operator + ( int i ) { return m_data + i ; } ;
const TYPE * operator + ( xsize i ) const { return m_data + i ; } ;
TYPE * operator + ( xsize i ) { return m_data + i ; } ;
const TYPE * operator - ( int i ) const { return m_data - i ; } ;
TYPE * operator - ( int i ) { return m_data - i ; } ;
const TYPE * operator - ( xsize i ) const { return m_data - i ; } ;
TYPE * operator - ( xsize i ) { return m_data - i ; } ;
// xsize Add(const TYPE newElement);
// TYPE AddNew();
// xsize Inserts(const TYPE &newElement, xsize pos, xsize count);
void CheckSize ( xsize nNewSize ) ;
void CheckSize ( xsize nNewSize , xsize nGrowBy ) ;
xsize AddUninitialized ( xsize count ) ; // add count uninitialzed elements
xsize Add ( const TYPE newElement , xsize count = 1 ) ;
xsize AddArray ( const TYPE * newElements , xsize count = 1 ) ;
xsize Insert ( const TYPE newElement , xsize pos , xsize count = 1 ) ;
void Remove ( const TYPE * Element ) ;
void Remove ( const TYPE & Element ) ;
void RemoveAtIndex ( xsize nIndex ) ;
void RemoveAtIndex ( int nIndex ) ;
2020-02-27 13:32:14 +01:00
void setEmpty ( ) ;
2020-03-10 12:51:04 +01:00
bool isEmpty ( ) const { return size ( ) = = 0 ; }
2020-02-23 12:21:28 +01:00
2020-02-27 15:34:29 +01:00
xsize IdxOf ( TYPE & e ) const ;
2020-02-23 12:21:28 +01:00
bool ExistIn ( TYPE & e ) const { return IdxOf ( e ) ! = MAX_XSIZE ; }
} ;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//
// XArray
//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
template < class TYPE >
xsize XArray < TYPE > : : IdxOf ( TYPE & e ) const
{
xsize i ;
2020-03-09 02:12:24 +01:00
for ( i = 0 ; i < size ( ) ; i + = 1 ) {
2020-02-23 12:21:28 +01:00
if ( ElementAt ( i ) = = e ) return i ;
}
return MAX_XSIZE ;
}
/* Constructeur */
template < class TYPE >
void XArray < TYPE > : : Init ( )
{
2020-02-23 21:23:31 +01:00
m_data = nullptr ;
2020-03-09 02:12:24 +01:00
m_allocatedSize = 0 ;
2020-02-23 12:21:28 +01:00
m_len = 0 ;
_GrowBy = XArrayGrowByDefault ;
}
/* Constructeur */
template < class TYPE >
XArray < TYPE > : : XArray ( const XArray < TYPE > & anArray )
{
Init ( ) ;
2020-03-12 15:40:38 +01:00
AddArray ( anArray . data ( ) , anArray . size ( ) ) ;
2020-02-23 12:21:28 +01:00
}
/* operator = */
template < class TYPE >
const XArray < TYPE > & XArray < TYPE > : : operator = ( const XArray < TYPE > & anArray )
{
xsize ui ;
2020-02-27 14:11:03 +01:00
setEmpty ( ) ;
2020-03-12 15:40:38 +01:00
for ( ui = 0 ; ui < anArray . length ( ) ; ui + = 1 ) Add ( anArray [ ui ] ) ;
2020-02-23 12:21:28 +01:00
return * this ;
}
/* Destructeur */
template < class TYPE >
XArray < TYPE > : : ~ XArray ( )
{
//printf("XArray Destructor\n");
if ( m_data ) Xfree ( m_data ) ;
}
/* CheckSize() */
template < class TYPE >
void XArray < TYPE > : : CheckSize ( xsize nNewSize , xsize nGrowBy )
{
//XArray_DBG("CheckSize: m_len=%d, m_size=%d, nGrowBy=%d, nNewSize=%d\n", m_len, m_size, nGrowBy, nNewSize);
2020-03-09 02:12:24 +01:00
if ( nNewSize > m_allocatedSize ) {
2020-02-23 12:21:28 +01:00
nNewSize + = nGrowBy ;
2020-03-09 02:12:24 +01:00
m_data = ( TYPE * ) Xrealloc ( m_allocatedSize * sizeof ( TYPE ) , nNewSize * sizeof ( TYPE ) , ( void * ) m_data ) ;
2020-02-23 12:21:28 +01:00
if ( ! m_data ) {
2020-03-09 02:12:24 +01:00
DebugLog ( 2 , " XArray<TYPE>::CheckSize(nNewSize=%llu, nGrowBy=%llu) : Xrealloc(%d, %d, %d) returned NULL. System halted \n " , nNewSize , nGrowBy , m_allocatedSize , nNewSize * sizeof ( TYPE ) , m_data ) ;
panic ( ) ;
2020-02-23 12:21:28 +01:00
}
// memset(&_Data[_Size], 0, (nNewSize-_Size) * sizeof(TYPE)); // Could help for debugging, but zeroing in not needed.
2020-03-09 02:12:24 +01:00
m_allocatedSize = nNewSize ;
2020-02-23 12:21:28 +01:00
}
}
/* CheckSize() */
template < class TYPE >
void XArray < TYPE > : : CheckSize ( xsize nNewSize )
{
CheckSize ( nNewSize , XArrayGrowByDefault ) ;
}
/* SetLength (xsize i) */
template < class TYPE >
2020-03-09 02:12:24 +01:00
void XArray < TYPE > : : setSize ( xsize l )
2020-02-23 12:21:28 +01:00
{
2020-03-06 08:55:52 +01:00
CheckSize ( l , XArrayGrowByDefault ) ; // be sure the size is allocated
2020-02-23 12:21:28 +01:00
m_len = l ;
# ifdef DEBUG
2020-03-09 02:12:24 +01:00
if ( m_len > m_allocatedSize ) {
2020-02-23 12:21:28 +01:00
DebugLog ( 2 , " XArray::SetLength(xsize) -> _Len > _Size " ) ;
2020-03-09 02:12:24 +01:00
panic ( ) ;
2020-02-23 12:21:28 +01:00
}
# endif
}
/* ElementAt() */
template < class TYPE >
TYPE & XArray < TYPE > : : ElementAt ( xsize index )
{
2020-03-06 08:55:52 +01:00
// #ifdef _DEBUG
2020-02-23 12:21:28 +01:00
if ( index > = m_len ) {
DebugLog ( 2 , " XArray::ElementAt(xsize) -> Operator [] : index > m_len " ) ;
2020-03-09 02:12:24 +01:00
panic ( ) ;
2020-02-23 12:21:28 +01:00
}
2020-03-06 08:55:52 +01:00
// #endif
2020-02-23 12:21:28 +01:00
return m_data [ index ] ;
}
/* ElementAt() */
template < class TYPE >
const TYPE & XArray < TYPE > : : ElementAt ( xsize index ) const
{
2020-03-06 08:55:52 +01:00
// #ifdef _DEBUG
2020-02-23 12:21:28 +01:00
if ( index > = m_len ) {
DebugLog ( 2 , " XArray::ElementAt(xsize) const -> Operator [] : index > m_len " ) ;
2020-03-09 02:12:24 +01:00
panic ( ) ;
2020-02-23 12:21:28 +01:00
}
2020-03-06 08:55:52 +01:00
// #endif
2020-02-23 12:21:28 +01:00
return m_data [ index ] ;
}
2020-03-11 15:23:58 +01:00
/* ElementAt() */
template < class TYPE >
TYPE & XArray < TYPE > : : ElementAt ( int index )
{
// #ifdef _DEBUG
if ( index < 0 ) {
panic ( " XArray::ElementAt(int) -> Operator [] : index < 0 " ) ;
}
if ( ( unsigned int ) index > = m_len ) { // cast safe, index > 0
DebugLog ( 2 , " XArray::ElementAt(xsize) -> Operator [] : index > m_len " ) ;
panic ( ) ;
}
// #endif
return m_data [ index ] ;
}
/* ElementAt() */
template < class TYPE >
const TYPE & XArray < TYPE > : : ElementAt ( int index ) const
{
// #ifdef _DEBUG
if ( index < 0 ) {
panic ( " XArray::ElementAt(int) const -> Operator [] : index < 0 " ) ;
}
if ( ( unsigned int ) index > = m_len ) { // cast ok as index > 0. Ideally cast would be like '(unsigned __typeof__(index))'
DebugLog ( 2 , " XArray::ElementAt(xsize) const -> Operator [] : index > m_len " ) ;
panic ( ) ;
}
// #endif
return m_data [ index ] ;
}
2020-02-23 12:21:28 +01:00
/* Add(xsize) */
template < class TYPE >
xsize XArray < TYPE > : : AddUninitialized ( xsize count )
{
CheckSize ( m_len + count ) ;
m_len + = count ;
return m_len - count ;
}
/* Add(TYPE, xsize) */
template < class TYPE >
xsize XArray < TYPE > : : Add ( const TYPE newElement , xsize count )
{
// XArray_DBG("xsize XArray<TYPE>::Add(const TYPE newElement, xsize count) -> Enter. count=%d _Len=%d _Size=%d\n", count, m_len, m_size);
xsize i ;
CheckSize ( m_len + count ) ;
for ( i = 0 ; i < count ; i + + ) {
m_data [ m_len + i ] = newElement ;
}
m_len + = count ;
return m_len - count ;
}
/* Add(TYPE *, xsize) */
template < class TYPE >
xsize XArray < TYPE > : : AddArray ( const TYPE * newElements , xsize count )
{
xsize i ;
CheckSize ( m_len + count ) ;
for ( i = 0 ; i < count ; i + + ) {
m_data [ m_len + i ] = newElements [ i ] ;
}
m_len + = count ;
return m_len - count ;
}
/* Insert(TYPE &, xsize, xsize) */
template < class TYPE >
xsize XArray < TYPE > : : Insert ( const TYPE newElement , xsize pos , xsize count )
{
xsize i ;
if ( pos < m_len ) {
CheckSize ( m_len + count ) ;
memmove ( & m_data [ pos ] , & m_data [ pos + count ] , ( m_len - pos ) * sizeof ( TYPE ) ) ;
for ( i = 0 ; i < count ; i + + ) {
m_data [ pos + i ] = newElement ;
}
m_len + = count ;
return pos ;
} else {
return Add ( newElement , count ) ;
}
}
/* Remove(xsize) */
template < class TYPE >
void XArray < TYPE > : : RemoveAtIndex ( xsize nIndex )
{
if ( nIndex < m_len ) {
2020-02-23 21:23:31 +01:00
if ( nIndex < m_len - 1 ) Xmemmove ( & m_data [ nIndex ] , & m_data [ nIndex + 1 ] , ( m_len - nIndex - 1 ) * sizeof ( TYPE ) ) ;
2020-02-23 12:21:28 +01:00
m_len - = 1 ;
return ;
}
# if defined(_DEBUG) && defined(TRACE)
TRACE ( " XArray::Remove(xsize) -> nIndex > m_len \n " ) ;
# endif
}
/* Remove(int) */
template < class TYPE >
void XArray < TYPE > : : RemoveAtIndex ( int nIndex )
{
# if defined(__XTOOLS_INT_CHECK__)
if ( nIndex < 0 ) {
DebugLog ( 2 , " XArray<TYPE>::RemoveAtIndex(int nIndex) : BUG nIndex (%d) is < 0. System halted \n " , nIndex ) ;
2020-03-09 02:12:24 +01:00
panic ( ) ;
2020-02-23 12:21:28 +01:00
}
# endif
RemoveAtIndex ( ( xsize ) nIndex ) ; // Check of nIndex is made in Remove(xsize nIndex)
return ;
}
/* Remove(TYPE) */
template < class TYPE >
void XArray < TYPE > : : Remove ( const TYPE & Element )
{
xsize i ;
for ( i = 0 ; i < m_len ; i + = 1 ) {
if ( m_data [ i ] = = Element ) {
Remove ( i ) ;
return ;
}
}
# if defined(_DEBUG) && defined(TRACE)
TRACE ( " XArray::Remove(const TYPE &) -> Element not found \n " ) ;
# endif
}
/* Remove(TYPE *) */
template < class TYPE >
void XArray < TYPE > : : Remove ( const TYPE * Element )
{
Remove ( * Element ) ;
}
/* Empty() */
template < class TYPE >
2020-02-27 13:32:14 +01:00
void XArray < TYPE > : : setEmpty ( )
2020-02-23 12:21:28 +01:00
{
//printf("XArray Empty\n");
m_len = 0 ;
}
# endif