MQLplus/lib_structures/lib_smart_object.mqh

537 lines
39 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:09:52 +02:00
#ifndef LIB_MQLPLUS_STRUCTURE_LIFETIME_MQH_INCLUDED
#define LIB_MQLPLUS_STRUCTURE_LIFETIME_MQH_INCLUDED
#property version "1.2";
/**********************************************************************************
* Copyright (C) 2010-2022 Dominik Egert <info@freie-netze.de>
*
* 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 <typename T>
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<int>
{
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 <typename T>
class smart_ptr : public _smart_object<T*>
{
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<string>
{
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