JsonParserByLeo/Src/JsonNode/JsonNode.mqh

431 lines
15 KiB
MQL5

2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| JsonNode.mqh |
//| Copyright 2026, Niquel Mendoza. |
//| https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
#property link "https://www.mql5.com/"
#property strict
2026-10-08 13:39:44 -05:00
#ifndef JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH
#define JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH
2026-06-02 22:52:39 -05:00
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-10-06 08:01:09 -05:00
#include "JsonNodeMethods.mqh"
2026-10-08 13:39:44 -05:00
#include <TSN\\BSFL\\Node.mqh>
2026-07-27 08:40:51 -05:00
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
2026-09-23 15:25:08 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
// Layour de los demas en repo base
2026-06-02 22:52:39 -05:00
// Layout cinta:
// NULL 1 pos [tipo(4)]
2026-09-23 15:25:08 -05:00
// Array y obj tambien tine un slot mas (para el stirng raw..)
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-27 08:40:51 -05:00
#define CJsonIteratorArray TSN::CNodeBaseIteradorArray<TSN::CJsonParser, TSN::CJsonNode>
#define CJsonIteratorArrayFast TSN::CNodeBaseIteradorArrayFast<TSN::CJsonParser, TSN::CJsonNode>
#define CJsonIteratorObj TSN::CNodeBaseIteratorObj<TSN::CJsonParser, TSN::CJsonNode>
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-26 16:46:05 -05:00
struct CJsonNode : CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>
2026-06-02 21:23:50 -05:00
{
2026-06-02 22:52:39 -05:00
public:
2026-06-02 21:23:50 -05:00
//---
CJsonNode()
2026-07-26 16:46:05 -05:00
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(NULL, -1, -1, -1) {}
2026-09-23 15:25:08 -05:00
//--- Resuelve m_node_pos una unica vez aqui
2026-06-02 21:23:50 -05:00
CJsonNode(CJsonParser* _ctx, const int _idx, const int _end)
2026-07-26 16:46:05 -05:00
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _end, NODEBASEF_RES_BASE(_ctx, _idx)) {}
2026-06-21 20:08:59 -05:00
2026-06-23 08:02:37 -05:00
CJsonNode(CJsonParser* _ctx, const int _idx)
2026-07-26 16:46:05 -05:00
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _idx + _ctx.GetStep(_idx), NODEBASEF_RES_BASE(_ctx, _idx)) {}
// Exclusivo de copia (Aqui NO RESUELVE NADA NI GET STE NI NADA) (constructor de clonacion)
CJsonNode(CJsonParser* _ctx, const int _idx, const int _end, const int _node_pos)
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _end, _node_pos) {}
2026-06-02 21:23:50 -05:00
2026-06-23 08:02:37 -05:00
//--- String
2026-06-02 22:52:39 -05:00
string ToString(const string def = "") const;
2026-09-23 15:25:08 -05:00
__forceinline int ToStringUArray(uchar& data[]) const;
__forceinline string ToStringNoEscape(const string def = "", uint cp = CP_UTF8) const;
__forceinline int ToStringUArrayNoEscape(uchar& data[]) const;
__forceinline int StrLenRaw() const;
__forceinline int StrStart() const;
2026-07-10 13:17:36 -05:00
2026-09-30 07:39:54 -05:00
//---
//- UInt
2026-10-08 13:39:44 -05:00
ulong ToUInt(const ulong def) const;
2026-09-30 07:39:54 -05:00
bool ToUIntSafe(ulong& val) const;
//- Int
2026-06-02 22:52:39 -05:00
long ToInt(const long def) const;
bool ToIntSafe(long& val) const;
2026-06-23 08:02:37 -05:00
2026-09-30 07:39:54 -05:00
//- Double
2026-06-02 22:52:39 -05:00
double ToDouble(const double def) const;
2026-06-23 08:02:37 -05:00
2026-07-27 08:40:51 -05:00
//--- MqlParam
bool ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const;
2026-06-02 22:52:39 -05:00
//--- Is
2026-09-23 15:25:08 -05:00
__forceinline bool IsNull() const;
2026-06-02 22:52:39 -05:00
//--- Navegacion raw
2026-07-26 16:46:05 -05:00
static const CJsonNode EMPTY_NODE;
2026-07-27 16:07:47 -05:00
static void OnMute(CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>& node);
2026-06-02 21:23:50 -05:00
};
2026-07-27 08:40:51 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-26 16:46:05 -05:00
const CJsonNode CJsonNode::EMPTY_NODE;
2026-07-24 14:20:14 -05:00
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
2026-07-27 16:07:47 -05:00
//| |
//+------------------------------------------------------------------+
static void CJsonNode::OnMute(CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode> &node)
{
node.RecalcNodePos(); // Posicion...
node.m_end = node.m_idx + node.m_ctx.GetStep(node.m_idx); // Calculamos el fin...
}
//+------------------------------------------------------------------+
2026-07-27 08:40:51 -05:00
//| To MqlParam |
//+------------------------------------------------------------------+
bool CJsonNode::ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const
{
//---
// Si no es un tipo de data valido salimos
2026-09-30 07:39:54 -05:00
if(NODEBASE_IS_NOT_VALID_F ||
CJsonParser::s_dtype_to_str[uchar(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)].Length() == 0)
2026-07-27 08:40:51 -05:00
return false;
//---
param.type = type;
//---
switch(type)
{
case TYPE_BOOL:
param.integer_value = ToBool(false);
break;
case TYPE_CHAR:
param.integer_value = char(ToInt(0));
break;
case TYPE_UCHAR:
param.integer_value = uchar(ToInt(0));
break;
case TYPE_SHORT:
param.integer_value = short(ToInt(0));
break;
case TYPE_USHORT:
param.integer_value = ushort(ToInt(0));
break;
case TYPE_COLOR:
param.integer_value = long(color(ToString("")));
break;
case TYPE_INT:
param.integer_value = int(ToInt(0));
break;
case TYPE_UINT:
param.integer_value = uint(ToInt(0));
break;
case TYPE_DATETIME:
param.integer_value = long(datetime(ToString("")));
break;
case TYPE_LONG:
case TYPE_ULONG:
2026-09-30 07:39:54 -05:00
param.integer_value = ToInt(0);
2026-07-27 08:40:51 -05:00
break;
case TYPE_FLOAT:
2026-10-08 13:39:44 -05:00
param.double_value = float(ToDouble(0.0));
2026-07-27 08:40:51 -05:00
break;
case TYPE_DOUBLE:
2026-10-08 13:39:44 -05:00
param.double_value = ToDouble(0.0);
2026-07-27 08:40:51 -05:00
break;
case TYPE_STRING:
param.string_value = ToString("");
break;
default:
param.string_value = ToString("");
break;
}
//---
return true;
}
2026-06-02 22:52:39 -05:00
2026-06-03 16:57:42 -05:00
//+------------------------------------------------------------------+
2026-06-23 08:02:37 -05:00
//| String |
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
string CJsonNode::ToString(const string def = "") const
{
2026-06-26 17:53:09 -05:00
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F)
2026-06-26 17:53:09 -05:00
return def;
2026-06-02 22:52:39 -05:00
//---
2026-07-19 07:41:52 -05:00
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
2026-06-02 22:52:39 -05:00
{
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
2026-10-08 13:39:44 -05:00
return CValueToBuffer::ULLToStr(m_ctx.m_cinta[m_idx + 1]);
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_INTEGER:
2026-10-08 13:39:44 -05:00
return string(long(m_ctx.m_cinta[m_idx + 1]));
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_REAL:
2026-07-26 16:46:05 -05:00
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
2026-07-26 16:46:05 -05:00
return string(un.double_value);
}
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_BOOLEAN:
2026-10-08 13:39:44 -05:00
return TSN_SBL_CNG_BOOL(m_idx) != 0 ? "true" : "false";
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_STRING:
2026-10-01 08:25:33 -05:00
{
2026-10-06 08:01:09 -05:00
static string res;
2026-10-08 13:39:44 -05:00
return m_ctx.GetStrAsStr<JPBL_STR_STR>(m_idx, res) ? res : def;
2026-10-01 08:25:33 -05:00
}
2026-09-23 15:25:08 -05:00
default:
return def;
2026-06-02 22:52:39 -05:00
}
}
2026-07-10 13:17:36 -05:00
//+------------------------------------------------------------------+
2026-09-23 15:25:08 -05:00
__forceinline string CJsonNode::ToStringNoEscape(const string def = "", uint cp = CP_UTF8) const
2026-07-10 13:17:36 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
2026-07-10 13:17:36 -05:00
return def;
2026-10-08 13:39:44 -05:00
return CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int), TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int), cp);
2026-07-10 13:17:36 -05:00
}
2026-06-23 08:02:37 -05:00
//+------------------------------------------------------------------+
2026-10-01 08:25:33 -05:00
// NOTA: funciones que trabajan con arrays retornan -1 en este caso como señal de falo.. no
// hay def posible aqui
2026-09-23 15:25:08 -05:00
__forceinline int CJsonNode::ToStringUArray(uchar & data[]) const
2026-06-23 08:02:37 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
2026-10-01 08:25:33 -05:00
return -1;
2026-10-08 13:39:44 -05:00
return m_ctx.GetStrAsUArr<JPBL_STR_STR>(m_idx, data);
2026-06-23 08:02:37 -05:00
}
//+------------------------------------------------------------------+
2026-09-23 15:25:08 -05:00
__forceinline int CJsonNode::ToStringUArrayNoEscape(uchar &data[]) const
2026-06-23 08:02:37 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
2026-10-01 08:25:33 -05:00
return -1;
2026-10-08 13:39:44 -05:00
return ArrayCopy(data, m_ctx.m_raw, 0, TSN_SBL_CNG_STR_START(m_idx, int), TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int));
2026-06-23 08:02:37 -05:00
}
//+------------------------------------------------------------------+
2026-09-23 15:25:08 -05:00
__forceinline int CJsonNode::StrLenRaw(void) const
2026-06-23 08:02:37 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
2026-06-23 08:02:37 -05:00
return 0;
2026-10-08 13:39:44 -05:00
return TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int);
2026-06-23 08:02:37 -05:00
}
//+------------------------------------------------------------------+
2026-09-23 15:25:08 -05:00
__forceinline int CJsonNode::StrStart(void) const
2026-06-23 08:02:37 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
2026-06-23 08:02:37 -05:00
return 0;
2026-10-08 13:39:44 -05:00
return TSN_SBL_CNG_STR_START(m_idx, int);
2026-06-23 08:02:37 -05:00
}
2026-08-25 21:23:08 -05:00
2026-10-13 21:28:39 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong CJsonNode::ToUInt(const ulong def) const
{
//---
if(NODEBASE_IS_NOT_VALID_F)
return def;
//---
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
{
case TSN_SBL_BASE_TYPE_UINT:
case TSN_SBL_BASE_TYPE_INT: // ya tiene el valor "volteado"
return m_ctx.m_cinta[m_idx + 1];
case TSN_SBL_BASE_TYPE_FLT:
{
TsnBitInterprete un;
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
return ulong(un.double_value);
}
case TSN_SBL_BASE_TYPE_BOL:
return ulong(TSN_SBL_CNG_BOOL(m_idx));
case TSN_SBL_BASE_TYPE_STR:
return ulong(CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int),
TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int)));
default:
return def;
}
}
//+------------------------------------------------------------------+
bool CJsonNode::ToUIntSafe(ulong &val) const
{
//---
if(NODEBASE_IS_NOT_VALID_F)
return false;
//---
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
{
case TSN_SBL_BASE_TYPE_UINT:
case TSN_SBL_BASE_TYPE_INT:
val = m_ctx.m_cinta[m_idx + 1];
return true;
case TSN_SBL_BASE_TYPE_FLT:
{
TsnBitInterprete un;
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
val = ulong(un.double_value);
return true;
}
case TSN_SBL_BASE_TYPE_BOL:
val = ulong(TSN_SBL_CNG_BOOL(m_idx));
return true;
case TSN_SBL_BASE_TYPE_STR:
val = ulong(CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int),
TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int)));
return true;
default:
return false;
}
}
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
//| ToInt |
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
long CJsonNode::ToInt(const long def) const
2026-06-02 22:52:39 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F)
return def;
2026-06-02 22:52:39 -05:00
//---
2026-07-19 07:41:52 -05:00
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
{
2026-09-30 07:39:54 -05:00
case TSN_SBL_BASE_TYPE_UINT:
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_INT:
2026-10-08 13:39:44 -05:00
return (long)m_ctx.m_cinta[m_idx + 1];
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_FLT:
2026-07-26 16:46:05 -05:00
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
2026-07-26 16:46:05 -05:00
return long(un.double_value);
}
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_BOL:
2026-10-08 13:39:44 -05:00
return long(TSN_SBL_CNG_BOOL(m_idx));
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_STR:
2026-10-08 13:39:44 -05:00
return long(CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int),
TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int)));
2026-09-23 15:25:08 -05:00
default:
return def;
2026-07-19 07:41:52 -05:00
}
2026-06-21 20:08:59 -05:00
}
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
bool CJsonNode::ToIntSafe(long & val) const
2026-06-21 20:08:59 -05:00
{
//---
2026-07-19 07:41:52 -05:00
if(NODEBASE_IS_NOT_VALID_F)
2026-06-21 20:08:59 -05:00
return false;
//---
2026-07-19 07:41:52 -05:00
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
{
2026-09-30 07:39:54 -05:00
case TSN_SBL_BASE_TYPE_UINT:
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_INT:
2026-10-08 13:39:44 -05:00
val = (long)m_ctx.m_cinta[m_idx + 1];
2026-07-19 07:41:52 -05:00
return true;
case TSN_SBL_BASE_TYPE_FLT:
2026-07-26 16:46:05 -05:00
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
2026-07-26 16:46:05 -05:00
val = long(un.double_value);
return true;
}
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_BOL:
2026-10-08 13:39:44 -05:00
val = long(TSN_SBL_CNG_BOOL(m_idx));
2026-07-19 07:41:52 -05:00
return true;
case TSN_SBL_BASE_TYPE_STR:
2026-10-08 13:39:44 -05:00
val = long(CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int),
TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int)));
2026-07-26 16:46:05 -05:00
return true;
2026-09-23 15:25:08 -05:00
default:
return false;
2026-07-19 07:41:52 -05:00
}
2026-06-21 20:08:59 -05:00
}
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
//| ToDouble |
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
double CJsonNode::ToDouble(const double def) const
2026-06-02 22:52:39 -05:00
{
2026-07-19 07:41:52 -05:00
//---
if(NODEBASE_IS_NOT_VALID_F)
return def;
2026-06-02 22:52:39 -05:00
2026-07-19 07:41:52 -05:00
//---
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
{
2026-09-30 07:39:54 -05:00
case TSN_SBL_BASE_TYPE_UINT:
2026-07-19 07:41:52 -05:00
return double(m_ctx.m_cinta[m_idx + 1]);
2026-10-08 13:39:44 -05:00
case TSN_SBL_BASE_TYPE_INT:
return double(long(m_ctx.m_cinta[m_idx + 1]));
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_FLT:
2026-07-26 16:46:05 -05:00
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
2026-07-26 16:46:05 -05:00
return un.double_value;
}
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_BOL:
2026-10-08 13:39:44 -05:00
return double(TSN_SBL_CNG_BOOL(m_idx));
2026-07-19 07:41:52 -05:00
case TSN_SBL_BASE_TYPE_STR:
2026-10-08 13:39:44 -05:00
return double(CharArrayToString(m_ctx.m_raw, TSN_SBL_CNG_STR_START(m_idx, int),
TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int)));
2026-09-23 15:25:08 -05:00
default:
return def;
2026-07-19 07:41:52 -05:00
}
2026-06-02 22:52:39 -05:00
}
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
//| Is |
//+------------------------------------------------------------------+
__forceinline bool CJsonNode::IsNull() const
2026-06-02 22:52:39 -05:00
{
2026-10-08 13:39:44 -05:00
return NODEBASE_IS_VALID && int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) == JSON_VTYPE_NULL;
2026-07-19 07:41:52 -05:00
}
2026-06-21 20:08:59 -05:00
2026-07-19 07:41:52 -05:00
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
//| |
2026-07-19 07:41:52 -05:00
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
CJsonNode CJsonParser::GetRoot()
2026-07-19 07:41:52 -05:00
{
2026-10-08 13:39:44 -05:00
if(m_cinta_pos == 0)
return CJsonNode::EMPTY_NODE;
return CJsonNode(&this, 0, GetStep(0));
2026-06-02 22:52:39 -05:00
}
2026-06-02 21:23:50 -05:00
}
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
#endif // JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH