MQLplus/lib_structures/base/lib_base_map.mqh
super.admin 466f9ca5c5 convert
2025-05-30 16:09:52 +02:00

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