#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 * * 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 #define THIS_MAP _map // Base object template struct _map : public _tree { public: // Element access structure class element : public MAP_SUBTYPE::tree_element { public: // Constructors element() : tree_element() { }; element(NODE_TYPE* p_obj, _param_details* _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::set(p_key)); }; virtual const bool set(USER_KEY& p_key) { return(tree_element::set(p_key)); }; virtual const bool set(const USER_KEY& p_key, const USER_DATA& p_data) { if(tree_element::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::_set(p_new, true)) { set(_old.get_obj()); delete(_old); return(true); } return(false); }; }; // Iterator class iterator final : public _iterator { 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() { }; // Copy constructor _map(const _map& p_in) : _tree(p_in) { }; // Assignment operator void operator=(_map& p_in) { _tree::operator=(p_in); }; // Comparison operator const bool operator!=(const _map& p_in) { return(!operator==(p_in)); }; const bool operator==(const _map& p_in) { return(p_params == p_in.p_params); }; public: // Access operator template 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::_insert(p_tmp)) { return(element(p_tmp, p_params)); } delete(p_tmp); p_tmp = NULL; } return(element(p_tmp, p_params)); }; // Array functions template const int get_array(ARRAY_TYPE& __p_arr[], const bool reverse = false) { USER_KEY tmp; return(_get_array(__p_arr, tmp, tmp, WHOLE_ARRAY, reverse, true)); }; template const int get_array(ARRAY_TYPE& __p_arr[], USER_KEY& start, const bool reverse = false) { USER_KEY tmp; return(_get_array(__p_arr, start, tmp, WHOLE_ARRAY, reverse, false)); }; template const int get_array(ARRAY_TYPE& __p_arr[], USER_KEY& start, const int count, const bool reverse = false) { USER_KEY tmp; return(_get_array(__p_arr, start, tmp, count, reverse, false)); }; template const int get_range(ARRAY_TYPE& __p_arr[], USER_KEY& start, USER_KEY& end) { return(_get_array(__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::_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