//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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 #define CJsonIteratorArrayFast TSN::CNodeBaseIteradorArrayFast #define CJsonIteratorObj TSN::CNodeBaseIteratorObj //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ struct CJsonNode : CNodeSFLBase { public: //--- CJsonNode() : CNodeSFLBase(NULL, -1, -1, -1) {} //--- Resuelve m_node_pos una unica vez aqui CJsonNode(CJsonParser* _ctx, const int _idx, const int _end) : CNodeSFLBase(_ctx, _idx, _end, NODEBASEF_RES_BASE(_ctx, _idx)) {} CJsonNode(CJsonParser* _ctx, const int _idx) : CNodeSFLBase(_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(_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& node); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ const CJsonNode CJsonNode::EMPTY_NODE; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ static void CJsonNode::OnMute(CNodeSFLBase &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: return CValueToBuffer::ULLToStr(m_ctx.m_cinta[m_idx + 1]); 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: { static string res; return m_ctx.GetStrAsStr(m_idx, res) ? res : 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(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