364 lines
11 KiB
MQL5
364 lines
11 KiB
MQL5
|
#ifndef LIB_MQLPLUS_BUFFERS_TEMPLATES_MQH_INCLUDED
|
||
|
#define LIB_MQLPLUS_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 base buffers
|
||
|
#include "lib_base_buffers.mqh"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
/* */
|
||
|
/* MQLplus data structures */
|
||
|
/* */
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// Bitflag Buffer
|
||
|
//
|
||
|
|
||
|
struct buffer_bitflags pack(8)
|
||
|
{
|
||
|
private:
|
||
|
// Local storage
|
||
|
|
||
|
int _arr_size;
|
||
|
ulong bit_flags[];
|
||
|
|
||
|
|
||
|
public:
|
||
|
// Constructor
|
||
|
|
||
|
buffer_bitflags() :
|
||
|
_arr_size (NULL)
|
||
|
{ };
|
||
|
|
||
|
buffer_bitflags(const buffer_bitflags& p_in)
|
||
|
{ operator=(p_in); }
|
||
|
|
||
|
|
||
|
// Assignment operator
|
||
|
|
||
|
void operator=(const buffer_bitflags& p_in)
|
||
|
{
|
||
|
_arr_size = p_in._arr_size;
|
||
|
::ArrayCopy(bit_flags, p_in.bit_flags);
|
||
|
}
|
||
|
|
||
|
void operator=(const int p_in)
|
||
|
{
|
||
|
const int _p_in = p_in * ((p_in < NULL) ? -1 : 1);
|
||
|
const int ptr = _resize(_p_in);
|
||
|
const ulong flag = 1 << (_p_in % 64);
|
||
|
bit_flags[ptr] |= flag;
|
||
|
bit_flags[ptr] &= (p_in < NULL) ? ~flag : bit_flags[ptr];
|
||
|
}
|
||
|
|
||
|
|
||
|
// Access operator
|
||
|
|
||
|
bool operator[](const int p_in)
|
||
|
{ return((bit_flags[_resize(p_in)] & (1 << (p_in % 64))) != NULL); }
|
||
|
|
||
|
|
||
|
// Comparison operators
|
||
|
|
||
|
const bool operator==(const int p_in)
|
||
|
{ return((bit_flags[_resize(p_in)] & (1 << (p_in % 64))) == ((p_in < NULL) ? NULL : (1 << (p_in % 64)))); }
|
||
|
|
||
|
const bool operator!=(const int p_in)
|
||
|
{ return((bit_flags[_resize(p_in)] & (1 << (p_in % 64))) != ((p_in < NULL) ? NULL : (1 << (p_in % 64)))); }
|
||
|
|
||
|
|
||
|
private:
|
||
|
// Auto-Resize function
|
||
|
|
||
|
int _resize(const int p_in)
|
||
|
{
|
||
|
const int ptr = p_in / 64;
|
||
|
_arr_size = (_arr_size <= ptr) ? ::ArrayResize(bit_flags, ptr + 1) : _arr_size;
|
||
|
return(ptr);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// First In Last Out Buffer
|
||
|
//
|
||
|
|
||
|
// Derived simple type class object
|
||
|
template <typename T>
|
||
|
class buffer_filo : public _buffer_filo<T>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
// Constructor / Destructor
|
||
|
|
||
|
// Default constructor
|
||
|
buffer_filo() :
|
||
|
_buffer_filo()
|
||
|
{ };
|
||
|
|
||
|
// Destructor
|
||
|
~buffer_filo()
|
||
|
{ _buffer_filo<T>::reset(); };
|
||
|
|
||
|
|
||
|
// Push functions
|
||
|
|
||
|
// Push new element
|
||
|
bool push(const T& p_in)
|
||
|
{
|
||
|
_ptr = (_ptr == _size - 1) ? ::ArrayResize(buffer, _size + 1) - 1 : (_ptr + 1);
|
||
|
_size += (_ptr == _size);
|
||
|
buffer[_ptr] = p_in;
|
||
|
return(_ptr > -1);
|
||
|
};
|
||
|
|
||
|
|
||
|
// Assignment operator
|
||
|
|
||
|
bool operator+=(const T& p_in)
|
||
|
{ return(push(p_in)); };
|
||
|
};
|
||
|
|
||
|
|
||
|
// Derived complex type class object for pointers
|
||
|
template <typename T>
|
||
|
class ptr_buffer_filo : public _buffer_filo<T*>
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
// Local storage
|
||
|
|
||
|
bool do_not_destroy;
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
// Constructor / Destructor
|
||
|
|
||
|
// Default constructor
|
||
|
ptr_buffer_filo() :
|
||
|
_buffer_filo(),
|
||
|
do_not_destroy(false)
|
||
|
{ _empty = new T; };
|
||
|
|
||
|
// Specific constructor
|
||
|
ptr_buffer_filo(const bool _do_not_destroy) :
|
||
|
_buffer_filo(),
|
||
|
do_not_destroy(_do_not_destroy)
|
||
|
{ _empty = new T; };
|
||
|
|
||
|
// Destructor
|
||
|
~ptr_buffer_filo()
|
||
|
{
|
||
|
reset();
|
||
|
delete(_empty);
|
||
|
};
|
||
|
|
||
|
|
||
|
// Buffer functions
|
||
|
|
||
|
// Do not destroy
|
||
|
bool dnd(const bool _do_not_destroy = true)
|
||
|
{
|
||
|
do_not_destroy |= _do_not_destroy;
|
||
|
return(do_not_destroy);
|
||
|
};
|
||
|
|
||
|
// Reset
|
||
|
void reset()
|
||
|
{
|
||
|
int cnt = _ptr;
|
||
|
if(!do_not_destroy)
|
||
|
{
|
||
|
while(cnt > -1)
|
||
|
{
|
||
|
if(::CheckPointer(buffer[cnt]) == POINTER_DYNAMIC)
|
||
|
{ delete(buffer[cnt]); }
|
||
|
cnt--;
|
||
|
}
|
||
|
}
|
||
|
_buffer_filo<T*>::reset();
|
||
|
};
|
||
|
|
||
|
|
||
|
// Push functions
|
||
|
|
||
|
// Create and push new element
|
||
|
bool push(const T& _p_in)
|
||
|
{
|
||
|
T* p_in = new T;
|
||
|
*p_in = _p_in;
|
||
|
_ptr = (_ptr == _size - 1) ? ::ArrayResize(buffer, _size + 1) - 1 : (_ptr + 1);
|
||
|
_size += (_ptr == _size);
|
||
|
buffer[_ptr] = p_in;
|
||
|
return(_ptr > -1);
|
||
|
};
|
||
|
|
||
|
// Push new element
|
||
|
bool push(T* p_in)
|
||
|
{
|
||
|
_ptr = (_ptr == _size - 1) ? ::ArrayResize(buffer, _size + 1) - 1 : (_ptr + 1);
|
||
|
_size += (_ptr == _size);
|
||
|
buffer[_ptr] = p_in;
|
||
|
return(_ptr > -1);
|
||
|
};
|
||
|
|
||
|
|
||
|
// Pop functions
|
||
|
|
||
|
// Pop pointer to 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) )
|
||
|
{ delete(pop()); cnt--; }
|
||
|
};
|
||
|
|
||
|
|
||
|
// Assignment operators
|
||
|
|
||
|
bool operator+=(const T& p_in)
|
||
|
{ return(push(p_in)); };
|
||
|
|
||
|
bool operator+=(T* p_in)
|
||
|
{ return(push(p_in)); };
|
||
|
|
||
|
|
||
|
// 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
|
||
|
//
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// Circle Buffer
|
||
|
//
|
||
|
|
||
|
template <typename T>
|
||
|
struct buffer_circle : public buffer_fifo<T>
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
// Internal state
|
||
|
uint _max_size;
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
// Default constructor
|
||
|
buffer_circle() :
|
||
|
buffer_fifo(),
|
||
|
_max_size (NULL)
|
||
|
{ };
|
||
|
|
||
|
// Defined constructor
|
||
|
buffer_circle(const uint size) :
|
||
|
buffer_fifo()
|
||
|
{ _max_size = size; };
|
||
|
|
||
|
|
||
|
// Overwritte size function
|
||
|
int size(const int max_size = -1)
|
||
|
{
|
||
|
switch(max_size)
|
||
|
{
|
||
|
case -1:
|
||
|
return(buffer_fifo<T>::size());
|
||
|
case 0x00:
|
||
|
_max_size = NULL;
|
||
|
buffer_fifo<T>::reset();
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
while(buffer_fifo<T>::size() > max_size)
|
||
|
{ pop(); }
|
||
|
|
||
|
_max_size = max_size;
|
||
|
return(buffer_fifo<T>::size());
|
||
|
}
|
||
|
|
||
|
|
||
|
// Overwritten push function
|
||
|
void push(const T p_in)
|
||
|
{
|
||
|
if(buffer_fifo<T>::size() >= (int)_max_size)
|
||
|
{ pop(); }
|
||
|
buffer_fifo<T>::push(p_in);
|
||
|
}
|
||
|
|
||
|
// Overwritten push function
|
||
|
void push(const T &p_in)
|
||
|
{
|
||
|
if(buffer_fifo<T>::size() >= (int)_max_size)
|
||
|
{ pop(); }
|
||
|
buffer_fifo<T>::push(p_in);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// END MQL data structures */
|
||
|
//*********************************************************************************************************************************************************/
|
||
|
#endif // LIB_MQLPLUS_BUFFERS_TEMPLATES_MQH_INCLUDED
|