2021-04-28 20:30:34 +02:00
/*
*
* Created by jief in 1997.
* Copyright ( c ) 2020 Jief
* All rights reserved .
*
*/
2020-02-23 12:21:28 +01:00
# if !defined(__XARRAY_H__)
# define __XARRAY_H__
2020-04-24 08:36:29 +02:00
# include <XToolsConf.h>
2021-03-26 10:43:15 +01:00
# include "XToolsCommon.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 :
2020-08-22 15:39:24 +02:00
TYPE * m_data ;
2020-08-11 14:43:53 +02:00
size_t m_len ;
size_t m_allocatedSize ;
2020-02-23 12:21:28 +01:00
public :
2020-08-11 14:43:53 +02:00
// void Init();
XArray ( ) : m_data ( 0 ) , m_len ( 0 ) , m_allocatedSize ( 0 ) { }
2020-02-23 12:21:28 +01:00
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-08-11 14:43:53 +02:00
size_t allocatedSize ( ) const { return m_allocatedSize ; }
size_t length ( ) const { return m_len ; }
size_t size ( ) const { return m_len ; }
void setSize ( size_t 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
2021-04-11 07:18:52 +02:00
const TYPE & begin ( ) const { if ( m_len = = 0 ) panic ( " m_len == 0 " ) ; return ElementAt ( 0 ) ; }
TYPE & begin ( ) { if ( m_len = = 0 ) panic ( " m_len == 0 " ) ; return ElementAt ( 0 ) ; }
2020-02-27 10:17:50 +01:00
2021-04-11 07:18:52 +02:00
const TYPE & end ( ) const { if ( m_len = = 0 ) panic ( " m_len == 0 " ) ; return ElementAt ( m_len - 1 ) ; }
TYPE & end ( ) { if ( m_len = = 0 ) panic ( " m_len == 0 " ) ; return ElementAt ( m_len - 1 ) ; }
2020-02-27 10:17:50 +01:00
2020-08-11 14:43:53 +02:00
size_t insert ( const TYPE newElement , size_t pos , size_t count = 1 ) { return Insert ( newElement , pos , count ) ; }
2020-02-27 14:11:03 +01:00
2020-02-27 10:17:50 +01:00
//--------------------------------------------------
2021-03-26 10:43:15 +01:00
template < typename IntegralType , enable_if ( is_integral ( IntegralType ) ) >
const TYPE & ElementAt ( IntegralType index ) const
{
2022-01-23 13:19:15 +01:00
# ifdef JIEF_DEBUG
2021-03-26 10:43:15 +01:00
if ( index < 0 ) {
panic ( " XArray::ElementAt(int) -> Operator [] : index < 0 " ) ;
}
if ( ( unsigned int ) index > = m_len ) { // cast safe, index > 0
panic ( " XArray::ElementAt(int) -> Operator [] : index > m_len " ) ;
}
# endif
return m_data [ index ] ;
}
template < typename IntegralType , enable_if ( is_integral ( IntegralType ) ) >
TYPE & ElementAt ( IntegralType index ) { return const_cast < TYPE & > ( const_cast < const XArray < TYPE > * > ( this ) - > ElementAt ( index ) ) ; }
template < typename IntegralType , enable_if ( is_integral ( IntegralType ) ) >
const TYPE & operator [ ] ( IntegralType nIndex ) const { return ElementAt ( nIndex ) ; }
template < typename IntegralType , enable_if ( is_integral ( IntegralType ) ) >
TYPE & operator [ ] ( IntegralType nIndex ) { return ElementAt ( nIndex ) ; }
2020-02-23 12:21:28 +01:00
2021-04-11 07:18:52 +02:00
bool operator = = ( const XArray < TYPE > & other ) const
{
if ( size ( ) ! = other . size ( ) ) return false ;
for ( size_t idx = 0 ; idx < other . size ( ) ; + + idx ) {
if ( ! ( ElementAt ( idx ) = = other . ElementAt ( idx ) ) ) return false ;
}
return true ;
}
bool isEqual ( const XArray < TYPE > & other ) const
{
if ( size ( ) ! = other . size ( ) ) return false ;
for ( size_t idx = 0 ; idx < other . size ( ) ; + + idx ) {
if ( ! ( ElementAt ( idx ) . isEqual ( other . ElementAt ( idx ) ) ) ) return false ;
}
return true ;
}
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 ; } ;
2020-08-11 14:43:53 +02:00
const TYPE * operator + ( size_t i ) const { return m_data + i ; } ;
TYPE * operator + ( size_t i ) { return m_data + i ; } ;
2020-02-23 12:21:28 +01:00
const TYPE * operator - ( int i ) const { return m_data - i ; } ;
TYPE * operator - ( int i ) { return m_data - i ; } ;
2020-08-11 14:43:53 +02:00
const TYPE * operator - ( size_t i ) const { return m_data - i ; } ;
TYPE * operator - ( size_t i ) { return m_data - i ; } ;
2020-02-23 12:21:28 +01:00
2020-08-11 14:43:53 +02:00
// size_t Add(const TYPE newElement);
2020-02-23 12:21:28 +01:00
// TYPE AddNew();
2020-08-11 14:43:53 +02:00
// size_t Inserts(const TYPE &newElement, size_t pos, size_t count);
2020-02-23 12:21:28 +01:00
2020-08-11 14:43:53 +02:00
void CheckSize ( size_t nNewSize ) ;
void CheckSize ( size_t nNewSize , size_t nGrowBy ) ;
2020-02-23 12:21:28 +01:00
2020-08-11 14:43:53 +02:00
size_t AddUninitialized ( size_t count ) ; // add count uninitialzed elements
size_t Add ( const TYPE newElement , size_t count = 1 ) ;
size_t AddArray ( const TYPE * newElements , size_t count = 1 ) ;
size_t Insert ( const TYPE newElement , size_t pos , size_t count = 1 ) ;
2020-02-23 12:21:28 +01:00
void Remove ( const TYPE * Element ) ;
void Remove ( const TYPE & Element ) ;
2020-08-11 14:43:53 +02:00
void RemoveAtIndex ( size_t nIndex ) ;
2020-02-23 12:21:28 +01:00
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-08-11 14:43:53 +02:00
size_t indexOf ( TYPE & e ) const ;
2020-04-23 22:43:35 +02:00
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-08-11 14:43:53 +02:00
size_t XArray < TYPE > : : indexOf ( TYPE & e ) const
2020-02-23 12:21:28 +01:00
{
2020-08-11 14:43:53 +02:00
size_t i ;
2020-02-23 12:21:28 +01:00
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 ;
}
2020-08-11 14:43:53 +02:00
///* Constructeur */
//template<class TYPE>
//void XArray<TYPE>::Init()
//{
// m_data = nullptr;
// m_allocatedSize = 0;
// m_len = 0;
// _GrowBy = XArrayGrowByDefault;
//}
2020-02-23 12:21:28 +01:00
/* Constructeur */
template < class TYPE >
2020-08-11 14:43:53 +02:00
XArray < TYPE > : : XArray ( const XArray < TYPE > & anArray ) : m_data ( 0 ) , m_len ( 0 ) , m_allocatedSize ( 0 )
2020-02-23 12:21:28 +01:00
{
2020-08-11 14:43:53 +02:00
// 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 ( ) ;
}
//
//
2020-08-11 14:43:53 +02:00
//size_t ui;
2020-03-30 23:42:58 +02:00
//
// 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 >
2020-08-11 14:43:53 +02:00
void XArray < TYPE > : : CheckSize ( size_t nNewSize , size_t nGrowBy )
2020-02-23 12:21:28 +01:00
{
//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 ) {
2022-01-23 13:19:15 +01:00
# ifdef JIEF_DEBUG
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 ) ;
2021-02-21 14:49:09 +01:00
# endif
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 >
2020-08-11 14:43:53 +02:00
void XArray < TYPE > : : CheckSize ( size_t nNewSize )
2020-02-23 12:21:28 +01:00
{
CheckSize ( nNewSize , XArrayGrowByDefault ) ;
}
2020-08-11 14:43:53 +02:00
/* SetLength (size_t i) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
void XArray < TYPE > : : setSize ( size_t l )
2020-02-23 12:21:28 +01:00
{
2020-08-12 17:15:47 +02:00
CheckSize ( l , 0 ) ; // be sure the size is allocated
2020-02-23 12:21:28 +01:00
m_len = l ;
2022-01-23 13:19:15 +01:00
# ifdef JIEF_DEBUG
2020-03-09 02:12:24 +01:00
if ( m_len > m_allocatedSize ) {
2020-08-11 14:43:53 +02:00
panic ( " XArray::SetLength(size_t) -> _Len > _Size " ) ;
2020-02-23 12:21:28 +01:00
}
# endif
}
2020-08-11 14:43:53 +02:00
/* Add(size_t) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
size_t XArray < TYPE > : : AddUninitialized ( size_t count )
2020-02-23 12:21:28 +01:00
{
CheckSize ( m_len + count ) ;
m_len + = count ;
return m_len - count ;
}
2020-08-11 14:43:53 +02:00
/* Add(TYPE, size_t) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
size_t XArray < TYPE > : : Add ( const TYPE newElement , size_t count )
2020-02-23 12:21:28 +01:00
{
2020-08-11 14:43:53 +02:00
// XArray_DBG("size_t XArray<TYPE>::Add(const TYPE newElement, size_t count) -> Enter. count=%d _Len=%d _Size=%d\n", count, m_len, m_size);
size_t i ;
2020-02-23 12:21:28 +01:00
CheckSize ( m_len + count ) ;
for ( i = 0 ; i < count ; i + + ) {
m_data [ m_len + i ] = newElement ;
}
m_len + = count ;
return m_len - count ;
}
2020-08-11 14:43:53 +02:00
/* Add(TYPE *, size_t) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
size_t XArray < TYPE > : : AddArray ( const TYPE * newElements , size_t count )
2020-02-23 12:21:28 +01:00
{
2020-08-11 14:43:53 +02:00
size_t i ;
2020-02-23 12:21:28 +01:00
CheckSize ( m_len + count ) ;
for ( i = 0 ; i < count ; i + + ) {
m_data [ m_len + i ] = newElements [ i ] ;
}
m_len + = count ;
return m_len - count ;
}
2020-08-11 14:43:53 +02:00
/* Insert(TYPE &, size_t, size_t) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
size_t XArray < TYPE > : : Insert ( const TYPE newElement , size_t pos , size_t count )
2020-02-23 12:21:28 +01:00
{
2020-08-11 14:43:53 +02:00
size_t i ;
2020-02-23 12:21:28 +01:00
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 ) ;
}
}
2020-08-11 14:43:53 +02:00
/* Remove(size_t) */
2020-02-23 12:21:28 +01:00
template < class TYPE >
2020-08-11 14:43:53 +02:00
void XArray < TYPE > : : RemoveAtIndex ( size_t nIndex )
2020-02-23 12:21:28 +01:00
{
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)
2020-08-11 14:43:53 +02:00
TRACE ( " XArray::Remove(size_t) -> nIndex > m_len \n " ) ;
2020-02-23 12:21:28 +01:00
# 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
2020-08-11 14:43:53 +02:00
RemoveAtIndex ( ( size_t ) nIndex ) ; // Check of nIndex is made in Remove(size_t nIndex)
2020-02-23 12:21:28 +01:00
return ;
}
/* Remove(TYPE) */
template < class TYPE >
void XArray < TYPE > : : Remove ( const TYPE & Element )
{
2020-08-11 14:43:53 +02:00
size_t i ;
2020-02-23 12:21:28 +01:00
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