307 lines
10 KiB
MQL5
307 lines
10 KiB
MQL5
|
#ifndef LIB_MQLPLUS_BASE_BUFFERS_TEMPLATES_MQH_INCLUDED
|
||
|
#define LIB_MQLPLUS_BASE_BUFFERS_TEMPLATES_MQH_INCLUDED
|
||
|
#property version "1.2";
|
||
|
/**********************************************************************************
|
||
|
* Copyright (C) 2010-2022 Dominik Egert <info@freie-netze.de>
|
||
|
*
|
||
|
* This file is the buffers include file.
|
||
|
*
|
||
|
* MQLplus, including this file may not be copied and/or distributed
|
||
|
* without explecit permit by the author.
|
||
|
* Author Dominik Egert / Freie Netze UG.
|
||
|
**********************************************************************************
|
||
|
*
|
||
|
* Version: 1.2
|
||
|
* State: production
|
||
|
*
|
||
|
* File information
|
||
|
* ================
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
#ifdef DBG_MSG_TRACE_FILE_LOADER
|
||
|
DBG_MSG_TRACE_FILE_LOADER;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////
|
||
|
//
|
||
|
// Include mt5api Array
|
||
|
//
|
||
|
//#include <MQLplus/lib_mqlplus/mt5api/lib_mt5api_Array_tpl.mqh>
|
||
|
|
||
|
#ifndef LIB_MQLPLUS
|
||
|
#define mqp_ArrayResize ArrayResize
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
/* */
|
||
|
/* MQLplus data structures */
|
||
|
/* */
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// First In Last Out Buffer
|
||
|
//
|
||
|
|
||
|
// Base class object
|
||
|
template <typename T>
|
||
|
class _buffer_filo
|
||
|
{
|
||
|
protected:
|
||
|
|
||
|
// Internal state
|
||
|
int _size;
|
||
|
int _ptr;
|
||
|
|
||
|
// Buffer
|
||
|
T buffer[];
|
||
|
T _empty;
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
// Constructor / Destructor
|
||
|
|
||
|
// Default constructor
|
||
|
_buffer_filo() :
|
||
|
_size(NULL),
|
||
|
_ptr(-1)
|
||
|
{ mqp_ArrayResize(buffer, NULL); };
|
||
|
|
||
|
|
||
|
// Buffer functions
|
||
|
|
||
|
// Reset
|
||
|
void reset()
|
||
|
{
|
||
|
::ArrayFree(buffer);
|
||
|
_size = NULL;
|
||
|
_ptr = -1;
|
||
|
};
|
||
|
|
||
|
// Size
|
||
|
int size() const
|
||
|
{ return(_ptr + 1); };
|
||
|
|
||
|
|
||
|
// Pop functions
|
||
|
|
||
|
// Pop last element
|
||
|
T pop()
|
||
|
{ return((_ptr < NULL) ? _empty : buffer[_ptr--]); };
|
||
|
|
||
|
// Pop by decrement
|
||
|
T operator--(int)
|
||
|
{ return(pop()); };
|
||
|
|
||
|
// Pop by subtraction
|
||
|
void operator-=(const int p_in)
|
||
|
{
|
||
|
int cnt = p_in;
|
||
|
while( (cnt > NULL)
|
||
|
&& (_ptr > -1) )
|
||
|
{ pop(); cnt--; }
|
||
|
};
|
||
|
|
||
|
|
||
|
// Assignment operator
|
||
|
|
||
|
void operator=(const _buffer_filo& p_in)
|
||
|
{
|
||
|
_size = p_in.size();
|
||
|
_ptr = mqp_ArrayResize(buffer, _size) - 1;
|
||
|
for(int cnt = NULL; (cnt < _size) && !_StopFlag; cnt++)
|
||
|
{ buffer[cnt] = p_in[cnt]; }
|
||
|
};
|
||
|
|
||
|
|
||
|
// Access operator
|
||
|
|
||
|
T operator[](const int idx) const
|
||
|
{
|
||
|
const int _idx = (idx < NULL) ? (_ptr + idx) + 1 : idx;
|
||
|
return((_ptr == -1) || (_idx < NULL) ? _empty : buffer[_idx]);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// First In First Out Buffer
|
||
|
//
|
||
|
|
||
|
template <typename T>
|
||
|
struct buffer_fifo
|
||
|
{
|
||
|
protected:
|
||
|
|
||
|
// Internal state
|
||
|
uint pop_buffer;
|
||
|
uint pop_ptr;
|
||
|
bool push_buffer;
|
||
|
uint push_ptr;
|
||
|
uint buffer_1_end;
|
||
|
uint buffer_1_size;
|
||
|
uint buffer_2_end;
|
||
|
uint buffer_2_size;
|
||
|
uint element_cnt;
|
||
|
T _empty;
|
||
|
|
||
|
// Buffer
|
||
|
T buffer_1[];
|
||
|
T buffer_2[];
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
// Constructor
|
||
|
|
||
|
buffer_fifo() :
|
||
|
pop_buffer (0x01),
|
||
|
pop_ptr (NULL),
|
||
|
|
||
|
push_buffer (false),
|
||
|
push_ptr (NULL),
|
||
|
|
||
|
buffer_1_end (NULL),
|
||
|
buffer_1_size (NULL),
|
||
|
|
||
|
buffer_2_end (NULL),
|
||
|
buffer_2_size (NULL),
|
||
|
|
||
|
element_cnt (NULL)
|
||
|
{
|
||
|
::ZeroMemory(_empty);
|
||
|
mqp_ArrayResize(buffer_1, NULL);
|
||
|
mqp_ArrayResize(buffer_1, NULL);
|
||
|
};
|
||
|
|
||
|
|
||
|
// Reset
|
||
|
|
||
|
void reset()
|
||
|
{
|
||
|
mqp_ArrayResize(buffer_1, NULL, (4096 / sizeof(T)));
|
||
|
mqp_ArrayResize(buffer_2, NULL, (4096 / sizeof(T)));
|
||
|
pop_buffer = 0x01;
|
||
|
pop_ptr = NULL;
|
||
|
push_buffer = false;
|
||
|
push_ptr = NULL;
|
||
|
buffer_1_end = NULL;
|
||
|
buffer_1_size = NULL;
|
||
|
buffer_2_end = NULL;
|
||
|
buffer_2_size = NULL;
|
||
|
element_cnt = NULL;
|
||
|
};
|
||
|
|
||
|
|
||
|
// Size
|
||
|
|
||
|
int size() const
|
||
|
{ return((int)(element_cnt - (element_cnt > NULL))); };
|
||
|
|
||
|
|
||
|
// Push new element
|
||
|
|
||
|
void push(const T &p_in)
|
||
|
{
|
||
|
const bool buffer_change = ((!(pop_buffer == 0x01) == push_buffer) && (pop_ptr > NULL));
|
||
|
push_buffer = (buffer_change) ? !push_buffer : push_buffer;
|
||
|
push_ptr = (buffer_change) ? NULL : push_ptr;
|
||
|
|
||
|
element_cnt += 1 + (element_cnt == NULL);
|
||
|
if(push_buffer)
|
||
|
{
|
||
|
buffer_2_size = (buffer_2_size > push_ptr) ? buffer_2_size : mqp_ArrayResize(buffer_2, buffer_2_size + 1);
|
||
|
buffer_2[push_ptr++] = p_in;
|
||
|
buffer_2_end = push_ptr;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
buffer_1_size = (buffer_1_size > push_ptr) ? buffer_1_size : mqp_ArrayResize(buffer_1, buffer_1_size + 1);
|
||
|
buffer_1[push_ptr++] = p_in;
|
||
|
buffer_1_end = push_ptr;
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
|
||
|
// Pop oldest element
|
||
|
|
||
|
T pop()
|
||
|
{
|
||
|
// Switch buffer
|
||
|
switch(pop_buffer * (element_cnt != NULL))
|
||
|
{
|
||
|
case 0x00:
|
||
|
return(_empty);
|
||
|
|
||
|
case 0x01:
|
||
|
pop_buffer = (pop_ptr == buffer_1_end) ? 0x02 : 0x01;
|
||
|
pop_ptr = (pop_ptr == buffer_1_end) ? NULL : pop_ptr;
|
||
|
break;
|
||
|
|
||
|
case 0x02:
|
||
|
pop_buffer = (pop_ptr == buffer_2_end) ? 0x01 : 0x02;
|
||
|
pop_ptr = (pop_ptr == buffer_2_end) ? NULL : pop_ptr;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Element counter
|
||
|
element_cnt -= (1 + (element_cnt == 2));
|
||
|
|
||
|
// Return
|
||
|
switch(pop_buffer)
|
||
|
{
|
||
|
case 0x01:
|
||
|
return(buffer_1[pop_ptr++]);
|
||
|
|
||
|
case 0x02:
|
||
|
return(buffer_2[pop_ptr++]);
|
||
|
}
|
||
|
|
||
|
// Return
|
||
|
return(_empty);
|
||
|
};
|
||
|
|
||
|
|
||
|
// Access operator
|
||
|
|
||
|
T operator[](const int _idx) const
|
||
|
{
|
||
|
const uint idx = (_idx < NULL) ? element_cnt - _idx : _idx;
|
||
|
uint cnt_buffer = NULL;
|
||
|
switch(pop_buffer * ((element_cnt != NULL) && ((element_cnt - 1) > idx)))
|
||
|
{
|
||
|
case 0x01:
|
||
|
cnt_buffer = buffer_1_end - pop_ptr;
|
||
|
return((idx < cnt_buffer) ? buffer_1[pop_ptr + idx] : buffer_2[idx - cnt_buffer]);
|
||
|
|
||
|
case 0x02:
|
||
|
cnt_buffer = buffer_2_end - pop_ptr;
|
||
|
return((idx < cnt_buffer) ? buffer_2[pop_ptr + idx] : buffer_1[idx - cnt_buffer]);
|
||
|
}
|
||
|
|
||
|
return(_empty);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// END MQL data structures */
|
||
|
//*********************************************************************************************************************************************************/
|
||
|
#endif // LIB_MQLPLUS_BASE_BUFFERS_TEMPLATES_MQH_INCLUDED
|