#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 * * 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 #ifndef LIB_MQLPLUS #define mqp_ArrayResize ArrayResize #endif /*********************************************************************************************************************************************************/ /* */ /* MQLplus data structures */ /* */ /*********************************************************************************************************************************************************/ /////////////////////////////////////// // // First In Last Out Buffer // // Base class object template 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 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