//************************************************************************************************* //************************************************************************************************* // // XObjArray // // Developed by jief666, from 1997. // //************************************************************************************************* //************************************************************************************************* #if !defined(__XOBJARRAY_H__) #define __XOBJARRAY_H__ #include #include "XToolsCommon.h" #if 1 #define XObjArray_DBG(...) printf__VA_ARGS__) #else #define XObjArray_DBG(...) #endif template class XObjArrayEntry { public: TYPE* Object; bool FreeIt; }; template class XObjArrayNC { public: XObjArrayEntry *_Data; size_t _Len; size_t m_allocatedSize; public: void Init(); XObjArrayNC() { Init(); } virtual ~XObjArrayNC(); protected: // XObjArrayNC(const XObjArrayNC &anObjArrayNC) { (void)anObjArrayNC; panic("Intentionally not defined"); } // const XObjArrayNC &operator =(const XObjArrayNC &anObjArrayNC) { (void)anObjArrayNC; panic("Intentionally not defined"); } XObjArrayNC(const XObjArrayNC &anObjArrayNC) = delete; const XObjArrayNC &operator =(const XObjArrayNC &anObjArrayNC) = delete; xsize _getLen() const { return _Len; } public: xsize AllocatedSize() const { return m_allocatedSize; } xsize size() const { return _Len; } xsize length() const { return _Len; } bool NotNull() const { return size() > 0; } bool IsNull() const { return size() == 0; } template const TYPE &ElementAt(IntegralType nIndex) const { if (nIndex < 0) { panic("XObjArrayNC::ElementAt() : i < 0. System halted\n"); } if ( (unsigned_type(IntegralType))nIndex >= _Len ) { panic("XObjArrayNC::ElementAt() -> operator [] - index (%zu) greater than length (%zu)\n", (size_t)nIndex, _Len); } return *((TYPE *)(_Data[nIndex].Object)); } template TYPE &ElementAt(IntegralType nIndex) { if (nIndex < 0) { panic("XObjArrayNC::ElementAt() : i < 0. System halted\n"); } if ( (unsigned_type(IntegralType))nIndex >= _Len ) { panic("XObjArrayNC::ElementAt() const -> operator [] - index (%zu) greater than length (%zu)\n", (size_t)nIndex, _Len); } return *((TYPE *)(_Data[nIndex].Object)); } // This was useful for realtime debugging with a debugger that do not recognise references. That was years and years ago. Probably not needed anymore. // #ifdef _DEBUG_iufasdfsfk const TYPE *DbgAt(int i) const { if ( i >= 0 && (xsize)i < _Len ) return &ElementAt ((xsize) i); else return NULL; } // #endif template const TYPE &operator[](IntegralType nIndex) const { return ElementAt(nIndex); } template TYPE &operator[](IntegralType nIndex) { return ElementAt(nIndex); } xsize AddReference(TYPE *newElement, bool FreeIt); // xsize InsertRef(TYPE *newElement, xsize pos, bool FreeIt = false); xsize InsertRef(TYPE *newElement, xsize pos, bool FreeIt); void SetFreeIt(xsize nIndex, bool Flag); void SetFreeIt(const TYPE *Element, bool Flag); void Remove(const TYPE *Element); void RemoveWithoutFreeing(const TYPE *Element); void Remove(const TYPE &Element); void RemoveAtIndex(xsize nIndex); void RemoveAtIndex(int nIndex); void RemoveWithoutFreeing(xsize nIndex); // If you use this, there might be a design problem somewhere ??? //void Remove(int nIndex); void RemoveAllBut(const TYPE *Element); void Empty(); public: void CheckSize(xsize nNewSize, xsize nGrowBy = XArrayGrowByDefault); }; template class XObjArray : public XObjArrayNC { public: XObjArray() : XObjArrayNC() {} XObjArray(const XObjArray &anObjArray); const XObjArray &operator =(const XObjArray &anObjArray); xsize AddCopy(const TYPE &newElement, bool FreeIt = true); xsize AddCopies(const TYPE &n1, bool FreeIt = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, const TYPE &n13, bool FreeThem = true); xsize AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, const TYPE &n13, const TYPE &n14, bool FreeThem = true); //TYPE & AddNew(bool FreeIt = true); xsize InsertCopy(const TYPE &newElement, xsize pos); }; //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // // XObjArray // //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /* Constructeur */ template void XObjArrayNC::Init() { _Data = nullptr; m_allocatedSize = 0; _Len = 0; // THis was useful for realtime debugging with a debugger that do not recognise references. // #ifdef _DEBUG_iufasdfsfk // { // const TYPE *tmp; // tmp = DbgAt(0); // } // #endif } /* Constructeur */ template XObjArray::XObjArray(const XObjArray &anObjArray) : XObjArrayNC() { xsize ui; XObjArrayNC::Init(); this->CheckSize(anObjArray.size(), (xsize)0); for ( ui=0 ; ui const XObjArray &XObjArray::operator =(const XObjArray &anObjArray) { xsize ui; if ( this == &anObjArray ) return *this; // self assignement XObjArrayNC::Empty(); this->CheckSize(anObjArray.length(), 0); for ( ui=0 ; ui XObjArrayNC::~XObjArrayNC() { //printf("XObjArray Destructor\n"); Empty(); if ( _Data ) free(_Data); } /* CheckSize() */ template void XObjArrayNC::CheckSize(xsize nNewSize, xsize nGrowBy) { if ( m_allocatedSize < nNewSize ) { nNewSize += nGrowBy + 1; _Data = (XObjArrayEntry *)Xrealloc((void *)_Data, sizeof(XObjArrayEntry) * nNewSize, sizeof(XObjArrayEntry) * m_allocatedSize); if ( !_Data ) { panic("XObjArrayNC::CheckSize(nNewSize=%zu, nGrowBy=%zu) : Xrealloc(%zu, %zu, %" PRIuPTR ") returned NULL. System halted\n", nNewSize, nGrowBy, m_allocatedSize, sizeof(XObjArrayEntry) * nNewSize, (uintptr_t)_Data); } // memset(&_Data[m_allocatedSize], 0, (nNewSize-m_allocatedSize) * sizeof(XObjArrayEntry)); m_allocatedSize = nNewSize; } } ///* Add() */ //template //TYPE &XObjArray::AddNew(bool FreeIt) //{ // XObjArrayNC::CheckSize(XObjArray::_getLen()+1); // XObjArray::_Data[XObjArray::_Len].Object = new TYPE; // XObjArray::_Data[XObjArray::_Len].FreeIt = FreeIt; // XObjArray::_Len += 1; // return *((TYPE *)(XObjArray::_Data[XObjArray::_Len-1].Object)); //} /* Add(TYPE &, xsize) */ template xsize XObjArray::AddCopy(const TYPE &newElement, bool FreeIt) { XObjArrayNC::CheckSize(XObjArray::_Len+1); XObjArray::_Data[XObjArray::_Len].Object = new TYPE(newElement); XObjArray::_Data[XObjArray::_Len].FreeIt = FreeIt; XObjArray::_Len += 1; return XObjArray::_Len-1; } template xsize XObjArray::AddCopies(const TYPE &n1, bool FreeIt) { return AddCopy(n1, FreeIt); } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, bool FreeThem) { xsize ui = AddCopies(n1, FreeThem); AddCopy(n2, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, bool FreeThem) { xsize ui = AddCopies(n1, n2, FreeThem); AddCopy(n3, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, FreeThem); AddCopy(n4, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, FreeThem); AddCopy(n5, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, FreeThem); AddCopy(n6, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, FreeThem); AddCopy(n7, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, FreeThem); AddCopy(n8, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, FreeThem); AddCopy(n9, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, n9, FreeThem); AddCopy(n10, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, FreeThem); AddCopy(n11, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, FreeThem); AddCopy(n12, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, const TYPE &n13, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, FreeThem); AddCopy(n13, FreeThem); return ui; } template xsize XObjArray::AddCopies(const TYPE &n1, const TYPE &n2, const TYPE &n3, const TYPE &n4, const TYPE &n5, const TYPE &n6, const TYPE &n7, const TYPE &n8, const TYPE &n9, const TYPE &n10, const TYPE &n11, const TYPE &n12, const TYPE &n13, const TYPE &n14, bool FreeThem) { xsize ui = AddCopies(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, FreeThem); AddCopy(n14, FreeThem); return ui; } /* Add(TYPE *, xsize) */ template xsize XObjArrayNC::AddReference(TYPE *newElement, bool FreeIt) { XObjArrayNC::CheckSize(XObjArrayNC::_Len+1); XObjArrayNC::_Data[XObjArrayNC::_Len].Object = newElement; XObjArrayNC::_Data[XObjArrayNC::_Len].FreeIt = FreeIt; XObjArrayNC::_Len += 1; return XObjArrayNC::_Len-1; } /* Insert(TYPE &, xsize) */ template xsize XObjArray::InsertCopy(const TYPE &newElement, xsize pos) { if ( pos < XObjArray::_Len ) { XObjArrayNC::CheckSize(XObjArray::_Len+1); memmove(&XObjArray::_Data[pos+1], &XObjArray::_Data[pos], (XObjArray::_Len-pos)*sizeof(XObjArrayEntry)); XObjArray::_Data[pos].Object = new TYPE(newElement); XObjArray::_Data[pos].FreeIt = true; XObjArray::_Len += 1; return pos; }else{ return AddCopy(newElement); } } /* Insert(TYPE &, xsize) */ template xsize XObjArrayNC::InsertRef(TYPE *newElement, xsize pos, bool FreeIt) { if ( pos < XObjArrayNC::_Len ) { CheckSize(XObjArrayNC::_Len+1); memmove(&XObjArrayNC::_Data[pos+1], &XObjArrayNC::_Data[pos], (XObjArrayNC::_Len-pos)*sizeof(XObjArrayEntry)); _Data[pos].Object = newElement; _Data[pos].FreeIt = FreeIt; XObjArrayNC::_Len += 1; return pos; }else{ return AddRef(newElement, FreeIt); } } /* SetFreeIt(xsize, bool) */ template void XObjArrayNC::SetFreeIt(xsize nIndex, bool Flag) { if ( nIndex < XObjArrayNC::_Len ) { XObjArrayNC::_Data[nIndex].FreeIt = Flag; } else{ #if defined(_DEBUG) throw "XObjArray::SetFreeIt(xsize) -> nIndex >= _Len\n"; #endif } } /* SetFreeIt(const TYPE *Element, bool) */ template void XObjArrayNC::SetFreeIt(const TYPE *Element, bool Flag) { xsize i; for ( i=0 ; i < XObjArrayNC::_Len ; i+= 1) { if ( ((TYPE *)XObjArrayNC::_Data[i].Object) == Element ) { SetFreeIt(i, Flag); return ; } } #if defined(_DEBUG) throw "XObjArray::SetFreeIt(const TYPE *) -> nIndex >= _Len\n"; #endif } /* Remove(xsize) */ template void XObjArrayNC::RemoveAtIndex(xsize nIndex) { if ( nIndex < XObjArrayNC::_Len ) { if ( nIndex >= XObjArrayNC::_Len ) { panic("void XObjArrayNC::RemoveAtIndex(xsize nIndex) : BUG nIndex (%zu) is > length(). System halted\n", nIndex); } } if ( _Data[nIndex].FreeIt ) { TYPE *TmpObject; // BCB 4 oblige me to use a tmp var for doing the delete. TmpObject = (TYPE *)(_Data[nIndex].Object); delete TmpObject; } if ( nIndex::_Len-1 ) memmove(&_Data[nIndex], &_Data[nIndex+1], (_Len-nIndex-1)*sizeof(XObjArrayEntry)); _Len -= 1; return; } //------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------- /* RemoveWithoutFreeing(xsize) */ template void XObjArrayNC::RemoveWithoutFreeing(xsize nIndex) { if ( nIndex < _Len ) { if ( nIndex<_Len-1 ) memcpy(&_Data[nIndex], &_Data[nIndex+1], (_Len-nIndex-1)*sizeof(XObjArrayEntry)); _Len -= 1; return; } #if defined(_DEBUG) throw "XObjArray::RemoveWithoutFreeing(xsize) -> nIndex > _Len\n"; #endif } //------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------- /* Remove(int) */ template void XObjArrayNC::RemoveAtIndex(int nIndex) { #if defined(__XTOOLS_CHECK_OVERFLOW__) if ( nIndex < 0 ) { panic("XArray::RemoveAtIndex(int nIndex) : BUG nIndex (%d) is < 0. System halted\n", nIndex); } #endif RemoveAtIndex( (xsize)nIndex ); // Remove(xsize) will check that index is < _Len } /* Remove(const TYPE &) */ template void XObjArrayNC::Remove(const TYPE &Element) { xsize i; for ( i=0 ; i<_Len ; i+= 1) { if ( *((TYPE *)(_Data[i].Object)) == Element ) { RemoveAtIndex(i); return ; } } #if defined(_DEBUG) printf("XObjArray::Remove(TYPE &) -> Not found\n"); panic(); #endif } //------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------- /* Remove(const TYPE *) */ template void XObjArrayNC::Remove(const TYPE *Element) { xsize i; for ( i=0 ; i<_Len ; i+= 1) { if ( ((TYPE *)_Data[i].Object) == Element ) { Remove(i); return ; } } #if defined(_DEBUG) throw "XObjArray::Remove(TYPE *) -> not found\n"; #endif } //------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------- /* RemoveWithoutFreeing(const TYPE *) */ template void XObjArrayNC::RemoveWithoutFreeing(const TYPE *Element) { xsize i; for ( i=0 ; i<_Len ; i+= 1) { if ( ((TYPE *)_Data[i].Object) == Element ) { RemoveWithoutFreeing(i); return ; } } #if defined(_DEBUG) throw "XObjArray::RemoveWithoutFreeing(TYPE *) -> not found\n"; #endif } //------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------- template void XObjArrayNC::RemoveAllBut(const TYPE *Element) { xsize i; for ( i=_Len ; i-- ; ) { if ( ((TYPE *)_Data[i].Object) != Element ) { Remove(i); } } } /* Empty() */ template void XObjArrayNC::Empty() { xsize i; if ( _Len > 0 ) { for ( i=0 ; i<_Len ; i+= 1) { if ( _Data[i].FreeIt ) { TYPE *TmpObject; // BCB 4 oblige me to use a tmp var for doing the delete. TmpObject = (TYPE *)(_Data[i].Object); delete TmpObject; } } _Len = 0; } } #endif