//+------------------------------------------------------------------+ //| ArrayObj.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "Array.mqh" //+------------------------------------------------------------------+ //| Class CArrayObj. | //| Puprose: Class of dynamic array of pointers to instances | //| of the CObject class and its derivatives. | //| Derives from class CArray. | //+------------------------------------------------------------------+ class CArrayObj : public CArray { protected: CObject *m_data[]; // data array bool m_free_mode; // flag of necessity of "physical" deletion of object public: CArrayObj(void); ~CArrayObj(void); //--- methods of access to protected data bool FreeMode(void) const { return(m_free_mode); } void FreeMode(const bool mode) { m_free_mode=mode; } //--- method of identifying the object virtual int Type(void) const { return(0x7778); } //--- methods for working with files virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); //--- method of creating an element of array virtual bool CreateElement(const int index) { return(false); } //--- methods of managing dynamic memory bool Reserve(const int size); bool Resize(const int size); bool Shutdown(void); //--- methods of filling the array bool Add(CObject *element); bool AddArray(const CArrayObj *src); bool Insert(CObject *element,const int pos); bool InsertArray(const CArrayObj *src,const int pos); bool AssignArray(const CArrayObj *src); //--- method of access to thre array CObject *At(const int index) const; //--- methods of changing bool Update(const int index,CObject *element); bool Shift(const int index,const int shift); //--- methods of deleting CObject *Detach(const int index); bool Delete(const int index); bool DeleteRange(int from,int to); void Clear(void); //--- method for comparing arrays bool CompareArray(const CArrayObj *array) const; //--- methods for working with the sorted array bool InsertSort(CObject *element); int Search(const CObject *element) const; int SearchGreat(const CObject *element) const; int SearchLess(const CObject *element) const; int SearchGreatOrEqual(const CObject *element) const; int SearchLessOrEqual(const CObject *element) const; int SearchFirst(const CObject *element) const; int SearchLast(const CObject *element) const; protected: void QuickSort(int beg,int end,const int mode); int QuickSearch(const CObject *element) const; int MemMove(const int dest,const int src,int count); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CArrayObj::CArrayObj(void) : m_free_mode(true) { //--- initialize protected data m_data_max=ArraySize(m_data); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CArrayObj::~CArrayObj(void) { if(m_data_max!=0) Shutdown(); } //+------------------------------------------------------------------+ //| Moving the memory within a single array | //+------------------------------------------------------------------+ int CArrayObj::MemMove(const int dest,const int src,int count) { int i; //--- check parameters if(dest<0 || src<0 || count<0) return(-1); //--- check count if(src+count>m_data_total) count=m_data_total-src; if(count<0) return(-1); //--- no need to copy if(dest==src || count==0) return(dest); //--- check data total if(dest+count>m_data_total) { if(m_data_max=0;i--) { //--- "physical" removal of the object (if necessary and possible) if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC) delete m_data[dest+i]; //--- m_data[dest+i]=m_data[src+i]; m_data[src+i]=NULL; } } //--- successful return(dest); } //+------------------------------------------------------------------+ //| Request for more memory in an array. Checks if the requested | //| number of free elements already exists; allocates additional | //| memory with a given step | //+------------------------------------------------------------------+ bool CArrayObj::Reserve(const int size) { int new_size; //--- check if(size<=0) return(false); //--- resize array if(Available()=size); } //+------------------------------------------------------------------+ //| Resizing (with removal of elements on the right) | //+------------------------------------------------------------------+ bool CArrayObj::Resize(const int size) { int new_size; //--- check if(size<0) return(false); //--- resize array new_size=m_step_resize*(1+size/m_step_resize); if(m_data_total>size) { //--- "physical" removal of the object (if necessary and possible) if(m_free_mode) for(int i=size;i=m_data_total) return(NULL); //--- result return(m_data[index]); } //+------------------------------------------------------------------+ //| Updating element in the specified position | //+------------------------------------------------------------------+ bool CArrayObj::Update(const int index,CObject *element) { //--- check if(index<0 || !CheckPointer(element) || index>=m_data_total) return(false); //--- "physical" removal of the object (if necessary and possible) if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) delete m_data[index]; //--- update m_data[index]=element; m_sort_mode=-1; //--- successful return(true); } //+------------------------------------------------------------------+ //| Moving element from the specified position | //| on the specified shift | //+------------------------------------------------------------------+ bool CArrayObj::Shift(const int index,const int shift) { CObject *tmp_node; //--- check if(index<0 || index+shift<0 || index+shift>=m_data_total) return(false); if(shift==0) return(true); //--- move tmp_node=m_data[index]; m_data[index]=NULL; if(shift>0) { if(MemMove(index,index+1,shift)<0) return(false); } else { if(MemMove(index+shift+1,index+shift,-shift)<0) return(false); } m_data[index+shift]=tmp_node; m_sort_mode=-1; //--- successful return(true); } //+------------------------------------------------------------------+ //| Deleting element from the specified position | //+------------------------------------------------------------------+ bool CArrayObj::Delete(const int index) { //--- check if(index>=m_data_total) return(false); //--- delete if(index=0 && MemMove(index,index+1,m_data_total-index-1)<0) return(false); } else if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) delete m_data[index]; m_data_total--; //--- successful return(true); } //+------------------------------------------------------------------+ //| Detach element from the specified position | //+------------------------------------------------------------------+ CObject *CArrayObj::Detach(const int index) { CObject *result; //--- check if(index>=m_data_total) return(NULL); //--- detach result=m_data[index]; //--- reset the array element, so as not remove the method MemMove m_data[index]=NULL; if(indexto || from>=m_data_total) return(false); //--- delete if(to>=m_data_total-1) to=m_data_total-1; if(MemMove(from,to+1,m_data_total-to-1)<0) return(false); for(int i=to-from+1;i>0;i--,m_data_total--) if(m_free_mode && CheckPointer(m_data[m_data_total-1])==POINTER_DYNAMIC) delete m_data[m_data_total-1]; //--- successful return(true); } //+------------------------------------------------------------------+ //| Clearing of array without the release of memory | //+------------------------------------------------------------------+ void CArrayObj::Clear(void) { //--- "physical" removal of the object (if necessary and possible) if(m_free_mode) { for(int i=0;i>1" is quick division by 2 p_node=m_data[(beg+end)>>1]; while(i0) { //--- control the output of the array bounds if(j==0) break; j--; } if(i<=j) { t_node=m_data[i]; m_data[i++]=m_data[j]; m_data[j]=t_node; //--- control the output of the array bounds if(j==0) break; j--; } } if(beg0) Insert(element,pos); else Insert(element,pos+1); //--- restore the sorting flag after Insert(...) m_sort_mode=mode; //--- successful return(true); } //+------------------------------------------------------------------+ //| Quick search of position of element in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::QuickSearch(const CObject *element) const { int i,j,m=-1; CObject *t_node; //--- search i=0; j=m_data_total-1; while(j>=i) { //--- ">>1" is quick division by 2 m=(j+i)>>1; if(m<0 || m==m_data_total-1) break; t_node=m_data[m]; if(t_node.Compare(element,m_sort_mode)==0) break; if(t_node.Compare(element,m_sort_mode)>0) j=m-1; else i=m+1; } //--- position return(m); } //+------------------------------------------------------------------+ //| Search of position of element in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::Search(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); if(m_data[pos].Compare(element,m_sort_mode)==0) return(pos); //--- not found return(-1); } //+------------------------------------------------------------------+ //| Search position of the first element which is greater than | //| specified in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchGreat(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); while(m_data[pos].Compare(element,m_sort_mode)<=0) if(++pos==m_data_total) return(-1); //--- position return(pos); } //+------------------------------------------------------------------+ //| Search position of the first element which is less than | //| specified in the sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchLess(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); while(m_data[pos].Compare(element,m_sort_mode)>=0) if(pos--==0) return(-1); //--- position return(pos); } //+------------------------------------------------------------------+ //| Search position of the first element which is greater than or | //| equal to the specified in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchGreatOrEqual(const CObject *element) const { //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search for(int pos=QuickSearch(element);pos=0) return(pos); //--- not found return(-1); } //+------------------------------------------------------------------+ //| Search position of the first element which is less than or equal | //| to the specified in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchLessOrEqual(const CObject *element) const { //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search for(int pos=QuickSearch(element);pos>=0;pos--) if(m_data[pos].Compare(element,m_sort_mode)<=0) return(pos); //--- not found return(-1); } //+------------------------------------------------------------------+ //| Find position of first appearance of element in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchFirst(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); if(m_data[pos].Compare(element,m_sort_mode)==0) { while(m_data[pos].Compare(element,m_sort_mode)==0) if(pos--==0) break; return(pos+1); } //--- not found return(-1); } //+------------------------------------------------------------------+ //| Find position of last appearance of element in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::SearchLast(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); if(m_data[pos].Compare(element,m_sort_mode)==0) { while(m_data[pos].Compare(element,m_sort_mode)==0) if(++pos==m_data_total) break; return(pos-1); } //--- not found return(-1); } //+------------------------------------------------------------------+ //| Writing array to file | //+------------------------------------------------------------------+ bool CArrayObj::Save(const int file_handle) { int i=0; //--- check if(!CArray::Save(file_handle)) return(false); //--- write array length if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) return(false); //--- write array for(i=0;i