#ifndef LIB_MQLPLUS_STRUCTURE_LIFETIME_MQH_INCLUDED #define LIB_MQLPLUS_STRUCTURE_LIFETIME_MQH_INCLUDED #property version "1.2"; /********************************************************************************** * Copyright (C) 2010-2022 Dominik Egert * * This file is the smart 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.2 * State: production * * File information * ================ * * * */ #ifdef DBG_MSG_TRACE_FILE_LOADER DBG_MSG_TRACE_FILE_LOADER; #endif /*********************************************************************************************************************************************************/ /* */ /* MQLplus auto destructing handlers */ /* */ /*********************************************************************************************************************************************************/ ///////////////////////////////////////////////////// // // Main handle and pointer structure // // Primary abstract template class template class _smart_object { protected: // Close message string _identifyer; string _close_msg; // Object handle T obj; public: // Constructors _smart_object() : obj(NULL), _close_msg(NULL), _identifyer(NULL) { }; _smart_object(_smart_object& p_in) : obj(operator=(p_in)), _close_msg(NULL), _identifyer(NULL) { }; _smart_object(const T p_in) : obj(p_in), _close_msg(NULL), _identifyer(NULL) { }; // Assignment operator const T operator=(const T p_in) { if(is_valid() && (obj != p_in)) { obj_free(); _identifyer = NULL; _close_msg = NULL; } obj = p_in; return(obj); } const T operator=(_smart_object& p_in) { return(obj_assign(p_in)); } // Compare handle const bool operator==(const _smart_object& p_in) const { return(obj == p_in.obj); } const bool operator!=(const _smart_object& p_in) const { return(obj != p_in.obj); } const bool operator==(const T p_in) const { return(obj == p_in); } const bool operator!=(const T p_in) const { return(obj != p_in); } // Set closing message void set_close_message(const string p_in) { _close_msg = p_in; } // Check handle virtual bool is_valid() = 0; // Get handle const T get() { return(obj); } // Get/Set identifyer const string get_identifyer() { return(_identifyer); } void set_identifyer(const string p_in) { _identifyer = p_in; } protected: // Assign smart object const T obj_assign(_smart_object& p_in) { if(is_valid() && (obj != p_in.obj)) { obj_free(); } _identifyer = p_in._identifyer; _close_msg = p_in._close_msg; obj = p_in.obj_extract(); return(obj); } // Release handle virtual void obj_free() = 0; // Extract handle virtual T obj_extract() = 0; }; // General 32 bit integer handle class __smo_handle : public _smart_object { public: // Constructor __smo_handle() : _smart_object(INVALID_HANDLE) { }; __smo_handle(const int p_in): _smart_object(p_in) { }; // Destructor ~__smo_handle() { if(is_valid()) { obj_free(); } }; // Check handle virtual bool is_valid() { return(obj != INVALID_HANDLE); }; protected: // Release handle virtual void obj_free() = 0; virtual int obj_extract() = 0; }; // Object pointer instance class template class smart_ptr : public _smart_object { public: // Constructor smart_ptr() : _smart_object(NULL) { }; smart_ptr(const T& p_in) : _smart_object(::GetPointer(p_in)) { }; // Destructor ~smart_ptr() { if(is_valid()) { obj_free(); } }; // Assignment operator T* operator=(smart_ptr& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } return(::StringLen(_identifyer) > 0) _identifyer : typename(*obj)); }; // Check handle virtual bool is_valid() { return((obj != NULL) && ::CheckPointer(obj) != POINTER_INVALID)); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Deleting object by pointer: %s; Object name: %s", _close_msg, typename(obj)); } delete(obj); obj = NULL; }; virtual T obj_extract() { const T tmp = obj; obj = NULL; return(tmp); }; }; // General string type object identifyer handle class str_handle : public _smart_object { public: // Constructor str_handle() : _smart_object(NULL) { }; str_handle(const string p_in) : _smart_object(p_in) { }; // Destructor ~str_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const string operator=(str_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } return((::StringLen(_identifyer) > 0) ? _identifyer : obj); }; // Check handle virtual bool is_valid() { return((obj != NULL) && (obj != "")); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("%s; String handle: %s", _close_msg, obj); } obj = NULL; }; }; // Resource handler class resource_handle : public str_handle { public: // Constructor resource_handle() : str_handle(NULL) { }; resource_handle(const string p_in) : str_handle(p_in) { }; // Destructor ~resource_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const string operator=(resource_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } return((::StringLen(_identifyer) > 0) ? _identifyer : obj); }; // Check handle virtual bool is_valid() { return((obj != NULL) && (obj != "")); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing Resource handle: %s; Resource name: %s", _close_msg, obj); } ::ResetLastError(); ::ResourceFree(obj); obj = NULL; if(_LastError != ERR_SUCCESS) { printf("Error closing resource: %i", _LastError); } }; }; ///////////////////////////////////////////////////// // // Specific handle implementations // // File handle class file_handle : public __smo_handle { public: // Destructor ~file_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(file_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } if(::StringLen(_identifyer) > 0) { return(_identifyer); } if(::FileGetInteger(obj, FILE_EXISTS) != 1) { return(NULL); } return(::TerminalInfoString((::FileGetInteger(obj, FILE_IS_COMMON)) ? TERMINAL_COMMONDATA_PATH : TERMINAL_DATA_PATH)); }; const int get_type() { if(!is_valid()) { return(-1); } return( (::FileGetInteger(obj, FILE_IS_COMMON) ? FILE_COMMON : NULL) | (::FileGetInteger(obj, FILE_IS_TEXT) ? FILE_TXT : NULL) | (::FileGetInteger(obj, FILE_IS_BINARY) ? FILE_BIN : NULL) | (::FileGetInteger(obj, FILE_IS_CSV) ? FILE_CSV : NULL) | (::FileGetInteger(obj, FILE_IS_ANSI) ? FILE_ANSI : FILE_UNICODE) | (::FileGetInteger(obj, FILE_IS_READABLE) ? FILE_READ : NULL) | (::FileGetInteger(obj, FILE_IS_WRITABLE) ? FILE_WRITE : NULL) ); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing File handle: %s; File location: %s", _close_msg, ::TerminalInfoString((::FileGetInteger(obj, FILE_IS_COMMON)) ? TERMINAL_COMMONDATA_PATH : TERMINAL_DATA_PATH)); } ::ResetLastError(); ::FileClose(obj); obj = INVALID_HANDLE; if(_LastError != ERR_SUCCESS) { printf("Error closing file: %i", _LastError); } if(_StopFlag) { Sleep(10); } }; virtual int obj_extract() { const int tmp = obj; obj = INVALID_HANDLE; return(tmp); }; }; #ifndef __MQL4_COMPATIBILITY_CODE__ // Indicator handle class indicator_handle : public __smo_handle { public: // Destructor ~indicator_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(indicator_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } if(::StringLen(_identifyer) > 0) { return(_identifyer); } string short_name = __find_indicator_short_name(::ChartID(), obj); long chart_id = ::ChartFirst(); while( (short_name == NULL) && (chart_id != -1) ) { short_name = __find_indicator_short_name(chart_id, obj); chart_id = ::ChartNext(chart_id); } if(short_name != NULL) {return(short_name); } ENUM_INDICATOR ind_type; MqlParam params[]; if(::IndicatorParameters(obj, ind_type, params) == -1) { ind_type = -1; } return(::EnumToString(ind_type)); }; const ENUM_INDICATOR get_type() { if(!is_valid()) { return(-1); } ENUM_INDICATOR ind_type; MqlParam params[]; if(::IndicatorParameters(obj, ind_type, params) == -1) { return(-1); } return(ind_type); } protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { ENUM_INDICATOR ind_type; MqlParam params[]; const int param_cnt = (!_StopFlag) ? ::IndicatorParameters(obj, ind_type, params) : NULL; string params_out = NULL; for(int cnt = NULL; (cnt < param_cnt) && !_StopFlag; cnt++) { switch(params[cnt].type) { case TYPE_BOOL: params_out += " " + ::StringFormat("%s\n", (params[cnt].integer_value) ? "True" : "False"); break; case TYPE_CHAR: case TYPE_SHORT: case TYPE_INT: case TYPE_LONG: params_out += " " + ::StringFormat("%lli\n", params[cnt].integer_value); break; case TYPE_UCHAR: case TYPE_USHORT: case TYPE_UINT: case TYPE_ULONG: params_out += " " + ::StringFormat("%llu\n", (ulong)params[cnt].integer_value); break; case TYPE_COLOR: params_out += " " + ::ColorToString((color)params[cnt].integer_value, true); break; case TYPE_DATETIME: params_out += " " + ::TimeToString((datetime)params[cnt].integer_value, TIME_DATE|TIME_MINUTES); break; case TYPE_FLOAT: case TYPE_DOUBLE: params_out += " " + ::StringFormat("%.*f", 12, params[cnt].double_value); break; case TYPE_STRING: params_out += " " + ::StringFormat("%s\n", params[cnt].string_value); break; } } printf("Closing Indicator handle: %s; Indicator type: %s\n%s", _close_msg, ::EnumToString(ind_type), params_out); } ::ResetLastError(); ::IndicatorRelease(obj); obj = INVALID_HANDLE; if(_LastError != ERR_SUCCESS) { printf("Error closing indicator: %i", _LastError); } if(_StopFlag) { ::Sleep(25); } }; virtual int obj_extract() { const int tmp = obj; obj = INVALID_HANDLE; return(tmp); }; private: // Find indicator on charts const string __find_indicator_short_name(const long chart_id, const int h_ind) { for(int wnd = (int)::ChartGetInteger(chart_id, CHART_WINDOWS_TOTAL) - 1; (wnd >= NULL); wnd--) { for(int ind = (int)::ChartIndicatorsTotal(chart_id, wnd) - 1; (ind >= NULL); ind--) { const string ind_name = ::ChartIndicatorName(chart_id, wnd, ind); if(::ChartIndicatorGet(chart_id, wnd, ind_name) == h_ind) { return(ind_name); } } } return(NULL); }; }; // Open CL handle #ifndef __MQL4_COMPATIBILITY_CODE__ class opencl_handle : public __smo_handle { public: // Constructor opencl_handle() : __smo_handle(OPENCL_INVALID) { }; // Destructor ~opencl_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(opencl_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } return((::StringLen(_identifyer) > 0) ? _identifyer : ::EnumToString(::CLHandleType(obj))); }; const ENUM_OPENCL_HANDLE_TYPE get_type() { if(!is_valid()) { return(OPENCL_INVALID); } return(::CLHandleType(obj)); }; // Check handle virtual bool is_valid() { return(obj != OPENCL_INVALID); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing OpenCL handle: %s; OpenCL handle type: %s", _close_msg, ::EnumToString(::CLHandleType(obj))); } ::ResetLastError(); switch(::CLHandleType(obj)) { case OPENCL_CONTEXT: ::CLContextFree(obj); obj = OPENCL_INVALID; break; case OPENCL_PROGRAM: ::CLProgramFree(obj); obj = OPENCL_INVALID; break; case OPENCL_KERNEL: ::CLKernelFree(obj); obj = OPENCL_INVALID; break; case OPENCL_BUFFER: ::CLBufferFree(obj); obj = OPENCL_INVALID; break; } if(_LastError != ERR_SUCCESS) { printf("Error closing ocl-handle: %i", _LastError); } if(_StopFlag) { ::Sleep(25); } }; virtual int obj_extract() { const int tmp = obj; obj = OPENCL_INVALID; return(tmp); }; }; // DirectX handle class dx_handle : public __smo_handle { public: // Constructor dx_handle() : __smo_handle(DX_HANDLE_INVALID) { }; // Destructor ~dx_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(dx_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } return((::StringLen(_identifyer) > 0) ? _identifyer : ::EnumToString(DXHandleType(obj))); }; const ENUM_DX_HANDLE_TYPE get_type() { if(!is_valid()) { return(-1); } return(::DXHandleType(obj)); }; // Check handle virtual bool is_valid() { return(obj != DX_HANDLE_INVALID); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing DirectX handle: %s; DirectX handle type: %s", _close_msg, ::EnumToString(::DXHandleType(obj))); } ::ResetLastError(); ::DXRelease(obj); obj = DX_HANDLE_INVALID; if(_LastError != ERR_SUCCESS) { printf("Error closing dx-handle: %i", _LastError); } if(_StopFlag) { Sleep(25); } }; virtual int obj_extract() { const int tmp = obj; obj = DX_HANDLE_INVALID; return(tmp); }; }; // Database handle class db_handle : public __smo_handle { public: // Destructor ~db_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(db_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid()) { return(NULL); } if(::StringLen(_identifyer) > 0) { return(_identifyer); } const int h_request = ::DatabasePrepare(obj, "SELECT file FROM pragma_database_list WHERE name = 'main';"); string file = NULL; bool err = !::DatabaseRead(h_request); err |= (!err) && !::DatabaseColumnText(h_request, 0, file); ::DatabaseFinalize(h_request); return((err) ? NULL : ((file == "") ? ":memory:" : file)); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing Database handle: %s", _close_msg); } ::ResetLastError(); ::DatabaseClose(obj); obj = INVALID_HANDLE; if(_LastError != ERR_SUCCESS) { printf("Error closing database: %i", _LastError); } if(_StopFlag) { Sleep(100); } }; virtual int obj_extract() { const int tmp = obj; obj = INVALID_HANDLE; return(tmp); }; }; // Socket handle class socket_handle : public __smo_handle { public: // Destructor ~socket_handle() { if(is_valid()) { obj_free(); } }; // Assignment operator const int operator=(socket_handle& p_in) { return(obj_assign(p_in)); }; // Handle Identifyer const string get_identifyer() { if(!is_valid() || !::SocketIsConnected(obj)) { return(NULL); } if(::StringLen(_identifyer) > 0) { return(_identifyer); } if(!::SocketIsConnected(obj)) { return(NULL); } ::ResetLastError(); string subject = NULL, issuer = NULL, serial = NULL, thumbprint = NULL; datetime expiration = NULL; bool err = !::SocketTlsCertificate(obj, subject, issuer, serial, thumbprint, expiration); if(_LastError == ERR_NETSOCKET_NO_CERTIFICATE) { ::ResetLastError(); return(""); } if(err) { return(NULL); } return(subject + ";" + issuer + ";" + ::TimeToString(expiration)); }; protected: // Release handle virtual void obj_free() { if(!is_valid()) { return; } if(_close_msg != NULL) { printf("Closing Socket handle: %s", _close_msg); } ::ResetLastError(); ::SocketClose(obj); obj = INVALID_HANDLE; if(_LastError != ERR_SUCCESS) { printf("Error closing socket: %i", _LastError); } if(_StopFlag) { ::Sleep(25); } }; virtual int obj_extract() { const int tmp = obj; obj = INVALID_HANDLE; return(tmp); }; }; #endif // // END MQL data structures */ //*********************************************************************************************************************************************************/ #endif // LIB_MQLPLUS_STRUCTURE_UNIONS_MQH_INCLUDED