MQLplus/lib_debug/lib_debug_mqlapi_tracer.mqh

334 lines
16 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:09:52 +02:00
#ifndef LIB_DBG_DEBUG_MQLAPI_TRACER_MQH_INCLUDED
#define LIB_DBG_DEBUG_MQLAPI_TRACER_MQH_INCLUDED
#property version "5.10"
/**********************************************************************************
* Copyright (C) 2020 Dominik Egert <info@freie-netze.de>
*
* This file is the MQL-API base tracer object include file.
*
* Lisence applied: GPLv2
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Author Dominik Egert / Freie Netze UG.
**********************************************************************************
*
* Version: 5.10
* State: public
*
* File information
* ================
*
*/
//*********************************************************************************************************************************************************/
// BEGIN MQLAPI tracer
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MQL API general function scheme
//
//
// This function wrapping scheme is used for all mql-api-functions.
//
// In basic there are three types of function wrapping methods to be used.
// - Functions of VOID-Type
// - Functions of RETURN-Type
// - Variable input parameter functions
//
// Representation of the original function signature as documented was most important, to prevent differences
// by the wrapper and the original function. - In case of doubt, the more reliable option was chosen.
//
//
// Example function wrapper for RETURN-Type:
//
// Original function signature from documentation:
//
// int WebRequest(
// const string method, // HTTP method
// const string url, // URL
// const string headers, // headers
// int timeout, // timeout
// const char &data[], // the array of the HTTP message body
// char &result[], // an array containing server response data
// string &result_headers // headers of server response
// );
//
// Wrapper replacement:
//
// int dbg_mqlapi_trace_func_WebRequest(const string method, const string url, const string headers, int timeout, const char& data[], char& result[], string& result_headers)
// {
// // Trace call setup
// DBG_MQLAPI_TRACE_FUNCTION_CALL_SETUP;
//
// // All input variables are stringified to "_params_in"-member variable.
// DBG_MQLAPI_TRACE_FUNC_PARAMS_STR(7, method, url, headers, timeout, data, result, result_headers);
//
// // The actual wrapped MQL api function call
// int retval = WebRequest(method, url, headers, timeout, data, result, result_headers);
//
// // In case output is provided by parameter references, output-print is avialable in "_params_out" member variable.
// DBG_MQLAPI_TRACE_FUNC_PARAM_RESULTS_STR(2, result, result_headers, NULL, NULL, NULL, NULL, NULL);
//
// // Output return value given by mql function
// DBG_MQLAPI_TRACE_PRINT_RETURN(retval);
//
// // Finalize call tracing
// DBG_MQLAPI_TRACE_FUNCTION_CALL_FINALIZE;
// return(retval);
// };
//
//
// Example function wrapper for VOID-Type:
//
// Original function signature form documentation:
//
// void ArrayPrint(
// const void& array[], // printed array
// uint digits=_Digits, // number of decimal places
// const string separator=NULL, // separator of the structure field values
// ulong start=0, // first printed element index
// ulong count=WHOLE_ARRAY, // number of printed elements
// ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN
// );
//
// Wrapper replacement:
//
// template <typename T>
// void dbg_mqlapi_trace_ArrayPrint(const T& arr[], uint digits = UINT_MAX, const string separator = NULL, ulong start = 0, ulong count = WHOLE_ARRAY, ulong flags = ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN)
// {
// // Trace call setup
// DBG_MQLAPI_TRACE_FUNCTION_CALL_SETUP;
//
// // Additional setup to ensure function compatibility to the original signature.
// int _digits = (digits == UINT_MAX) ? _Digits : digits;
//
// // All input variables are stringified to "_params_in"-member variable.
// DBG_MQLAPI_TRACE_FUNC_PARAMS_STR(6, arr, _digits, separator, start, count, flags);
//
// // The actual wrapped MQL api function call
// ArrayPrint(arr, _digits, separator, start, count, flags);
//
// // Output void type function
// DBG_MQLAPI_TRACE_PRINT;
//
// // FInalize call tracing
// DBG_MQLAPI_TRACE_FUNCTION_CALL_FINALIZE;
// return;
// };
//
//
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MQL API tracer special function definitions
//
// MQL API Function IDs for variable inputs
#define DBG_MQL_API_TRACING_FUNCTION_ID_ALERT -1
#define DBG_MQL_API_TRACING_FUNCTION_ID_COMMENT -2
#define DBG_MQL_API_TRACING_FUNCTION_ID_PRINT -3
#define DBG_MQL_API_TRACING_FUNCTION_ID_PRINTF -4
#define DBG_MQL_API_TRACING_FUNCTION_ID_PRINTFORMAT -5
#define DBG_MQL_API_TRACING_FUNCTION_ID_STRINGFORMAT -6
#define DBG_MQL_API_TRACING_FUNCTION_ID_PRINTFORMAT_ERROR -126
// Rerouting (c/c++) standard functions to MQL-version Math*
#define DBG_MQL_API_TRACING_FUNCTION_ID_ACOS -7
#define DBG_MQL_API_TRACING_FUNCTION_ID_ASIN -8
#define DBG_MQL_API_TRACING_FUNCTION_ID_ATAN -9
#define DBG_MQL_API_TRACING_FUNCTION_ID_CEIL -10
#define DBG_MQL_API_TRACING_FUNCTION_ID_COS -11
#define DBG_MQL_API_TRACING_FUNCTION_ID_EXP -12
#define DBG_MQL_API_TRACING_FUNCTION_ID_FABS -13
#define DBG_MQL_API_TRACING_FUNCTION_ID_FLOOR -14
#define DBG_MQL_API_TRACING_FUNCTION_ID_FMAX -15
#define DBG_MQL_API_TRACING_FUNCTION_ID_FMIN -16
#define DBG_MQL_API_TRACING_FUNCTION_ID_FMOD -17
#define DBG_MQL_API_TRACING_FUNCTION_ID_LOG -18
#define DBG_MQL_API_TRACING_FUNCTION_ID_LOG10 -19
#define DBG_MQL_API_TRACING_FUNCTION_ID_POW -20
#define DBG_MQL_API_TRACING_FUNCTION_ID_RAND -21
#define DBG_MQL_API_TRACING_FUNCTION_ID_ROUND -22
#define DBG_MQL_API_TRACING_FUNCTION_ID_SIN -23
#define DBG_MQL_API_TRACING_FUNCTION_ID_SQRT -24
#define DBG_MQL_API_TRACING_FUNCTION_ID_SRAND -25
#define DBG_MQL_API_TRACING_FUNCTION_ID_TAN -26
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MT4/5 API function call meta object
//
#ifdef __MQL5__
namespace dbg_lib
{
#endif
#ifndef LIB_MQLAPI_TRACE_CUSTOM_EXTENSION
class LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)
{
protected:
// Local storage
ulong _perf_runtime_;
int _prev_err_state;
int _line;
char _rtol_op;
bool _print_params_;
bool _print_result_;
string _api_name_;
string _file;
string _function;
string _mqlapi_funcname;
string _params_in;
string _params_out;
string _return_type;
public:
// Constructor
LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)() :
_perf_runtime_ (0),
_prev_err_state (0),
_line (0),
_rtol_op (0),
_print_params_ (false),
_print_result_ (false),
_api_name_ (NULL),
_file (NULL),
_function (NULL),
_mqlapi_funcname (NULL),
_params_in (NULL),
_params_out (NULL),
_return_type (NULL)
#else
class LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object) : public LIB_DBG_NAMESPACE_DEF(dbg_lib, userapi_call_tracer_custom_object)
{
public:
// Constructor
LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)()
#endif
{
::printf(" >>> LIB_DEBUG: MQLAPI-Tracer enabled <<< \n - Note: initially clearing _LastError variable now.\n");
::ResetLastError();
};
LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)(const LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)& p_in)
{
_rtol_op = p_in._rtol_op;
_prev_err_state = p_in._prev_err_state;
_line = p_in._line;
_print_params_ = p_in._print_params_;
_print_result_ = p_in._print_result_;
_perf_runtime_ = p_in._perf_runtime_;
_api_name_ = p_in._api_name_;
_file = p_in._file;
_function = p_in._function;
_params_in = p_in._params_in;
_params_out = p_in._params_out;
_return_type = p_in._return_type;
};
// Debug location recorder
LIB_DBG_NAMESPACE_DEF(dbg_lib, mqlapi_call_tracer_object)* trace_call_details(const int _line_in, const char _func_id, const string _file_in, const string _function_in, const string _mqlapi_func, const string _api_name = NULL)
{
// Prestate setup
_params_out = NULL;
_params_in = NULL;
_api_name_ = (_api_name_ == NULL) ? _api_name : _api_name_;
_print_params_ = LIB_MQLAPI_TRACE_SHOW_PARAMS;
_print_result_ = LIB_MQLAPI_TRACE_SHOW_RESULT;
_perf_runtime_ = NULL;
_prev_err_state = _LastError;
// Trace setup details
_line = _line_in;
_rtol_op = _func_id;
_file = _file_in;
_function = _function_in;
_mqlapi_funcname = _mqlapi_func;
// Overwrite function name, if applicable
switch(_rtol_op)
{
case DBG_MQL_API_TRACING_FUNCTION_ID_ALERT: _mqlapi_funcname = "Alert"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_COMMENT: _mqlapi_funcname = "Comment"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_PRINT: _mqlapi_funcname = "Print"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_PRINTF: _mqlapi_funcname = "printf"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_PRINTFORMAT_ERROR:
case DBG_MQL_API_TRACING_FUNCTION_ID_PRINTFORMAT: _mqlapi_funcname = "PrintFormat"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_STRINGFORMAT: _mqlapi_funcname = "StringFormat"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_ACOS: _mqlapi_funcname = "acos"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_ASIN: _mqlapi_funcname = "asin"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_ATAN: _mqlapi_funcname = "atan"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_CEIL: _mqlapi_funcname = "ceil"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_COS: _mqlapi_funcname = "cos"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_EXP: _mqlapi_funcname = "exp"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_FABS: _mqlapi_funcname = "fabs"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_FLOOR: _mqlapi_funcname = "floor"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_FMAX: _mqlapi_funcname = "fmax"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_FMIN: _mqlapi_funcname = "fmin"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_FMOD: _mqlapi_funcname = "fmod"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_LOG: _mqlapi_funcname = "log"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_LOG10: _mqlapi_funcname = "log10"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_POW: _mqlapi_funcname = "pow"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_RAND: _mqlapi_funcname = "rand"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_ROUND: _mqlapi_funcname = "round"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_SIN: _mqlapi_funcname = "sin"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_SQRT: _mqlapi_funcname = "sqrt"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_SRAND: _mqlapi_funcname = "srand"; break;
case DBG_MQL_API_TRACING_FUNCTION_ID_TAN: _mqlapi_funcname = "tan"; break;
default:
{
string tmp[];
const int cnt = StringSplit(_mqlapi_func, 0x005F, tmp);
_mqlapi_funcname = (cnt > 0) ? tmp[cnt - 1] : _mqlapi_funcname;
}
}
// Clear error code
::ResetLastError();
// Return
return(::GetPointer(this));
};
};
#ifdef __MQL5__
};
#endif
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END Debugging support
//*********************************************************************************************************************************************************/
#endif // LIB_DBG_DEBUG_MQLAPI_TRACER_MQH_INCLUDED