//+------------------------------------------------------------------+ //| ArrayList.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include #include #include #include #include //+------------------------------------------------------------------+ //| Class CArrayList. | //| Usage: Represents a strongly typed list of values that can be | //| accessed by index. Provides methods to search, sort, and | //| manipulate lists. | //+------------------------------------------------------------------+ template class CArrayList: public IList { protected: T m_items[]; int m_size; const int m_default_capacity; public: CArrayList(void); CArrayList(const int capacity); CArrayList(ICollection*collection); CArrayList(T &array[]); ~CArrayList(void); //--- methods of access to protected data int Capacity(void); void Capacity(const int capacity); int Count(void); bool Contains(T item); void TrimExcess(void); //--- method of access to the data bool TryGetValue(const int index,T &value); bool TrySetValue(const int index,T value); //--- methods of filling the array bool Add(T item); bool AddRange(T &array[]); bool AddRange(ICollection*collection); bool Insert(const int index,T item); bool InsertRange(const int index,T &array[]); bool InsertRange(const int index,ICollection*collection); //--- methods of copy data from collection int CopyTo(T &dst_array[],const int dst_start=0); //--- methods for binary searching index int BinarySearch(T item); int BinarySearch(T item,IComparer*comparer); int BinarySearch(const int index,const int count,T item,IComparer*comparer); //--- methods for searching index int IndexOf(T item); int IndexOf(T item,const int start_index); int IndexOf(T item,const int start_index,const int count); int LastIndexOf(T item); int LastIndexOf(T item,const int start_index); int LastIndexOf(T item,const int start_index,const int count); //--- methods of cleaning and deleting void Clear(void); bool Remove(T item); bool RemoveAt(const int index); bool RemoveRange(const int start_index,const int count); //--- reversing method bool Reverse(void); bool Reverse(const int start_index,const int count); //--- sorting method bool Sort(void); bool Sort(IComparer*comparer); bool Sort(const int start_index,const int count,IComparer*comparer); private: void EnsureCapacity(const int min); }; //+------------------------------------------------------------------+ //| Initializes a new instance of the CArrayList class that is | //| empty and has the default initial capacity. | //+------------------------------------------------------------------+ template CArrayList::CArrayList(void): m_default_capacity(4), m_size(0) { ArrayResize(m_items,m_default_capacity); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CArrayList class that is | //| empty and has the specified initial capacity. | //+------------------------------------------------------------------+ template CArrayList::CArrayList(const int capacity): m_default_capacity(4), m_size(0) { ArrayResize(m_items,capacity); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CArrayList class that | //| contains elements copied from the specified array and has | //| sufficient capacity to accommodate the number of elements copied.| //+------------------------------------------------------------------+ template CArrayList::CArrayList(T &array[]): m_default_capacity(4), m_size(0) { m_size=ArrayCopy(m_items,array); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CArrayList class that | //| contains elements copied from the specified collection and has | //| sufficient capacity to accommodate the number of elements copied.| //+------------------------------------------------------------------+ template CArrayList::CArrayList(ICollection*collection): m_default_capacity(4), m_size(0) { //--- check collection if(CheckPointer(collection)!=POINTER_INVALID) m_size=collection.CopyTo(m_items,0); } //+------------------------------------------------------------------+ //| Destructor. | //+------------------------------------------------------------------+ template CArrayList::~CArrayList(void) { } //+------------------------------------------------------------------+ //| Gets the total number of elements the internal data structure can| //| hold without resizing. | //+------------------------------------------------------------------+ template int CArrayList::Capacity(void) { return ArraySize(m_items); } //+------------------------------------------------------------------+ //| Sets the total number of elements the internal data structure can| //| hold without resizing. | //+------------------------------------------------------------------+ template void CArrayList::Capacity(const int capacity) { //--- check new capacity should be greater than current size if(capacity>=m_size && capacity!=ArraySize(m_items)) { if(capacity>0) ArrayResize(m_items,capacity); else ArrayFree(m_items); } } //+------------------------------------------------------------------+ //| Gets the number of elements. | //+------------------------------------------------------------------+ template int CArrayList::Count(void) { return(m_size); } //+------------------------------------------------------------------+ //| Determines whether an element is in the list. | //+------------------------------------------------------------------+ template bool CArrayList::Contains(T item) { //--- try to find item in array for(int i=0; i bool CArrayList::TryGetValue(const int index,T &value) { //--- check index if((uint)index<(uint)m_size) { //--- get value by index value=m_items[index]; return(true); } return(false); } //+------------------------------------------------------------------+ //| Sets the element at the specified index. | //+------------------------------------------------------------------+ template bool CArrayList::TrySetValue(const int index,T value) { //--- check index if((uint)index<(uint)m_size) { //--- set value by index m_items[index]=value; return(true); } return(false); } //+------------------------------------------------------------------+ //| Sets the capacity to the actual number of elements in the list, | //| if that number is less than a threshold value. | //+------------------------------------------------------------------+ template void CArrayList::TrimExcess(void) { //--- calculate threshold value int threshold=(int)(((double)ArraySize(m_items))*0.9); //--- set a сapacity equal to the size if(m_size bool CArrayList::Add(T item) { //--- increse capacity if its necessary if(m_size==ArraySize(m_items)) EnsureCapacity(m_size+1); //--- add value to the end m_items[m_size++]=item; return(true); } //+------------------------------------------------------------------+ //| Adds the elements of the specified array to the end of the list. | //+------------------------------------------------------------------+ template bool CArrayList::AddRange(T &array[]) { //--- increse capacity if its necessary if(m_size==ArraySize(m_items)) EnsureCapacity(m_size+ArraySize(array)); //--- add values to the end m_size+=ArrayCopy(m_items,array,m_size); return(true); } //+------------------------------------------------------------------+ //| Adds the elements of the specified collection to the end of the | //| list. | //+------------------------------------------------------------------+ template bool CArrayList::AddRange(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(false); //--- increse capacity if its necessary if(m_size==ArraySize(m_items)) EnsureCapacity(m_size+collection.Count()); //--- add value to the end m_size+=collection.CopyTo(m_items,m_size); return(true); } //+------------------------------------------------------------------+ //| Inserts an element into the list at the specified index. | //+------------------------------------------------------------------+ template bool CArrayList::Insert(const int index,T item) { //--- check index if((uint)index>(uint)m_size) return(false); //--- increse capacity if its necessary if(m_size==ArraySize(m_items)) EnsureCapacity(m_size+1); //--- shift the values to the right if(index bool CArrayList::InsertRange(const int index,T &array[]) { //--- check index if((uint)index>(uint)m_size) return(false); int size=ArraySize(array); //--- check size of inserted array if(size>0) { //--- increse capacity if its necessary EnsureCapacity(m_size+size); //--- shift the values to the right if(index bool CArrayList::InsertRange(const int index,ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(false); //--- check index if((uint)index>(uint)m_size) return(false); int count=collection.Count(); //--- check count of inserted collection if(count>0) { //--- increse capacity if its necessary EnsureCapacity(m_size+count); //--- shift the values to the right if(index int CArrayList::CopyTo(T &dst_array[],const int dst_start=0) { return ArrayCopy(dst_array,m_items,dst_start,0,m_size); } //+------------------------------------------------------------------+ //| Searches a range of elements in the sorted list for an element | //| using the specified comparer and returns the zero-based index of | //| the element. | //+------------------------------------------------------------------+ template int CArrayList::BinarySearch(const int start_index,const int count,T item,IComparer*comparer) { //--- check index if(start_index<0 || count<0 || m_size-start_indexdef_comparer; //--- use default comparer return ArrayBinarySearch(m_items, start_index, count, item, GetPointer(def_comparer)); } } //+------------------------------------------------------------------+ //| Searches the entire sorted list for an element using the | //| specified comparer and returns the zero-based index of the | //| element. | //+------------------------------------------------------------------+ template int CArrayList::BinarySearch(T item,IComparer*comparer) { return BinarySearch(0, m_size, item, comparer); } //+------------------------------------------------------------------+ //| Searches the entire sorted list for an element using the default | //| comparer and returns the zero-based index of the element. | //+------------------------------------------------------------------+ template int CArrayList::BinarySearch(T item) { return BinarySearch(item, NULL); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based index| //| of the first occurrence within the entire list. | //+------------------------------------------------------------------+ template int CArrayList::IndexOf(T item) { return ArrayIndexOf(m_items, item, 0, m_size); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based index| //| of the first occurrence within the range of elements in the list | //| that extends from the specified index to the last element. | //+------------------------------------------------------------------+ template int CArrayList::IndexOf(T item,const int start_index) { //--- check start index if(start_index>=m_size) return(-1); return ArrayIndexOf(m_items, item, start_index, m_size-start_index); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based index| //| of the first occurrence within the range of elements in the list | //| that starts at the specified index and contains the specified | //| number of elements. | //+------------------------------------------------------------------+ template int CArrayList::IndexOf(T item,const int start_index,const int count) { //--- check start index and count if(start_index<0 || count<0 || start_index>=m_size) return(-1); return ArrayIndexOf(m_items, item, start_index, MathMin(m_size-start_index,count)); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based index| //| of the last occurrence within the entire list. | //+------------------------------------------------------------------+ template int CArrayList::LastIndexOf(T item) { return LastIndexOf(item, m_size - 1, m_size); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based index| //| of the last occurrence within the range of elements in the list | //| that extends from the first element to the specified index. | //+------------------------------------------------------------------+ template int CArrayList::LastIndexOf(T item,const int start_index) { //--- check start index if(start_index>=m_size) return(-1); return ArrayLastIndexOf(m_items, item, start_index, start_index+1); } //+------------------------------------------------------------------+ //| Searches for the specified value and returns the zero-based | //| index of the last occurrence within the range of elements in the | //| list that contains the specified number of elements and ends at | //| the specified index. | //+------------------------------------------------------------------+ template int CArrayList::LastIndexOf(T item,const int start_index,const int count) { //--- check start index and count if(start_index<0 || count<0 || start_index>=m_size) return(-1); return ArrayLastIndexOf(m_items, item, start_index, MathMin(start_index+1,count)); } //+------------------------------------------------------------------+ //| Removes all elements from the list. | //+------------------------------------------------------------------+ template void CArrayList::Clear(void) { //--- check current size if(m_size>0) { ZeroMemory(m_items); m_size=0; } } //+------------------------------------------------------------------+ //| Removes the element at the specified index of the list. | //+------------------------------------------------------------------+ template bool CArrayList::RemoveAt(const int index) { //--- check index if((uint)index>=(uint)m_size) return(false); //--- decrement size m_size--; //--- shift the values to the left if(index bool CArrayList::Remove(T item) { //--- find index of value int index=IndexOf(item); //--- delete element by index if(index>=0) return RemoveAt(index); else return(false); } //+------------------------------------------------------------------+ //| Removes a range of elements from the list. | //+------------------------------------------------------------------+ template bool CArrayList::RemoveRange(const int start_index,const int count) { //--- check start index and count if(start_index<0 || count<0 || m_size-start_index0) { //--- decrement size m_size-=count; //--- shift the values to the left if(start_index bool CArrayList::Reverse(void) { return Reverse(0, m_size); } //+------------------------------------------------------------------+ //| Reverses the order of the elements in the specified range. | //+------------------------------------------------------------------+ template bool CArrayList::Reverse(const int start_index,const int count) { //--- check start index and count if(start_index<0 || count<0 || m_size-start_index bool CArrayList::Sort(void) { return Sort(0,m_size,NULL); } //+------------------------------------------------------------------+ //| Sorts the elements in the entire list using the specified | //| comparer. | //+------------------------------------------------------------------+ template bool CArrayList::Sort(IComparer*comparer) { return Sort(0,m_size,comparer); } //+------------------------------------------------------------------+ //| Sorts the elements in a range of elements in list using the | //| specified comparer. | //+------------------------------------------------------------------+ template bool CArrayList::Sort(const int start_index,const int count,IComparer*comparer) { //--- check start index and count if(start_index<0 || count<0 || m_size-start_indexsorter(); //--- set array to sorter ArrayCopy(sorter.keys,m_items); //--- check comparer if(CheckPointer(comparer)!=POINTER_INVALID) { //--- use specified comparer sorter.comparer=comparer; //--- sort array sorter.Sort(start_index,count); } else { //--- use default comparer CDefaultComparerdef_comparer; sorter.comparer=GetPointer(def_comparer); //--- sort array sorter.Sort(start_index,count); } //--- store the sorted array ArrayCopy(m_items,sorter.keys); return(true); } //+------------------------------------------------------------------+ //| Ensures that the capacity of this list is at least the given | //| minimum value. If the currect capacity of the list is less than | //| min, the capacity is increased to twice the current capacity or | //| to min, whichever is larger. | //+------------------------------------------------------------------+ template void CArrayList::EnsureCapacity(const int min) { int size=ArraySize(m_items); //--- check current size if(sizeINT_MAX) new_capacity=INT_MAX; if(new_capacity