| //+------------------------------------------------------------------+
|
| //| JsonNode.mqh |
|
| //| Copyright 2026, Niquel Mendoza. |
|
| //| https://www.mql5.com/ |
|
| //+------------------------------------------------------------------+
|
| #property copyright "Copyright 2026, Niquel Mendoza."
|
| #property link "https://www.mql5.com/"
|
| #property strict
|
|
|
| #ifndef JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH
|
| #define JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| #include "JsonNodeMethods.mqh"
|
| #include <TSN\\BSFL\\Node.mqh>
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| namespace TSN
|
| {
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| // Layour de los demas en repo base
|
| // Layout cinta:
|
| // NULL 1 pos [tipo(4)]
|
| // Array y obj tambien tine un slot mas (para el stirng raw..)
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| #define CJsonIteratorArray TSN::CNodeBaseIteradorArray<TSN::CJsonParser, TSN::CJsonNode>
|
| #define CJsonIteratorArrayFast TSN::CNodeBaseIteradorArrayFast<TSN::CJsonParser, TSN::CJsonNode>
|
| #define CJsonIteratorObj TSN::CNodeBaseIteratorObj<TSN::CJsonParser, TSN::CJsonNode>
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| struct CJsonNode : CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>
|
| {
|
| public:
|
| //---
|
| CJsonNode()
|
| : CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(NULL, -1, -1, -1) {}
|
| //--- Resuelve m_node_pos una unica vez aqui
|
| CJsonNode(CJsonParser* _ctx, const int _idx, const int _end)
|
| : CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _end, NODEBASEF_RES_BASE(_ctx, _idx)) {}
|
|
|
| CJsonNode(CJsonParser* _ctx, const int _idx)
|
| : 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) {}
|
|
|
|
|
| //--- String
|
| string ToString(const string def = "") const;
|
| __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;
|
|
|
| //---
|
| //- UInt
|
| ulong ToUInt(const ulong def) const;
|
| bool ToUIntSafe(ulong& val) const;
|
|
|
| //- Int
|
| long ToInt(const long def) const;
|
| bool ToIntSafe(long& val) const;
|
|
|
| //- Double
|
| double ToDouble(const double def) const;
|
|
|
| //--- MqlParam
|
| bool ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const;
|
|
|
| //--- Is
|
| __forceinline bool IsNull() const;
|
|
|
| //--- Navegacion raw
|
| static const CJsonNode EMPTY_NODE;
|
| static void OnMute(CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>& node);
|
| };
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| const CJsonNode CJsonNode::EMPTY_NODE;
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| 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...
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| To MqlParam |
|
| //+------------------------------------------------------------------+
|
| bool CJsonNode::ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const
|
| {
|
| //---
|
| // Si no es un tipo de data valido salimos
|
| 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)
|
| 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:
|
| param.integer_value = ToInt(0);
|
| break;
|
| case TYPE_FLOAT:
|
| param.double_value = float(ToDouble(0.0));
|
| break;
|
| case TYPE_DOUBLE:
|
| param.double_value = ToDouble(0.0);
|
| break;
|
| case TYPE_STRING:
|
| param.string_value = ToString("");
|
| break;
|
| default:
|
| param.string_value = ToString("");
|
| break;
|
| }
|
|
|
| //---
|
| return true;
|
| }
|
|
|
|
|
| //+------------------------------------------------------------------+
|
| //| String |
|
| //+------------------------------------------------------------------+
|
| string CJsonNode::ToString(const string def = "") const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F)
|
| return def;
|
|
|
| //---
|
| switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
|
| {
|
| case JSON_VTYPE_UINTEGER:
|
| {
|
| STRCONV_VALTOBUFFER_ULLSTR_WR(m_ctx.m_cinta[m_idx + 1], __s_node_str, w)
|
| return __s_node_str;
|
| }
|
| case JSON_VTYPE_INTEGER:
|
| return string(long(m_ctx.m_cinta[m_idx + 1]));
|
| case JSON_VTYPE_REAL:
|
| {
|
| TsnBitInterprete un;
|
| un.ulong_value = m_ctx.m_cinta[m_idx + 1];
|
| return string(un.double_value);
|
| }
|
| case JSON_VTYPE_BOOLEAN:
|
| return TSN_SBL_CNG_BOOL(m_idx) != 0 ? "true" : "false";
|
| case JSON_VTYPE_STRING:
|
| return m_ctx.GetStrAsStr<JPBL_STR_STR>(m_idx, __s_node_str) ? __s_node_str : def;
|
| default:
|
| return def;
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| __forceinline string CJsonNode::ToStringNoEscape(const string def = "", uint cp = CP_UTF8) const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| return def;
|
| 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);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| // NOTA: funciones que trabajan con arrays retornan -1 en este caso como señal de falo.. no
|
| // hay def posible aqui
|
| __forceinline int CJsonNode::ToStringUArray(uchar & data[]) const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| return -1;
|
| return m_ctx.GetStrAsUArr<JPBL_STR_STR>(m_idx, data);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| __forceinline int CJsonNode::ToStringUArrayNoEscape(uchar &data[]) const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| return -1;
|
| 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));
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| __forceinline int CJsonNode::StrLenRaw(void) const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| return 0;
|
| return TSN_SBL_CNG_STR_LEN(m_idx, TSN_SBL_SLEN_STR, int);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| __forceinline int CJsonNode::StrStart(void) const
|
| {
|
| //---
|
| if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| return 0;
|
| return TSN_SBL_CNG_STR_START(m_idx, int);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| 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;
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| ToInt |
|
| //+------------------------------------------------------------------+
|
| long CJsonNode::ToInt(const long 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:
|
| return (long)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 long(un.double_value);
|
| }
|
| case TSN_SBL_BASE_TYPE_BOL:
|
| return long(TSN_SBL_CNG_BOOL(m_idx));
|
| case TSN_SBL_BASE_TYPE_STR:
|
| 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)));
|
| default:
|
| return def;
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| bool CJsonNode::ToIntSafe(long & 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 = (long)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 = long(un.double_value);
|
| return true;
|
| }
|
| case TSN_SBL_BASE_TYPE_BOL:
|
| val = long(TSN_SBL_CNG_BOOL(m_idx));
|
| return true;
|
| case TSN_SBL_BASE_TYPE_STR:
|
| 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)));
|
| return true;
|
| default:
|
| return false;
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| ToDouble |
|
| //+------------------------------------------------------------------+
|
| double CJsonNode::ToDouble(const double 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:
|
| return double(m_ctx.m_cinta[m_idx + 1]);
|
| case TSN_SBL_BASE_TYPE_INT:
|
| return double(long(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 un.double_value;
|
| }
|
| case TSN_SBL_BASE_TYPE_BOL:
|
| return double(TSN_SBL_CNG_BOOL(m_idx));
|
| case TSN_SBL_BASE_TYPE_STR:
|
| 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)));
|
| default:
|
| return def;
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Is |
|
| //+------------------------------------------------------------------+
|
| __forceinline bool CJsonNode::IsNull() const
|
| {
|
| return NODEBASE_IS_VALID && int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) == JSON_VTYPE_NULL;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CJsonNode CJsonParser::GetRoot()
|
| {
|
| if(m_cinta_pos == 0)
|
| return CJsonNode::EMPTY_NODE;
|
| return CJsonNode(&this, 0, GetStep(0));
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| #endif // JSONPARSERBYLEO_SRC_JSONNODE_JSONNODE_MQH
|