2020-02-23 12:21:28 +01:00
//*************************************************************************************************
//*************************************************************************************************
//
// XArray
//
// Developed by jief666, from 1997.
//
//*************************************************************************************************
//*************************************************************************************************
# if !defined(__XARRAY_H__)
# define __XARRAY_H__
2020-04-24 08:36:29 +02:00
# include <XToolsConf.h>
2020-02-23 12:21:28 +01:00
#if 0
2020-04-24 11:30:09 +02:00
# define XArray_DBG(...) printf(__VA_ARGS__)
2020-02-23 12:21:28 +01:00
# 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-30 23:42:58 +02:00
xsize allocatedSize ( ) const { return m_allocatedSize ; }
xsize length ( ) const { return m_len ; }
2020-03-09 02:12:24 +01:00
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
2020-04-23 22:43:35 +02:00
// const TYPE& operator[](xsize nIndex) const { return ElementAt(nIndex); }
// TYPE& operator[](xsize nIndex) { return ElementAt(nIndex); }
// const TYPE& operator[]( int nIndex) const { return ElementAt(nIndex); }
2020-02-27 10:17:50 +01:00
TYPE & operator [ ] ( int nIndex ) { return ElementAt ( nIndex ) ; }
2020-04-23 22:43:35 +02:00
// const TYPE& operator[]( unsigned long long nIndex) const { return ElementAt((size_t)nIndex); }
// const TYPE& operator[]( long long nIndex) const { return ElementAt((size_t)nIndex); }
TYPE & operator [ ] ( unsigned long long nIndex ) { return ElementAt ( ( size_t ) nIndex ) ; }
TYPE & operator [ ] ( long long nIndex ) { return ElementAt ( ( size_t ) 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-04-23 22:43:35 +02:00
xsize indexOf ( TYPE & e ) const ;
bool contains ( TYPE & e ) const { return indexOf ( e ) ! = MAX_XSIZE ; } //logically it should be named as Contains(e)
2020-02-23 12:21:28 +01:00
} ;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//
// XArray
//
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
template < class TYPE >
2020-04-23 22:43:35 +02:00
xsize XArray < TYPE > : : indexOf ( TYPE & e ) const
2020-02-23 12:21:28 +01:00
{
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 )
{
2020-03-30 23:42:58 +02:00
if ( anArray . length ( ) > 0 )
{
CheckSize ( anArray . length ( ) , 0 ) ;
memcpy ( m_data , anArray . m_data , anArray . m_len * sizeof ( TYPE ) ) ;
m_len = anArray . m_len ;
}
else
{
setEmpty ( ) ;
}
//
//
//xsize ui;
//
// setEmpty();
// 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");
2020-03-21 14:12:26 +01:00
if ( m_data ) free ( m_data ) ;
2020-02-23 12:21:28 +01:00
}
2020-04-23 15:20:48 +02:00
/* CheckSize() // nNewSize is number of TYPE, not in bytes */
2020-02-23 12:21:28 +01:00
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-04-24 08:36:29 +02:00
m_data = ( TYPE * ) Xrealloc ( ( void * ) m_data , nNewSize * sizeof ( TYPE ) , m_allocatedSize * sizeof ( TYPE ) ) ;
2020-02-23 12:21:28 +01:00
if ( ! m_data ) {
2020-04-24 11:30:09 +02:00
panic ( " XArray<TYPE>::CheckSize(nNewSize=%zu, nGrowBy=%zu) : Xrealloc(%zu, %lu, % " PRIuPTR " ) returned NULL. System halted \n " , nNewSize , nGrowBy , m_allocatedSize , nNewSize * sizeof ( TYPE ) , ( uintptr_t ) m_data ) ;
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-04-24 11:30:09 +02:00
panic ( " XArray::SetLength(xsize) -> _Len > _Size " ) ;
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 ) {
2020-04-24 11:30:09 +02:00
panic ( " XArray::ElementAt(xsize) -> Operator [] : index > m_len " ) ;
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 ) {
2020-04-24 11:30:09 +02:00
panic ( " XArray::ElementAt(xsize) const -> Operator [] : index > m_len " ) ;
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
2020-04-07 21:48:36 +02:00
if ( index < 0 ) {
2020-03-11 15:23:58 +01:00
panic ( " XArray::ElementAt(int) -> Operator [] : index < 0 " ) ;
}
if ( ( unsigned int ) index > = m_len ) { // cast safe, index > 0
2020-04-24 11:30:09 +02:00
panic ( " XArray::ElementAt(int) -> Operator [] : index > m_len " ) ;
2020-03-11 15:23:58 +01:00
}
// #endif
return m_data [ index ] ;
}
/* ElementAt() */
template < class TYPE >
const TYPE & XArray < TYPE > : : ElementAt ( int index ) const
{
// #ifdef _DEBUG
2020-04-07 21:48:36 +02:00
if ( index < 0 ) {
2020-03-11 15:23:58 +01:00
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))'
2020-04-24 11:30:09 +02:00
panic ( " XArray::ElementAt(int) const -> Operator [] : index > m_len " ) ;
2020-03-11 15:23:58 +01:00
}
// #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-03-21 14:12:26 +01:00
if ( nIndex < m_len - 1 ) memmove ( & 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 )
{
2020-04-24 08:36:29 +02:00
# if defined(__XTOOLS_CHECK_OVERFLOW__)
2020-02-23 12:21:28 +01:00
if ( nIndex < 0 ) {
2020-04-24 11:30:09 +02:00
panic ( " XArray<TYPE>::RemoveAtIndex(int nIndex) : BUG nIndex (%d) is < 0. System halted \n " , nIndex ) ;
}
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