Files
2025-02-07 19:15:50 +03:30

166 lines
13 KiB
Plaintext

//+------------------------------------------------------------------+
//| RingBuffer.mqh |
//| Copyright 2016, Vasiliy Sokolov. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link "http://www.mql5.com"
//+------------------------------------------------------------------+
//| Double ring buffer |
//+------------------------------------------------------------------+
class CRiBuffInt
{
private:
bool m_full_buff;
int m_max_total;
int m_head_index;
int m_buffer[];
protected:
virtual void OnAddValue(int value);
virtual void OnRemoveValue(int value);
virtual void OnChangeValue(int index, int prev_value, int new_value);
virtual void OnChangeArray(void);
virtual void OnSetMaxTotal(int max_total);
int ToRealInd(int index);
public:
CRiBuffInt(void);
void AddValue(int value);
void ChangeValue(int index, int new_value);
int GetValue(int index);
int GetTotal(void);
int GetMaxTotal(void);
void SetMaxTotal(int max_total);
void ToArray(int& array[]);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CRiBuffInt::CRiBuffInt(void) : m_full_buff(false),
m_head_index(-1),
m_max_total(0)
{
SetMaxTotal(3);
}
//+------------------------------------------------------------------+
//| Called when a new value is received |
//+------------------------------------------------------------------+
void CRiBuffInt::OnAddValue(int value)
{
}
//+------------------------------------------------------------------+
//| Called when an old value is removed |
//+------------------------------------------------------------------+
void CRiBuffInt::OnRemoveValue(int value)
{
}
//+------------------------------------------------------------------+
//| Called when an old value is changed |
//+------------------------------------------------------------------+
void CRiBuffInt::OnChangeValue(int index,int prev_value,int new_value)
{
}
//+------------------------------------------------------------------+
//| Called when changing the number of elements in the buffer |
//+------------------------------------------------------------------+
void CRiBuffInt::OnSetMaxTotal(int max_total)
{
}
//+------------------------------------------------------------------+
//| Called if the entire array should be counted |
//+------------------------------------------------------------------+
void CRiBuffInt::OnChangeArray(void)
{
}
//+------------------------------------------------------------------+
//| Set the new size of the ring buffer |
//+------------------------------------------------------------------+
void CRiBuffInt::SetMaxTotal(int max_total)
{
if(ArraySize(m_buffer) == max_total)
return;
m_max_total = ArrayResize(m_buffer, max_total);
OnSetMaxTotal(m_max_total);
}
//+------------------------------------------------------------------+
//| Get the actual ring buffer size |
//+------------------------------------------------------------------+
int CRiBuffInt::GetMaxTotal(void)
{
return m_max_total;
}
//+------------------------------------------------------------------+
//| Get the index value |
//+------------------------------------------------------------------+
int CRiBuffInt::GetValue(int index)
{
return m_buffer[ToRealInd(index)];
}
//+------------------------------------------------------------------+
//| Get the total number of elements |
//+------------------------------------------------------------------+
int CRiBuffInt::GetTotal(void)
{
if(m_full_buff)
return m_max_total;
return m_head_index+1;
}
//+------------------------------------------------------------------+
//| Add a new value to the ring buffer |
//+------------------------------------------------------------------+
void CRiBuffInt::AddValue(int value)
{
if(++m_head_index == m_max_total)
{
m_head_index = 0;
m_full_buff = true;
}
int last_value = 0.0;
if(m_full_buff)
last_value = m_buffer[m_head_index];
m_buffer[m_head_index] = value;
OnAddValue(value);
if(m_full_buff)
OnRemoveValue(last_value);
OnChangeArray();
}
//+------------------------------------------------------------------+
//| Replace the previously added value with the new one |
//+------------------------------------------------------------------+
void CRiBuffInt::ChangeValue(int index, int value)
{
int r_index = ToRealInd(index);
int prev_value = m_buffer[r_index];
m_buffer[r_index] = value;
OnChangeValue(index, prev_value, value);
OnChangeArray();
}
//+------------------------------------------------------------------+
//| Convert the virtual index into a real one |
//+------------------------------------------------------------------+
int CRiBuffInt::ToRealInd(int index)
{
if(index >= GetTotal() || index < 0)
return m_max_total;
if(!m_full_buff)
return index;
int delta = (m_max_total-1) - m_head_index;
if(index < delta)
return m_max_total + (index - delta);
return index - delta;
}
//+------------------------------------------------------------------+
//| Get the array of values |
//+------------------------------------------------------------------+
void CRiBuffInt::ToArray(int &array[])
{
ArrayResize(array, GetTotal());
int start = ToRealInd(0);
if(start > m_head_index)
{
int lt = m_max_total-start;
ArrayCopy(array, m_buffer, 0, start, lt);
ArrayCopy(array, m_buffer, lt, 0, m_head_index+1);
}
else
ArrayCopy(array, m_buffer, 0, 0, m_head_index);
}