CArrayObj

//+------------------------------------------------------------------+

//|                                                     ArrayObj.mqh |

//|                        Copyright 2010, MetaQuotes Software Corp. |

//|                                        http://www.metaquotes.net |

//|                                              Revision 2010.02.22 |

//+------------------------------------------------------------------+

#include "Array.mqh"

//+------------------------------------------------------------------+

//| Class CArrayObj.                                                 |

//| Appointment: Class of dynamic array type pointers to instances   |

//|              of CObject and his heirs.                           |

//|              Derives from class CArray.                          |

//+------------------------------------------------------------------+

class CArrayObj : public CArray

  {

protected:

   CObject          *m_data[];           // data array

   bool              m_free_mode;        // flag of the need to "physical" object deletion

public:

                     CArrayObj();

                    ~CArrayObj();

   //--- methods of access to protected data

   bool              FreeMode() const    { return(m_free_mode); }

   void              FreeMode(bool mode) { m_free_mode=mode;    }

   //--- method of identifying the object

   virtual int       Type() const        { return(0x7778);      }

   //--- methods for working with files

   virtual bool      Save(int file_handle);

   virtual bool      Load(int file_handle);

   //--- method of creating an array element

   virtual bool      CreateElement(int index) { return(false);  }

   //--- methods of managing dynamic memory

   bool              Reserve(int size);

   bool              Resize(int size);

   bool              Shutdown();

   //--- methods of filling an array

   bool              Add(CObject *element);

   bool              AddArray(const CArrayObj *src);

   bool              Insert(CObject *element,int pos);

   bool              InsertArray(const CArrayObj *src,int pos);

   bool              AssignArray(const CArrayObj *src);

   //--- method of access to an array

   CObject          *At(int index) const;

   //--- methods change

   bool              Update(int index,CObject *element);

   bool              Shift(int index,int shift);

   //--- methods deleting

   CObject          *Detach(int index);

   bool              Delete(int index);

   bool              DeleteRange(int from,int to);

   void              Clear();

   //--- method to compare 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,int mode);

   int               QuickSearch(const CObject *element) const;

   int               MemMove(int dest,int src,int count);

  };

//+------------------------------------------------------------------+

//| Constructor CArrayObj.                                           |

//| INPUT:  no.                                                      |

//| OUTPUT: no.                                                      |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

void CArrayObj::CArrayObj()

  {

//--- initialize protected data

   m_data_max=ArraySize(m_data);

   m_free_mode=true;

  }

//+------------------------------------------------------------------+

//| Destructor CArrayObj.                                            |

//| INPUT:  no.                                                      |

//| OUTPUT: no.                                                      |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

void CArrayObj::~CArrayObj()

  {

   if(m_data_max!=0) Shutdown();

  }

//+------------------------------------------------------------------+

//| Moving the memory within a single array.                         |

//| INPUT:  dest  -index-receiver,                                   |

//|         src   -index-source,                                     |

//|         count -number of elements to move.                       |

//| OUTPUT: dest if OK, -1 if failure.                               |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::MemMove(int dest,int src,int count)

  {

   int i;

//--- checking

   if(dest<0 || src<0 || count<0) return(-1);

   if(dest+count>m_data_total)

     {

      if(Available()<dest+count) return(-1);

      else                       m_data_total=dest+count;

     }

//--- copy does not need

   if(dest==src || count==0) return(dest);

//--- copy

   if(dest<src)

     {

      //--- copy left to right

      for(i=0;i<count;i++)

        {

         //--- "physical" removal of the object (if necessary and possible)

         if(m_free_mode && m_data[dest+i]!=NULL) delete m_data[dest+i];

         //---

         m_data[dest+i]=m_data[src+i];

         m_data[src+i]=NULL;

        }

     }

   else

     {

      //--- copy right to left

      for(i=count-1;i>=0;i--)

        {

         //--- "physical" removal of the object (if necessary and possible)

         if(m_free_mode && m_data[dest+i]!=NULL) delete m_data[dest+i];

         //---

         m_data[dest+i]=m_data[src+i];

         m_data[src+i]=NULL;

        }

     }

//---

   return(dest);

  }

//+------------------------------------------------------------------+

//| Request for more memory in an array. Check if the requested      |

//| number of free elements, and the need for reallocating with      |

//| a given step.                                                    |

//| INPUT:  size -requested number of free elements.                 |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Reserve(int size)

  {

   int new_size;

//--- checking

   if(size<=0) return(false);

//--- resizing array

   if(Available()<size)

     {

      new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);

      if(new_size<0)

        {

         //--- overflow occurred when calculating new_size

         return(false);

        }

      m_data_max=ArrayResize(m_data,new_size);

      //--- clearly zero out all the loose items in an array

      for(int i=m_data_total;i<m_data_max;i++) m_data[i]=NULL;

     }

//---

   return(Available()>=size);

  }

//+------------------------------------------------------------------+

//| Resizing (with removal of elements on the right).                |

//| INPUT:  size -new array size.                                    |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Resize(int size)

  {

   int new_size;

//--- checking

   if(size<0) return(false);

//--- resizing array

   new_size=m_step_resize*(1+(size-Available())/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;i++)

           {

            if(m_data[i]!=NULL)

              {

               delete m_data[i];

               m_data[i]=NULL;

              }

           }

        }

      m_data_total=size;

     }

   if(m_data_max!=new_size) m_data_max=ArrayResize(m_data,new_size);

//---

   return(m_data_max==new_size);

  }

//+------------------------------------------------------------------+

//| Complete cleaning of the array with the release of memory.       |

//| INPUT:  no.                                                      |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Shutdown()

  {

//--- checking

   if(m_data_max==0) return(true);

//--- cleaning

   Clear();

   if(ArrayResize(m_data,0)==-1) return(false);

   m_data_max=0;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Adding an element to the end of the array.                       |

//| INPUT:  element -variable to add.                                |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Add(CObject *element)

  {

//--- checking

   if(!CheckPointer(element)) return(false);

//--- checking/reserve elements of array

   if(!Reserve(1)) return(false);

//--- adding

   m_data[m_data_total++]=element;

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Adding an elements to the end of the array.                      |

//| INPUT:  src -pointer to an instance of class CArrayObj.          |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::AddArray(const CArrayObj *src)

  {

   int num;

//--- checking

   if(!CheckPointer(src)) return(false);

//--- checking/reserve elements of array

   num=src.Total();

   if(!Reserve(num)) return(false);

//--- adding

   for(int i=0;i<num;i++) m_data[m_data_total++]=src.m_data[i];

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Inserting an element in the specified position.                  |

//| INPUT:  element -variable to insert,                             |

//|         pos     -position to insert.                             |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Insert(CObject *element,int pos)

  {

//--- checking

   if(pos<0 || !CheckPointer(element)) return(false);

//--- checking/reserve elements of array

   if(!Reserve(1)) return(false);

//--- inserting

   m_data_total++;

   if(pos<m_data_total-1)

     {

      MemMove(pos+1,pos,m_data_total-pos-1);

      m_data[pos]=element;

     }

   else

      m_data[m_data_total-1]=element;

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Inserting elements in the specified position.                    |

//| INPUT:  src -pointer to an instance of class CArrayObj,          |

//|         pos -position to insert.                                 |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::InsertArray(const CArrayObj *src,int pos)

  {

   int num;

//--- checking

   if(!CheckPointer(src)) return(false);

//--- checking/reserve elements of array

   num=src.Total();

   if(!Reserve(num)) return(false);

//--- inserting

   MemMove(num+pos,pos,m_data_total-pos);

   for(int i=0;i<num;i++) m_data[i+pos]=src.m_data[i];

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Assignment (copy) of another array.                              |

//| INPUT:  src -pointer to an instance of class CArrayObj.          |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::AssignArray(const CArrayObj *src)

  {

   int num;

//--- checking

   if(!CheckPointer(src)) return(false);

//--- checking/reserve elements of array

   num=src.m_data_total;

   Clear();

   if(m_data_max<num)

     {

      if(!Reserve(num)) return(false);

     }

   else   Resize(num);

//--- copying array

   for(int i=0;i<num;i++)

     {

      m_data[i]=src.m_data[i];

      m_data_total++;

     }

   m_sort_mode=src.SortMode();

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Access to data in the specified position.                        |

//| INPUT:  index -position of element.                              |

//| OUTPUT: element in position or NULL.                             |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

CObject *CArrayObj::At(int index) const

  {

//--- checking

   if(index<0 || index>=m_data_total) return(NULL);

//---

   return(m_data[index]);

  }

//+------------------------------------------------------------------+

//| Updating an item in the position.                                |

//| INPUT:  index   -position of element,                            |

//|         element -new value element.                              |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Update(int index,CObject *element)

  {

//--- checking

   if(index<0 || !CheckPointer(element) || index>=m_data_total) return(false);

//--- "physical" removal of the object (if necessary and possible)

   if(m_free_mode && m_data[index]!=NULL)

      delete m_data[index];

//--- update

   m_data[index]=element;

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Moving item from the specified position in the specified offset. |

//| INPUT:  index -position of element,                              |

//|         shift -relative displacement for new position            |

//|                shift>0-to right,shift<0-to left.                 |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Shift(int index,int shift)

  {

   CObject *tmp_node;

//--- checking

   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) MemMove(index,index+1,shift);

   else        MemMove(index+shift+1,index+shift,-shift);

   m_data[index+shift]=tmp_node;

   m_sort_mode=-1;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Delete an item from the specified position.                      |

//| INPUT:  index -position of element.                              |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: does not violate the sorting.                            |

//+------------------------------------------------------------------+

bool CArrayObj::Delete(int index)

  {

//--- checking

   if(index>=m_data_total) return(false);

//--- delete

   if(index<0 || index<m_data_total-1) MemMove(index,index+1,m_data_total-index-1);

   m_data_total--;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Detach item from the specified position.                         |

//| INPUT:  index -position of element.                              |

//| OUTPUT: pointer (handle) of detached element.                    |

//| REMARK: does not violate the sorting.                            |

//+------------------------------------------------------------------+

CObject *CArrayObj::Detach(int index)

  {

   CObject *result;

//--- checking

   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(index<m_data_total-1) MemMove(index,index+1,m_data_total-index-1);

   m_data_total--;

//---

   return(result);

  }

//+------------------------------------------------------------------+

//| Delete range of elements.                                        |

//| INPUT:  from -begining position of the range,                    |

//|         to   -ending position of the range.                      |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: does not violate the sorting.                            |

//+------------------------------------------------------------------+

bool CArrayObj::DeleteRange(int from,int to)

  {

//--- checking

   if(from<0 || to<0)                return(false);

   if(from>to || from>=m_data_total) return(false);

//--- delete

   if(to>=m_data_total-1) to=m_data_total-1;

   else                   MemMove(from,to,m_data_total-to-1);

   m_data_total-=to-from;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Clear of the array without the release of memory.                |

//| INPUT:  no.                                                      |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

void CArrayObj::Clear()

  {

//--- "physical" removal of the object (if necessary and possible)

   if(m_free_mode)

     {

      for(int i=0;i<m_data_total;i++)

        {

         if(m_data[i]!=NULL)

           {

            delete m_data[i];

            m_data[i]=NULL;

           }

        }

     }

   m_data_total=0;

  }

//+------------------------------------------------------------------+

//| Comparison of two arrays for equality.                           |

//| INPUT:  Array -pointer to an instance of class CArrayObj         |

//|         for comparison.                                          |

//| OUTPUT: true if equality, false if not.                          |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::CompareArray(const CArrayObj *Array) const

  {

//--- checking

   if(!CheckPointer(Array)) return(false);

//--- comparison

   if(m_data_total!=Array.m_data_total) return(false);

   for(int i=0;i<m_data_total;i++)

      if(m_data[i].Compare(Array.m_data[i],0)!=0) return(false);

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Method QuickSort.                                                |

//| INPUT:  beg -start sorting area,                                 |

//|         end -end sorting area,                                   |

//|         mode-sorting mode.                                       |

//| OUTPUT: no.                                                      |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

void CArrayObj::QuickSort(int beg,int end,int mode)

  {

   int      i,j;

   CObject *p_node;

   CObject *t_node;

//--- sort

   i=beg;

   j=end;

   while(i<end)

     {

      //--- ">>1" is quick division by 2

      p_node=m_data[(beg+end)>>1];

      while(i<j)

        {

         while(m_data[i].Compare(p_node,mode)<0)

           {

            //--- control the output of the array bounds

            if(i==m_data_total-1) break;

            i++;

           }

         while(m_data[j].Compare(p_node,mode)>0)

           {

            //--- 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;

            else     j--;

           }

        }

      if(beg<j) QuickSort(beg,j,mode);

      beg=i;

      i=beg;

      j=end;

     }

  }

//+------------------------------------------------------------------+

//| Inserting an element in a sorted array.                          |

//| INPUT:  element -element value.                                  |

//| OUTPUT: true if OK, false if failure.                            |

//| REMARK: does not violate the sorting.                            |

//+------------------------------------------------------------------+

bool CArrayObj::InsertSort(CObject *element)

  {

   int pos;

//--- checking

   if(!CheckPointer(element) || m_sort_mode==-1) return(false);

//--- checking/reserve elements of array

   if(!Reserve(1)) return(false);

//--- if the array is empty, add an element

   if(m_data_total==0)

     {

      m_data[m_data_total++]=element;

      return(true);

     }

//--- search position and insert

   int mode=m_sort_mode;

   pos=QuickSearch(element);

   if(m_data[pos].Compare(element,m_sort_mode)>0) Insert(element,pos);

   else                                           Insert(element,pos+1);

//--- restore the sorting flag after Insert(...)

   m_sort_mode=mode;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Quick search the element's position in the sorted array.         |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array.              |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

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;

     }

//---

   return(m);

  }

//+------------------------------------------------------------------+

//| Search the element's position in the sorted array.               |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::Search(const CObject *element) const

  {

   int pos;

//--- checking

   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);

//---

   return(-1);

  }

//+------------------------------------------------------------------+

//| Search position of the first element greater than specified      |

//| in the sorted array.                                             |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchGreat(const CObject *element) const

  {

   int pos;

//--- checking

   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);

//---

   return(pos);

  }

//+------------------------------------------------------------------+

//| Search position of the first element less than specified         |

//| in the sorted array.                                             |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchLess(const CObject *element) const

  {

   int pos;

//--- checking

   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);

//---

   return(pos);

  }

//+------------------------------------------------------------------+

//| Search position of the first element greater or equal            |

//| than specified in the sorted array.                              |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchGreatOrEqual(const CObject *element) const

  {

   int pos;

//--- checking

   if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1);

//--- search

   if((pos=SearchGreat(element))!=-1)

     {

      if(pos!=0 && m_data[pos-1].Compare(element,m_sort_mode)==0) return(pos-1);

      else                                                        return(pos);

     }

//---

   return(-1);

  }

//+------------------------------------------------------------------+

//| Search position of the first element less or equal               |

//| than specified in the sorted array.                              |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchLessOrEqual(const CObject *element) const

  {

   int pos;

//--- checking

   if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1);

//--- search

   if((pos=SearchLess(element))!=-1)

     {

      if(pos!=m_data_total-1 && m_data[pos+1].Compare(element,m_sort_mode)==0) return(pos+1);

      else                                                                     return(pos);

     }

//---

   return(-1);

  }

//+------------------------------------------------------------------+

//| Find position of first occurrence of element in the sorted array.|

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchFirst(const CObject *element) const

  {

   int pos;

//--- checking

   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);

     }

//---

   return(-1);

  }

//+------------------------------------------------------------------+

//| Find position of last occurrence of element in the sorted array. |

//| INPUT:  element -search value.                                   |

//| OUTPUT: position of the found element in the array or -1.        |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

int CArrayObj::SearchLast(const CObject *element) const

  {

   int pos;

//--- checking

   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);

     }

//---

   return(-1);

  }

//+------------------------------------------------------------------+

//| Writing array to file.                                           |

//| INPUT:  file_handle -handle previously opened for writing file.  |

//| OUTPUT: true if OK, else false.                                  |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Save(int file_handle)

  {

   int i=0;

//--- checking

   if(!CArray::Save(file_handle)) return(false);

//--- writing

//--- writing array length

   if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) return(false);

//--- writing array

   for(i=0;i<m_data_total;i++)

      if(m_data[i].Save(file_handle)!=true) break;

//---

   return(i==m_data_total);

  }

//+------------------------------------------------------------------+

//| Reading array from file.                                         |

//| INPUT:  file_handle -handle previously opened for reading file.  |

//| OUTPUT: true if OK, else false.                                  |

//| REMARK: no.                                                      |

//+------------------------------------------------------------------+

bool CArrayObj::Load(int file_handle)

  {

   int i=0,num;

//--- checking

   if(!CArray::Load(file_handle)) return(false);

//--- reading

//--- reading array length

   num=FileReadInteger(file_handle,INT_VALUE);

//--- reading array

   Clear();

   if(num!=0)

     {

      if(Reserve(num))

        {

         for(i=0;i<num;i++)

           {

            //--- create new element

            if(!CreateElement(i)) break;

            if(m_data[i].Load(file_handle)!=true) break;

            m_data_total++;

           }

        }

     }

   m_sort_mode=-1;

//---

   return(m_data_total==num);

  }

//+------------------------------------------------------------------+