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-06-02 22:52:39 -05:00 | | | #ifndef JSONPARSERBYLEO_SRC_JSONNODE_MQH
|
| | | #define JSONPARSERBYLEO_SRC_JSONNODE_MQH
|
| | |
|
2026-06-02 21:23:50 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-06-18 09:48:36 -05:00 | | | #include "JsonAsm.mqh"
|
2026-07-19 18:32:50 -05:00 | | | #include "JsonDomSerializer.mqh"
|
2026-06-02 21:23:50 -05:00 | | |
|
2026-07-27 08:40:51 -05:00 | | | //---
|
| | | #include <TSN\\MQLArticles\\Utils\\EnumReg.mqh>
|
| | |
|
2026-06-02 21:23:50 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
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:
|
2026-06-04 11:36:42 -05:00 | | | // NULL 1 pos [tipo(4)]
|
2026-06-02 22:52:39 -05:00 | | |
|
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-06-21 20:08:59 -05:00 | | | //--- Resuelve m_node_pos una unica vez aqui (igual que YML_NODE_RPOS en YAML)
|
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-02 22:52:39 -05:00 | | | //--- Acceso
|
2026-06-20 13:57:50 -05:00 | | | CJsonNode operator[](const string& key);
|
2026-07-26 16:46:05 -05:00 | | | //CJsonNode At(const int index) const;
|
| | |
|
2026-06-23 08:02:37 -05:00 | | |
|
2026-06-21 20:08:59 -05:00 | | | //--- Array
|
| | | template <typename T>
|
| | | int ToArray(T& out_arr[]) const;
|
2026-06-23 08:02:37 -05:00 | | | // Exist?
|
| | | template <typename T>
|
2026-07-19 07:41:52 -05:00 | | | bool ExistInArray(const uint flags, const T val) const;
|
2026-06-23 08:02:37 -05:00 | | | bool ExistInArrayStr(const string& val) const;
|
2026-06-24 17:20:42 -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-06-03 16:57:42 -05:00 | | | int ToStringUArray(uchar& data[]) const;
|
2026-06-23 08:02:37 -05:00 | | | string ToStringNoEscape(const string def = "") const;
|
| | | int ToStringUArrayNoEscape(uchar& data[]) const;
|
| | | int StrLenRaw() const;
|
| | | __forceinline bool CompareStrWith(const string& str) const; // Compara sin pagar el costo de copias.. directo al buffer.
|
| | |
|
2026-08-25 21:23:08 -05:00 | | | //-- to bytes (asume hex string)
|
| | | int HexToBytes(uchar& buf[]) const;
|
| | |
|
2026-07-10 13:17:36 -05:00 | | | // Interpolacion
|
| | | template <typename TInterpolate>
|
| | | string Interpolate(const TInterpolate& cs, const string def) const;
|
| | |
|
2026-07-19 07:41:52 -05:00 | | | //---
|
| | | string ComplexToString(bool clean) const;
|
| | | int ComplexToData(uchar& data[], bool clean, int dst_start = 0, bool ajustar_arr = true) const;
|
| | |
|
2026-06-23 08:02:37 -05:00 | | | //--- 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 | | |
|
| | | //--- Double
|
2026-06-02 22:52:39 -05:00 | | | double ToDouble(const double def) const;
|
| | | bool ToDoubleSafe(double& val) const;
|
2026-06-23 08:02:37 -05:00 | | |
|
2026-07-27 08:40:51 -05:00 | | | //--- MqlParam
|
| | | bool ToMqlParam(MqlParam& param, const string stype) const;
|
| | | bool ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const;
|
| | |
|
| | |
|
2026-06-02 22:52:39 -05:00 | | | //--- Is
|
2026-06-23 08:02:37 -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 |
|
| | | //+------------------------------------------------------------------+
|
| | | __forceinline bool CJsonNode::ToMqlParam(MqlParam& param, const string stype) const
|
| | | {
|
| | | const ENUM_DATATYPE type = CEnumRegBasis::GetVal<ENUM_DATATYPE>(stype, WRONG_VALUE);
|
| | | return type == WRONG_VALUE ? false : ToMqlParam(param, type);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | 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_is_valid[uchar(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)])
|
| | | 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 = long(ToInt(0));
|
| | | break;
|
| | | case TYPE_FLOAT:
|
| | | param.double_value = float(ToInt(0));
|
| | | break;
|
| | | case TYPE_DOUBLE:
|
| | | param.double_value = double(ToInt(0));
|
| | | break;
|
| | | case TYPE_STRING:
|
| | | param.string_value = ToString("");
|
| | | break;
|
| | | default:
|
| | | param.string_value = ToString("");
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-06-03 07:50:45 -05:00 | | | //| |
|
2026-06-02 21:23:50 -05:00 | | | //+------------------------------------------------------------------+
|
2026-07-10 07:17:28 -05:00 | | | string CJsonNode::ComplexToString(bool clean) const
|
2026-06-03 12:20:23 -05:00 | | | {
|
2026-07-19 07:41:52 -05:00 | | | if(NODEBASE_IS_NOT_VALID_F || ((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) & (TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
2026-06-03 12:20:23 -05:00 | | | return "";
|
| | |
|
| | | //---
|
| | | const int start = int(m_ctx.m_cinta[m_idx + 1] & 0xFFFFFFFF);
|
| | | const int end = int(m_ctx.m_cinta[m_idx + 1] >> TSN_JSON_BIT_END_T);
|
2026-07-19 07:41:52 -05:00 | | | return clean ? m_ctx.CleanNode(start, end) : CharArrayToString(m_ctx.m_raw, start, (end - start) + 1);
|
2026-06-03 12:20:23 -05:00 | | | }
|
| | |
|
2026-06-03 16:57:42 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-07-15 17:58:56 -05:00 | | | int CJsonNode::ComplexToData(uchar &data[], bool clean, int dst_start = 0, bool ajustar_arr = true) const
|
2026-06-03 16:57:42 -05:00 | | | {
|
2026-07-19 07:41:52 -05:00 | | | if(NODEBASE_IS_NOT_VALID_F || ((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) & (TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
2026-06-03 16:57:42 -05:00 | | | return 0;
|
| | |
|
| | | //---
|
| | | const int start = int(m_ctx.m_cinta[m_idx + 1] & 0xFFFFFFFF);
|
| | | const int end = int(m_ctx.m_cinta[m_idx + 1] >> TSN_JSON_BIT_END_T);
|
2026-07-15 17:58:56 -05:00 | | | return clean ? m_ctx.CleanNode(start, end, data, dst_start, ajustar_arr) :
|
2026-07-19 07:41:52 -05:00 | | | ArrayCopy(data, m_ctx.m_raw, dst_start, start, (end - start) + 1);
|
2026-06-20 13:57:50 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | CJsonNode CJsonNode::operator[](const string& key)
|
2026-06-02 21:23:50 -05:00 | | | {
|
2026-06-02 22:52:39 -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_OBJ)
|
2026-07-26 16:46:05 -05:00 | | | return EMPTY_NODE;
|
2026-06-02 22:52:39 -05:00 | | |
|
| | | //--- Iterar pares KEY+VAL
|
2026-06-20 13:57:50 -05:00 | | | // Print("Call");
|
2026-07-19 07:41:52 -05:00 | | | if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & TSN_SBL_BIT_MASK_IS_HASHSING) == 0)
|
2026-06-02 22:52:39 -05:00 | | | {
|
2026-06-20 13:57:50 -05:00 | | | //Print("No esta hasheado buscando o(n)");
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | int c = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_C_HASH) & TSN_SBL_BIT_MASK_NUM_C_HASH;
|
2026-06-20 13:57:50 -05:00 | | | //Print("Contador actual: ", c);
|
2026-07-26 18:16:21 -05:00 | | | if(c >= TSN_NODEBASEREAD_MIN_JIT_ATTEMPS_TO_PHASH) // Veriricamos si supero
|
2026-06-02 22:52:39 -05:00 | | | {
|
2026-06-20 13:57:50 -05:00 | | | if(NodeHashing())
|
| | | {
|
2026-06-24 17:20:42 -05:00 | | | //Print("Hasheado");
|
2026-06-20 13:57:50 -05:00 | | | //--- Obtenemos posicion
|
2026-06-24 17:20:42 -05:00 | | | int val_pos = m_ctx.PerfectHashComputeHash(key, m_node_pos);
|
| | | if(val_pos == -1)
|
| | | {
|
2026-07-26 16:46:05 -05:00 | | | return EMPTY_NODE;
|
2026-06-24 17:20:42 -05:00 | | | }
|
| | | else
|
| | | {
|
| | | val_pos++; // Luego de key
|
| | | return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
| | | }
|
2026-06-20 13:57:50 -05:00 | | | }
|
2026-06-24 17:20:42 -05:00 | | | //Print("No se pudo hashear");
|
2026-06-20 13:57:50 -05:00 | | | // Si llega aqui es por que fallo.. en ese caso reiniciamos los intetnos..
|
| | |
|
| | | //---
|
| | | c = 0;
|
2026-07-19 07:41:52 -05:00 | | | const long mask = long(TSN_SBL_BIT_MASK_NUM_C_HASH) << TSN_SBL_BIT_START_NUM_C_HASH; // máscara de 3 bits en pos 5
|
| | | m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) | (c << TSN_SBL_BIT_START_NUM_C_HASH);
|
2026-06-02 22:52:39 -05:00 | | | }
|
2026-06-20 13:57:50 -05:00 | | | else
|
2026-06-02 22:52:39 -05:00 | | | {
|
2026-06-20 13:57:50 -05:00 | | | // Aun no.. solo aumentamos y modificamos..
|
| | | c++;
|
2026-07-19 07:41:52 -05:00 | | | const long mask = long(TSN_SBL_BIT_MASK_NUM_C_HASH) << TSN_SBL_BIT_START_NUM_C_HASH; // máscara de 3 bits en pos 5
|
| | | m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) | (c << TSN_SBL_BIT_START_NUM_C_HASH);
|
2026-06-02 22:52:39 -05:00 | | | }
|
| | |
|
2026-06-20 13:57:50 -05:00 | | | //--- Linear probing.. de siempre...
|
| | | int cur = m_idx + 2;
|
| | | while(cur < m_end)
|
| | | {
|
2026-07-19 07:41:52 -05:00 | | | if(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_KEY)
|
2026-06-20 13:57:50 -05:00 | | | {
|
| | | cur += m_ctx.GetStep(cur);
|
| | | continue;
|
| | | }
|
2026-07-26 16:46:05 -05:00 | | | if(m_ctx.KeysEqual(key, cur))
|
2026-06-20 13:57:50 -05:00 | | | {
|
2026-06-20 14:18:38 -05:00 | | | const int val_pos = cur + 1;
|
2026-06-20 13:57:50 -05:00 | | | return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
| | | }
|
| | |
|
2026-06-20 14:18:38 -05:00 | | | //---
|
| | | cur++; // salta KEY
|
2026-06-20 13:57:50 -05:00 | | | cur += m_ctx.GetStep(cur); // salta VAL
|
| | | }
|
2026-07-26 16:46:05 -05:00 | | | return EMPTY_NODE;
|
2026-06-02 22:52:39 -05:00 | | | }
|
| | |
|
2026-06-21 20:08:59 -05:00 | | | //--- m_node_pos ya viene resuelto desde el constructor
|
2026-06-24 17:20:42 -05:00 | | | int val_pos = m_ctx.PerfectHashComputeHash(key, m_node_pos);
|
| | | if(val_pos == -1)
|
| | | {
|
2026-07-26 16:46:05 -05:00 | | | return EMPTY_NODE;
|
2026-06-24 17:20:42 -05:00 | | | }
|
| | | else
|
| | | {
|
| | | val_pos++; // Luego de key
|
| | | return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
| | | }
|
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 | | | {
|
| | | case JSON_VTYPE_INTEGER:
|
| | | return string(m_ctx.m_cinta[m_idx + 1]);
|
| | | case JSON_VTYPE_REAL:
|
2026-07-26 16:46:05 -05:00 | | | {
|
2026-08-28 08:28:32 -05:00 | | | TsnBitInterprete un;
|
2026-07-26 16:46:05 -05:00 | | | un.long_value = m_ctx.m_cinta[m_idx + 1];
|
| | | return string(un.double_value);
|
| | | }
|
2026-06-02 22:52:39 -05:00 | | | case JSON_VTYPE_BOOLEAN:
|
2026-07-19 07:41:52 -05:00 | | | return ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1) != 0 ? "true" : "false";
|
2026-06-02 22:52:39 -05:00 | | | case JSON_VTYPE_STRING:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return m_ctx.Unescape(start, start + slen - 1);
|
| | | }
|
2026-06-02 22:52:39 -05:00 | | | }
|
| | |
|
| | | return def;
|
| | | }
|
| | |
|
2026-07-10 13:17:36 -05:00 | | | //+------------------------------------------------------------------+
|
| | | template <typename TInterpolate>
|
| | | string CJsonNode::Interpolate(const TInterpolate& cs, const string def) const
|
| | | {
|
| | | //---
|
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-07-19 07:41:52 -05:00 | | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return cs.Interpolate(m_ctx.m_raw, start, start + slen - 1, def);
|
2026-07-10 13:17:36 -05:00 | | | }
|
| | |
|
2026-06-23 08:02:37 -05:00 | | | //+------------------------------------------------------------------+
|
| | | string CJsonNode::ToStringNoEscape(const string def = "") const
|
| | | {
|
| | | //---
|
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 def;
|
| | |
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return CharArrayToString(m_ctx.m_raw, start, slen);
|
2026-06-23 08:02:37 -05:00 | | |
|
| | | //---
|
| | | return def;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | int CJsonNode::ToStringUArray(uchar & data[]) const
|
| | | {
|
| | | //---
|
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-07-19 07:41:52 -05:00 | | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
2026-06-23 08:02:37 -05:00 | | | return m_ctx.Unescape(start, start + slen - 1, data);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | int CJsonNode::ToStringUArrayNoEscape(uchar &data[]) const
|
| | | {
|
| | | //---
|
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-07-19 07:41:52 -05:00 | | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return ArrayCopy(data, m_ctx.m_raw, 0, start, slen);
|
2026-06-23 08:02:37 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | int CJsonNode::StrLenRaw(void) const
|
| | | {
|
| | | //---
|
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-07-19 07:41:52 -05:00 | | | return int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
2026-06-23 08:02:37 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | __forceinline bool CJsonNode::CompareStrWith(const string &str) const
|
| | | {
|
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 false;
|
| | | return m_ctx.StrEquals(str, m_idx);
|
| | | }
|
2026-08-25 21:23:08 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | int CJsonNode::HexToBytes(uchar &buf[]) const
|
| | | {
|
| | | if(NODEBASE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
|
| | | return 0;
|
| | | // ahora si en value
|
| | | // tenemos que recortar por la parte alta
|
| | |
|
| | | //---
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | |
|
| | | //---
|
| | | const int sob = slen & 1; // % 2 (vemos si hay sobrante o si es multiplo de dos exacto)
|
| | | int exact_len = slen - sob;
|
2026-09-04 09:06:00 -05:00 | | | ArrayResize(buf, (slen >> 1) + sob);
|
2026-08-25 21:23:08 -05:00 | | | int w = 0;
|
| | |
|
| | | //---
|
| | | exact_len += start; // para que peuda empzar bien..
|
| | | int i = start;
|
2026-09-04 09:06:00 -05:00 | | |
|
2026-08-25 21:23:08 -05:00 | | | //---
|
2026-09-04 09:06:00 -05:00 | | | if(sob)
|
| | | {
|
| | | buf[w++] = g_arr_valid_hex_chars[m_ctx.m_raw[i++]];
|
| | | exact_len++;
|
| | | }
|
| | | //---
|
| | | for(; i < exact_len; i += 2)
|
| | | buf[w++] = (g_arr_valid_hex_chars[m_ctx.m_raw[i]] << 4) | g_arr_valid_hex_chars[m_ctx.m_raw[i + 1]];
|
| | |
|
2026-08-25 21:23:08 -05:00 | | | //---
|
| | | return w;
|
| | | }
|
| | |
|
2026-06-21 20:08:59 -05:00 | | | //+------------------------------------------------------------------+
|
2026-06-23 08:02:37 -05:00 | | | //| Arrays |
|
2026-06-21 20:08:59 -05:00 | | | //+------------------------------------------------------------------+
|
| | | template <typename T>
|
| | | int CJsonNode::ToArray(T &out_arr[]) const
|
| | | {
|
| | | //---
|
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_ARR)
|
2026-06-21 20:08:59 -05:00 | | | return 0;
|
| | |
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
2026-06-21 20:08:59 -05:00 | | | ArrayResize(out_arr, count);
|
| | |
|
| | | //---
|
| | | int cur = m_idx + 2;
|
| | | int k = 0;
|
| | |
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | switch(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
|
2026-06-21 20:08:59 -05:00 | | | {
|
| | | case JSON_VTYPE_INTEGER:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | while(cur < m_end)
|
2026-06-21 20:08:59 -05:00 | | | {
|
2026-07-26 16:46:05 -05:00 | | | out_arr[k++] = T(m_ctx.m_cinta[cur + 1]);
|
| | | cur += 2;
|
2026-06-21 20:08:59 -05:00 | | | }
|
2026-07-26 16:46:05 -05:00 | | | return count;
|
| | | }
|
2026-06-21 20:08:59 -05:00 | | | case JSON_VTYPE_REAL:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | while(cur < m_end)
|
2026-06-21 20:08:59 -05:00 | | | {
|
2026-08-28 08:28:32 -05:00 | | | TsnBitInterprete bit;
|
2026-07-26 16:46:05 -05:00 | | | bit.long_value = m_ctx.m_cinta[cur + 1];
|
| | | out_arr[k++] = T(bit.double_value);
|
| | | cur += 2;
|
2026-06-21 20:08:59 -05:00 | | | }
|
2026-07-26 16:46:05 -05:00 | | | return count;
|
| | | }
|
2026-06-21 20:08:59 -05:00 | | | case JSON_VTYPE_BOOLEAN:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | while(cur < m_end)
|
2026-06-21 20:08:59 -05:00 | | | {
|
2026-07-26 16:46:05 -05:00 | | | out_arr[k++] = T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
| | | cur++;
|
2026-06-21 20:08:59 -05:00 | | | }
|
2026-07-26 16:46:05 -05:00 | | | return count;
|
| | | }
|
2026-06-21 20:08:59 -05:00 | | | case JSON_VTYPE_STRING:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | while(cur < m_end)
|
2026-06-21 20:08:59 -05:00 | | | {
|
2026-07-26 16:46:05 -05:00 | | | const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | out_arr[k++] = T(m_ctx.Unescape(start, start + slen - 1));
|
| | | cur++;
|
2026-06-21 20:08:59 -05:00 | | | }
|
2026-07-26 16:46:05 -05:00 | | | return count;
|
| | | }
|
2026-06-21 20:08:59 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | return 0;
|
| | | }
|
| | |
|
2026-06-23 08:02:37 -05:00 | | | //+------------------------------------------------------------------+
|
| | | template <typename T>
|
2026-07-19 07:41:52 -05:00 | | | bool CJsonNode::ExistInArray(const uint flags, const T val) 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_ARR)
|
2026-06-23 08:02:37 -05:00 | | | return false;
|
| | |
|
| | | //---
|
| | | int cur = m_idx + 2;
|
| | | while(cur < m_end)
|
| | | {
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | const uint ct = 1U << uint(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
|
| | | if((ct & flags) == 0)
|
2026-06-23 08:02:37 -05:00 | | | {
|
| | | cur += m_ctx.GetStep(cur);
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | switch(ct)
|
| | | {
|
| | | case JSON_VTYPE_INTEGER:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | if(m_ctx.m_cinta[cur + 1] == T(val))
|
| | | return true;
|
| | | break;
|
| | | }
|
2026-06-23 08:02:37 -05:00 | | | case JSON_VTYPE_REAL:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | bit.long_value = m_ctx.m_cinta[cur + 1];
|
| | | if(bit.double_value == T(val))
|
| | | return true;
|
| | | break;
|
| | | }
|
2026-06-23 08:02:37 -05:00 | | | case JSON_VTYPE_BOOLEAN:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | if(val == T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1))
|
| | | return true;
|
| | | break;
|
| | | }
|
2026-06-23 08:02:37 -05:00 | | | case JSON_VTYPE_STRING:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | if(val == T(m_ctx.Unescape(start, start + slen - 1)))
|
2026-06-23 08:02:37 -05:00 | | | return true;
|
2026-07-26 16:46:05 -05:00 | | | break;
|
| | | }
|
| | | case JSON_VTYPE_NULL:
|
| | | {
|
| | | return true;
|
| | | }
|
2026-06-23 08:02:37 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | cur += m_ctx.GetStep(cur);
|
| | | }
|
| | |
|
| | | //---
|
| | | return false;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CJsonNode::ExistInArrayStr(const string& val) const
|
| | | {
|
| | | //---
|
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_ARR)
|
2026-06-23 08:02:37 -05:00 | | | return false;
|
| | |
|
| | | //---
|
| | | int cur = m_idx + 2;
|
| | | while(cur < m_end)
|
| | | {
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | const int ct = int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
|
2026-06-23 08:02:37 -05:00 | | | if(ct != JSON_VTYPE_STRING)
|
| | | {
|
| | | cur += m_ctx.GetStep(cur);
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
2026-07-19 07:41:52 -05:00 | | | const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
2026-06-23 08:02:37 -05:00 | | | if(val == m_ctx.Unescape(start, start + slen - 1))
|
| | | return true;
|
| | |
|
| | | //---
|
| | | cur += m_ctx.GetStep(cur);
|
| | | }
|
| | |
|
| | | //---
|
| | | 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))
|
| | | {
|
| | | case TSN_SBL_BASE_TYPE_INT:
|
| | | return m_ctx.m_cinta[m_idx + 1];
|
| | | 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-07-26 16:46:05 -05:00 | | | un.long_value = m_ctx.m_cinta[m_idx + 1];
|
| | | return long(un.double_value);
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | case TSN_SBL_BASE_TYPE_BOL:
|
| | | return long((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
| | | case TSN_SBL_BASE_TYPE_STR:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return long(CharArrayToString(m_ctx.m_raw, start, slen));
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | }
|
| | | return def;
|
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))
|
| | | {
|
| | | case TSN_SBL_BASE_TYPE_INT:
|
| | | val = m_ctx.m_cinta[m_idx + 1];
|
| | | 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-07-26 16:46:05 -05:00 | | | un.long_value = m_ctx.m_cinta[m_idx + 1];
|
| | | val = long(un.double_value);
|
| | | return true;
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | case TSN_SBL_BASE_TYPE_BOL:
|
| | | val = long((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
| | | return true;
|
| | | case TSN_SBL_BASE_TYPE_STR:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | val = long(CharArrayToString(m_ctx.m_raw, start, slen));
|
| | | return true;
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | }
|
| | |
|
| | | return false;
|
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))
|
| | | {
|
| | | case TSN_SBL_BASE_TYPE_INT:
|
| | | return double(m_ctx.m_cinta[m_idx + 1]);
|
| | | 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-07-26 16:46:05 -05:00 | | | un.long_value = m_ctx.m_cinta[m_idx + 1];
|
| | | return un.double_value;
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | case TSN_SBL_BASE_TYPE_BOL:
|
| | | return double((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
| | | case TSN_SBL_BASE_TYPE_STR:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | return double(CharArrayToString(m_ctx.m_raw, start, slen));
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | }
|
2026-06-02 22:52:39 -05:00 | | |
|
2026-07-19 07:41:52 -05:00 | | | return def;
|
2026-06-02 22:52:39 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-07-19 07:41:52 -05:00 | | | bool CJsonNode::ToDoubleSafe(double & val) const
|
2026-06-02 22:52:39 -05:00 | | | {
|
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 false;
|
| | |
|
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))
|
| | | {
|
| | | case TSN_SBL_BASE_TYPE_INT:
|
| | | val = double(m_ctx.m_cinta[m_idx + 1]);
|
| | | 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-07-26 16:46:05 -05:00 | | | un.long_value = m_ctx.m_cinta[m_idx + 1];
|
| | | val = un.double_value;
|
| | | return true;
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | case TSN_SBL_BASE_TYPE_BOL:
|
| | | val = double((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
| | | return true;
|
| | | case TSN_SBL_BASE_TYPE_STR:
|
2026-07-26 16:46:05 -05:00 | | | {
|
| | | const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | val = double(CharArrayToString(m_ctx.m_raw, start, slen));
|
| | | return true;
|
| | | }
|
2026-07-19 07:41:52 -05:00 | | | }
|
2026-06-21 20:08:59 -05:00 | | |
|
2026-07-19 07:41:52 -05:00 | | | return false;
|
| | | }
|
2026-06-21 20:08:59 -05:00 | | |
|
2026-07-19 07:41:52 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| 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;
|
2026-06-02 22:52:39 -05:00 | | | }
|
2026-06-02 21:23:50 -05:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
2026-06-02 22:52:39 -05:00 | | | #endif // JSONPARSERBYLEO_SRC_JSONNODE_MQH
|