269 lines
15 KiB
MQL5
269 lines
15 KiB
MQL5
#ifndef LIB_MQLPLUS_BASE_OBJ_MAP_TEMPLATES_MQH_INCLUDED
|
|
#define LIB_MQLPLUS_BASE_OBJ_MAP_TEMPLATES_MQH_INCLUDED
|
|
#property version "1.0";
|
|
/**********************************************************************************
|
|
* Copyright (C) 2010-2022 Dominik Egert <info@freie-netze.de>
|
|
*
|
|
* This file is the objects 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.0
|
|
* State: production
|
|
*
|
|
* File information
|
|
* ================
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
#ifdef DBG_MSG_TRACE_FILE_LOADER
|
|
DBG_MSG_TRACE_FILE_LOADER;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Incluse element handler
|
|
#include "lib_base_node_element.mqh"
|
|
|
|
|
|
|
|
/*********************************************************************************************************************************************************/
|
|
/* */
|
|
/* MQLplus data structures */
|
|
/* */
|
|
/*********************************************************************************************************************************************************/
|
|
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// Map key-value object
|
|
//
|
|
|
|
#define MAP_SUBTYPE _tree<USER_KEY, NODE_TYPE>
|
|
#define THIS_MAP _map<USER_DATA, USER_KEY, NODE_TYPE>
|
|
|
|
// Base object
|
|
template <typename USER_DATA, typename USER_KEY, typename NODE_TYPE>
|
|
struct _map : public _tree<USER_KEY, NODE_TYPE>
|
|
{
|
|
public:
|
|
// Element access structure
|
|
|
|
class element : public MAP_SUBTYPE::tree_element<USER_DATA>
|
|
{
|
|
public:
|
|
// Constructors
|
|
element() : tree_element() { };
|
|
element(NODE_TYPE* p_obj, _param_details<NODE_TYPE>* _params) : tree_element((NODE_TYPE*)p_obj, _params) { };
|
|
element(const element& p_in) : tree_element(p_in) { };
|
|
|
|
// Functions
|
|
virtual USER_DATA get() const { if(p_element_obj == NULL) { USER_DATA tmp; ZeroMemory(tmp); return(tmp); } return(p_element_obj.get_obj()); };
|
|
|
|
virtual const bool set(const USER_KEY& p_key) { return(tree_element<USER_DATA>::set(p_key)); };
|
|
virtual const bool set(USER_KEY& p_key) { return(tree_element<USER_DATA>::set(p_key)); };
|
|
virtual const bool set(const USER_KEY& p_key, const USER_DATA& p_data) { if(tree_element<USER_DATA>::set(p_key)) { p_element_obj.operator=(p_data); return(true); } return(false); };
|
|
virtual const bool set(const USER_DATA& p_data) { p_element_obj.operator=(p_data); return(true); };
|
|
|
|
virtual const bool key(const USER_KEY& p_key) { return(_key(p_key)); };
|
|
virtual const bool key(USER_KEY& p_key) { return(_key(p_key)); };
|
|
virtual USER_KEY key() const { return(p_element_obj.get_key()); };
|
|
|
|
// Additional assignment operator
|
|
USER_DATA operator=(USER_DATA& p_in) { p_element_obj.operator=(p_in); return(p_in); };
|
|
|
|
protected:
|
|
const bool _key(const USER_KEY& p_key) {
|
|
bool valid_data = false;
|
|
NODE_TYPE* _old = p_element_obj;
|
|
NODE_TYPE* p_new = new NODE_TYPE(p_key, valid_data);
|
|
if(!valid_data)
|
|
{
|
|
delete(p_new);
|
|
return(false);
|
|
}
|
|
if(tree_element<USER_DATA>::_set(p_new, true))
|
|
{
|
|
set(_old.get_obj());
|
|
delete(_old);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
};
|
|
};
|
|
|
|
|
|
// Iterator
|
|
|
|
class iterator final : public _iterator<USER_KEY, USER_DATA, THIS_MAP, THIS_MAP::element, NODE_TYPE>
|
|
{
|
|
public:
|
|
// Constructors
|
|
iterator() : _iterator() { };
|
|
iterator(THIS_MAP& p_in) : _iterator(p_in) { };
|
|
iterator(THIS_MAP& p_in, USER_DATA& _first, USER_DATA& _last) : _iterator(p_in) { init(p_in, _first, _last); };
|
|
|
|
// Virtual functions
|
|
virtual USER_DATA get() const { return(p_list[p_cnt].p_element_obj.get_obj()); };
|
|
|
|
|
|
virtual const bool set(USER_KEY& p_key, USER_DATA& p_data) { return(p_list[p_cnt].set(p_key, p_data)); };
|
|
virtual const bool key(USER_KEY& p_key) { return(p_list[p_cnt].key(p_key)); };
|
|
virtual USER_KEY key() const { return(p_list[p_cnt].key()); };
|
|
const bool init(THIS_MAP& p_in, USER_KEY& _first, USER_KEY& _last) { _remove_deleted(p_cnt == -1); size = p_in.get_range(p_list, _first, _last); return(_init()); };
|
|
};
|
|
|
|
|
|
protected:
|
|
// Constructors / Destructor
|
|
|
|
// Default constructor
|
|
_map() :
|
|
_tree<USER_KEY, NODE_TYPE>()
|
|
{ };
|
|
|
|
// Copy constructor
|
|
_map(const _map<USER_DATA, USER_KEY, NODE_TYPE>& p_in) :
|
|
_tree<USER_KEY, NODE_TYPE>(p_in)
|
|
{ };
|
|
|
|
|
|
// Assignment operator
|
|
|
|
void operator=(_map<USER_DATA, USER_KEY, NODE_TYPE>& p_in)
|
|
{ _tree<USER_KEY, NODE_TYPE>::operator=(p_in); };
|
|
|
|
|
|
// Comparison operator
|
|
|
|
const bool operator!=(const _map<USER_DATA, USER_KEY, NODE_TYPE>& p_in)
|
|
{ return(!operator==(p_in)); };
|
|
|
|
const bool operator==(const _map<USER_DATA, USER_KEY, NODE_TYPE>& p_in)
|
|
{ return(p_params == p_in.p_params); };
|
|
|
|
|
|
public:
|
|
// Access operator
|
|
|
|
template <typename CUSTOM_KEY>
|
|
element operator[](CUSTOM_KEY p_in)
|
|
{
|
|
NODE_TYPE* p_tmp = p_params.p_root.operator[](p_in);
|
|
if(p_tmp == NULL)
|
|
{
|
|
USER_DATA tmp_data;
|
|
p_tmp = new NODE_TYPE(p_in, tmp_data);
|
|
if(_tree<USER_KEY, NODE_TYPE>::_insert(p_tmp))
|
|
{ return(element(p_tmp, p_params)); }
|
|
delete(p_tmp);
|
|
p_tmp = NULL;
|
|
}
|
|
return(element(p_tmp, p_params));
|
|
};
|
|
|
|
|
|
// Array functions
|
|
|
|
template <typename ARRAY_TYPE>
|
|
const int get_array(ARRAY_TYPE& __p_arr[], const bool reverse = false) { USER_KEY tmp; return(_get_array<ARRAY_TYPE, element>(__p_arr, tmp, tmp, WHOLE_ARRAY, reverse, true)); };
|
|
template <typename ARRAY_TYPE>
|
|
const int get_array(ARRAY_TYPE& __p_arr[], USER_KEY& start, const bool reverse = false) { USER_KEY tmp; return(_get_array<ARRAY_TYPE, element>(__p_arr, start, tmp, WHOLE_ARRAY, reverse, false)); };
|
|
template <typename ARRAY_TYPE>
|
|
const int get_array(ARRAY_TYPE& __p_arr[], USER_KEY& start, const int count, const bool reverse = false) { USER_KEY tmp; return(_get_array<ARRAY_TYPE, element>(__p_arr, start, tmp, count, reverse, false)); };
|
|
template <typename ARRAY_TYPE>
|
|
const int get_range(ARRAY_TYPE& __p_arr[], USER_KEY& start, USER_KEY& end) { return(_get_array<ARRAY_TYPE, element>(__p_arr, start, end, 0, false, true)); };
|
|
|
|
|
|
protected:
|
|
// Element functions
|
|
|
|
// Insert element
|
|
const int insert(USER_KEY& p_key[], USER_DATA& p_in[], const bool ignore_duplicates = true)
|
|
{
|
|
const int count = ArraySize(p_key);
|
|
const int data_count = ArraySize(p_in);
|
|
int ptr = count / 2;
|
|
int insert_cnt = NULL;
|
|
bool __stop = false;
|
|
for(int cnt = NULL; (cnt < count) && !__stop; cnt++, ptr++)
|
|
{
|
|
__stop |= _StopFlag || (!insert(p_key[ptr % count], p_in[ptr % count]) && !ignore_duplicates);
|
|
insert_cnt += !__stop;
|
|
}
|
|
return(insert_cnt);
|
|
};
|
|
|
|
const bool insert(USER_KEY& p_key, USER_DATA& p_in)
|
|
{
|
|
// Create new tree node
|
|
NODE_TYPE* p_new = new NODE_TYPE(p_key, p_in);
|
|
|
|
// Insert and return
|
|
if(_tree<USER_KEY, NODE_TYPE>::_insert(p_new))
|
|
{ return(true); }
|
|
|
|
// Insert failed
|
|
delete(p_new);
|
|
|
|
// Return failure
|
|
return(false);
|
|
};
|
|
|
|
// Remove element
|
|
const int remove(USER_KEY& p_key[], USER_DATA& p_out[], const bool _do_not_destroy = false)
|
|
{
|
|
// Local init
|
|
const int count = ArraySize(p_key);
|
|
int remove_cnt = NULL;
|
|
bool __stop = false;
|
|
|
|
// Allocate output array
|
|
if(ArrayResize(p_out, count) != count)
|
|
{ return(NULL); }
|
|
|
|
for(int cnt = NULL; (cnt < count) && !__stop; cnt++)
|
|
{
|
|
__stop |= _StopFlag || !remove(p_key[cnt], p_out[cnt]);
|
|
remove_cnt += !__stop;
|
|
}
|
|
|
|
// Return
|
|
return(remove_cnt);
|
|
};
|
|
|
|
const bool remove(USER_KEY& p_key, USER_DATA& p_out, const bool _do_not_destroy = false)
|
|
{
|
|
// Precheck list
|
|
if( (p_params.p_root == NULL)
|
|
|| ((p_params.p_left != NULL) && (p_params.p_left > p_key))
|
|
|| ((p_params.p_right != NULL) && (p_params.p_right < p_key)) )
|
|
{ return(false); }
|
|
|
|
// Get and access object, then return
|
|
NODE_TYPE* p_tmp = p_params.p_root.operator[](p_key);
|
|
p_out = p_tmp.get_obj();
|
|
|
|
// Return
|
|
return(MAP_SUBTYPE::_remove(p_tmp, _do_not_destroy));
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
// Remove local definitions
|
|
|
|
#undef THIS_MAP
|
|
|
|
|
|
|
|
//
|
|
// END MQL data structures */
|
|
//*********************************************************************************************************************************************************/
|
|
#endif // LIB_MQLPLUS_BASE_OBJ_MAP_TEMPLATES_MQH_INCLUDED
|