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-06-03 14:16:03 -05:00
|
|
|
#include "JsonBuilder.mqh"
|
2026-07-13 18:47:16 -05:00
|
|
|
#include "JsonStrBuilder.mqh"
|
2026-07-19 07:41:52 -05:00
|
|
|
#include <TSN\\BSFL\\Node.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-06-26 17:53:09 -05:00
|
|
|
//---
|
2026-06-02 22:52:39 -05:00
|
|
|
struct CJsonIteratorArray;
|
|
|
|
|
struct CJsonIteratorObj;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-19 07:41:52 -05:00
|
|
|
struct CJsonNode : CNodeSFLBase<CJsonParser>
|
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-19 07:41:52 -05:00
|
|
|
: CNodeSFLBase<CJsonParser>(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-19 07:41:52 -05:00
|
|
|
: CNodeSFLBase<CJsonParser>(_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-19 07:41:52 -05:00
|
|
|
: CNodeSFLBase<CJsonParser>(_ctx, _idx, _idx + _ctx.GetStep(_idx), NODEBASEF_RES_BASE(_ctx, _idx)) {}
|
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-06-21 12:25:55 -05:00
|
|
|
CJsonNode At(const int index) const;
|
2026-06-02 22:52:39 -05:00
|
|
|
CJsonNode AtHomegeneo(const int index) const;
|
2026-06-23 08:02:37 -05:00
|
|
|
CJsonNode AtObj(const int index) const; // Obtiene el valor...
|
2026-06-02 22:52:39 -05:00
|
|
|
|
2026-06-23 08:02:37 -05:00
|
|
|
//--- Keys
|
2026-06-02 22:52:39 -05:00
|
|
|
string AtObjKey(const int index) const;
|
|
|
|
|
string AtObjKeyHomogeneo(const int index) const;
|
2026-06-21 20:08:59 -05:00
|
|
|
int KeyToPosition(const string& key) const;
|
|
|
|
|
int GetKeys(string& out[]) const;
|
2026-06-23 08:02:37 -05:00
|
|
|
bool HasKey(const string& key) const;
|
|
|
|
|
|
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>
|
|
|
|
|
bool ExistInArrayHomogeneo(const T val) const;
|
|
|
|
|
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-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-06-03 12:20:23 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
__forceinline ENUM_JSON_VTYPE GetType() const { return ENUM_JSON_VTYPE(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE);}
|
2026-06-30 08:24:44 -05:00
|
|
|
|
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
|
|
|
|
|
|
|
|
//--- Iteradores
|
|
|
|
|
CJsonIteratorArray BeginArr() const;
|
|
|
|
|
CJsonIteratorObj BeginObj() const;
|
|
|
|
|
|
|
|
|
|
//--- Navegacion raw
|
|
|
|
|
CJsonNode MoveNextPositions(const int posiciones, const bool solo_en_el_bloque_actual = true);
|
2026-06-02 21:23:50 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const CJsonNode EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
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-06-02 22:52:39 -05:00
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//--- 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);
|
|
|
|
|
if(c >= TSN_JSON_JIT_MIN_REF_TO_HASING) // 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)
|
|
|
|
|
{
|
|
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
if(m_ctx.StrEquals(key, cur))
|
|
|
|
|
{
|
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
|
|
|
|
|
}
|
|
|
|
|
return EMPTY_JSON_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)
|
|
|
|
|
{
|
|
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
}
|
|
|
|
|
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-23 08:02:37 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CJsonNode::HasKey(const string &key) 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_OBJ)
|
2026-06-23 08:02:37 -05:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//--- Iterar pares KEY+VAL
|
2026-07-19 07:41:52 -05:00
|
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&B'1')==0)
|
2026-06-23 08:02:37 -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-23 08:02:37 -05:00
|
|
|
{
|
|
|
|
|
cur += m_ctx.GetStep(cur);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(m_ctx.StrEquals(key, cur))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur++; // salta KEY
|
|
|
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-24 17:20:42 -05:00
|
|
|
return m_ctx.PerfectHashComputeHash(key, m_node_pos) != -1;
|
2026-06-23 08:02:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-06-20 18:08:19 -05:00
|
|
|
|
2026-06-02 22:52:39 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| At — acceso por indice en ARR |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-21 12:25:55 -05:00
|
|
|
CJsonNode CJsonNode::At(const int index) const
|
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_ARR)
|
2026-06-02 22:52:39 -05:00
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-03 15:48:09 -05:00
|
|
|
int cur = m_idx + 2;
|
2026-06-02 22:52:39 -05:00
|
|
|
for(int k = 0; k < index; k++)
|
|
|
|
|
cur += m_ctx.GetStep(cur);
|
|
|
|
|
|
|
|
|
|
return CJsonNode(m_ctx, cur, cur + m_ctx.GetStep(cur));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| AtHomegeneo — acceso por indice en ARR con step fijo |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonNode CJsonNode::AtHomegeneo(const int index) 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-02 22:52:39 -05:00
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-03 15:48:09 -05:00
|
|
|
const int first = m_idx + 2;
|
|
|
|
|
const int step = m_ctx.GetStep(first);
|
|
|
|
|
const int cur = first + index * step;
|
2026-06-02 22:52:39 -05:00
|
|
|
return CJsonNode(m_ctx, cur, cur + step);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-23 08:02:37 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonNode CJsonNode::AtObj(const int index) 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_OBJ)
|
2026-06-23 08:02:37 -05:00
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int cur = 0;
|
2026-07-19 07:41:52 -05:00
|
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & 1) != 0)
|
2026-06-23 08:02:37 -05:00
|
|
|
{
|
|
|
|
|
cur = m_ctx.m_tables[m_node_pos].pos_arr[index] + 1;// Ahora mismo apunta a key saltos al valor..
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cur = m_idx + 2;
|
|
|
|
|
// Ahora mismo apunta a key..
|
|
|
|
|
for(int k = 0; k < index; k++)
|
|
|
|
|
{
|
|
|
|
|
cur++; // Salta key
|
|
|
|
|
cur += m_ctx.GetStep(cur);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return CJsonNode(m_ctx, cur, cur + m_ctx.GetStep(cur));
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-02 22:52:39 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| AtObjKey — key string del par en posicion index dentro de OBJ |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
string CJsonNode::AtObjKey(const int index) 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_OBJ)
|
2026-06-02 22:52:39 -05:00
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-21 20:08:59 -05:00
|
|
|
int cur = 0;
|
2026-07-19 07:41:52 -05:00
|
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & 1) != 0)
|
2026-06-02 22:52:39 -05:00
|
|
|
{
|
2026-06-21 20:08:59 -05:00
|
|
|
//--- Objeto ya hasheado, m_node_pos ya viene resuelto desde el constructor.
|
|
|
|
|
// Usamos pos_arr en vez de recorrer linealmente (esta funcion no fuerza el JIT, solo lo aprovecha).
|
|
|
|
|
cur = m_ctx.m_tables[m_node_pos].pos_arr[index];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cur = m_idx + 2;
|
|
|
|
|
for(int k = 0; k < index; k++)
|
|
|
|
|
{
|
|
|
|
|
cur++; // salta KEY (1 pos)
|
|
|
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
|
|
|
}
|
2026-06-02 22:52:39 -05:00
|
|
|
}
|
|
|
|
|
|
2026-07-19 07:41:52 -05:00
|
|
|
//--- TSN_SBL_BIT_STR_MASK_LEN
|
2026-06-20 17:29:49 -05:00
|
|
|
// KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
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);
|
|
|
|
|
return CharArrayToString(m_ctx.m_raw, start, slen);
|
2026-06-02 22:52:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| AtObjKeyHomogeneo — igual pero asume step fijo del VAL |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
string CJsonNode::AtObjKeyHomogeneo(const int index) 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_OBJ)
|
2026-06-02 22:52:39 -05:00
|
|
|
return "";
|
|
|
|
|
|
2026-06-20 17:29:49 -05:00
|
|
|
//--- step fijo = 1(KEY) + step(primer VAL)
|
|
|
|
|
const int first_val = m_idx + 3;
|
2026-06-02 22:52:39 -05:00
|
|
|
const int val_step = m_ctx.GetStep(first_val);
|
2026-06-21 20:08:59 -05:00
|
|
|
const int pair_step = 1 + val_step; // key+val
|
2026-06-03 15:48:09 -05:00
|
|
|
const int key_pos = (m_idx + 2) + index * pair_step;
|
2026-06-02 22:52:39 -05:00
|
|
|
|
2026-06-20 17:29:49 -05:00
|
|
|
//--- KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
2026-07-19 07:41:52 -05:00
|
|
|
const int start = int(m_ctx.m_cinta[key_pos] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int slen = int((m_ctx.m_cinta[key_pos] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
|
|
|
return CharArrayToString(m_ctx.m_raw, start, slen);
|
2026-06-02 22:52:39 -05:00
|
|
|
}
|
|
|
|
|
|
2026-06-21 20:08:59 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| KeyToPosition — indice posicional de una key dentro del objeto |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int CJsonNode::KeyToPosition(const string &key) 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_OBJ)
|
2026-06-21 20:08:59 -05:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & 1) != 0)
|
2026-06-21 20:08:59 -05:00
|
|
|
{
|
|
|
|
|
//--- Ya hasheado, m_node_pos ya viene resuelto desde el constructor
|
2026-06-24 17:20:42 -05:00
|
|
|
return m_ctx.PerfectHashComputeHashIndex(key, m_node_pos);
|
2026-06-21 20:08:59 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int cur = m_idx + 2;
|
|
|
|
|
int k = 0;
|
|
|
|
|
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-21 20:08:59 -05:00
|
|
|
{
|
|
|
|
|
cur += m_ctx.GetStep(cur);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(m_ctx.StrEquals(key, cur))
|
|
|
|
|
return k;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur++; // salta KEY
|
|
|
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
|
|
|
k++;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| GetKeys — vacia todas las keys del objeto a un array de strings |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int CJsonNode::GetKeys(string &out[]) 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_OBJ)
|
2026-06-21 20:08:59 -05:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & 1) != 0)
|
2026-06-21 20:08:59 -05:00
|
|
|
{
|
|
|
|
|
//--- Ya hasheado, m_node_pos ya viene resuelto desde el constructor
|
|
|
|
|
const int count = m_ctx.m_tables[m_node_pos].table_size;
|
|
|
|
|
ArrayResize(out, count);
|
|
|
|
|
for(int i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
const int cur = m_ctx.m_tables[m_node_pos].pos_arr[i];
|
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);
|
|
|
|
|
out[i] = CharArrayToString(m_ctx.m_raw, start, slen);
|
2026-06-21 20:08:59 -05:00
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//---
|
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, count);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int i = 0;
|
|
|
|
|
int cur = m_idx + 2;
|
|
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
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);
|
|
|
|
|
out[i++] = CharArrayToString(m_ctx.m_raw, start, slen);
|
2026-06-21 20:08:59 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur++; // salta KEY
|
|
|
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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-06-23 08:02:37 -05:00
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
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-06-23 08:02:37 -05:00
|
|
|
{
|
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);
|
|
|
|
|
}
|
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-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-06-23 08:02:37 -05:00
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
|
|
|
|
out_arr[k++] = T(m_ctx.m_cinta[cur + 1]);
|
|
|
|
|
cur += 2;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
2026-06-21 20:08:59 -05:00
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_REAL:
|
|
|
|
|
{
|
2026-06-23 08:02:37 -05:00
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter bit;
|
|
|
|
|
bit.long_value = m_ctx.m_cinta[cur + 1];
|
|
|
|
|
out_arr[k++] = T(bit.double_value);
|
|
|
|
|
cur += 2;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
2026-06-21 20:08:59 -05:00
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_BOOLEAN:
|
|
|
|
|
{
|
2026-06-23 08:02:37 -05:00
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
out_arr[k++] = T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
2026-06-23 08:02:37 -05:00
|
|
|
cur++;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
2026-06-21 20:08:59 -05:00
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_STRING:
|
|
|
|
|
{
|
2026-06-23 08:02:37 -05:00
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
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
|
|
|
out_arr[k++] = T(m_ctx.Unescape(start, start + slen - 1));
|
|
|
|
|
cur++;
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
if(m_ctx.m_cinta[cur + 1] == T(val))
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_REAL:
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
bit.long_value = m_ctx.m_cinta[cur + 1];
|
2026-06-23 08:02:37 -05:00
|
|
|
if(bit.double_value == T(val))
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_BOOLEAN:
|
|
|
|
|
{
|
|
|
|
|
if(val == T((m_ctx.m_cinta[cur] >> TSN_JSON_BIT_START_ENDTYPE) & 1))
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_STRING:
|
|
|
|
|
{
|
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 == T(m_ctx.Unescape(start, start + slen - 1)))
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_NULL:
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool CJsonNode::ExistInArrayHomogeneo(const T 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;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
switch(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
|
2026-06-23 08:02:37 -05:00
|
|
|
{
|
|
|
|
|
case JSON_VTYPE_INTEGER:
|
|
|
|
|
{
|
|
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
|
|
|
|
if(val == T(m_ctx.m_cinta[cur + 1]))
|
|
|
|
|
return true;
|
|
|
|
|
cur += 2;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case JSON_VTYPE_REAL:
|
|
|
|
|
{
|
|
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter bit;
|
|
|
|
|
bit.long_value = m_ctx.m_cinta[cur + 1];
|
|
|
|
|
if(val == T(bit.double_value))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur += 2;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_BOOLEAN:
|
|
|
|
|
{
|
|
|
|
|
while(cur < m_end)
|
|
|
|
|
{
|
|
|
|
|
if(val == T((m_ctx.m_cinta[cur] >> TSN_JSON_BIT_START_ENDTYPE) & 1))
|
|
|
|
|
return true;
|
|
|
|
|
cur++;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_value = m_ctx.m_cinta[m_idx + 1];
|
|
|
|
|
return long(un.double_value);
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_value = m_ctx.m_cinta[m_idx + 1];
|
|
|
|
|
val = long(un.double_value);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_value = m_ctx.m_cinta[m_idx + 1];
|
|
|
|
|
return un.double_value;
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
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-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:
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_value = m_ctx.m_cinta[m_idx + 1];
|
|
|
|
|
val = un.double_value;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
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-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-07-19 07:41:52 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Navegacion raw |
|
2026-06-02 22:52:39 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonNode CJsonNode::MoveNextPositions(const int posiciones, const bool solo_en_el_bloque_actual = true)
|
|
|
|
|
{
|
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 EMPTY_JSON_NODE;
|
|
|
|
|
|
2026-06-02 22:52:39 -05:00
|
|
|
//---
|
|
|
|
|
const int next_pos = m_idx + posiciones;
|
|
|
|
|
const int final_pos = solo_en_el_bloque_actual ? m_end : next_pos + m_ctx.GetStep(next_pos);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
|
|
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return CJsonNode(m_ctx, next_pos, final_pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Iterador de arrays |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
struct CJsonIteratorArray
|
|
|
|
|
{
|
2026-06-23 08:02:37 -05:00
|
|
|
CJsonParser* const m_ctx;
|
2026-06-02 22:52:39 -05:00
|
|
|
int m_cur;
|
|
|
|
|
const int m_end;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
CJsonIteratorArray(CJsonParser* ctx, const int cur, const int end)
|
|
|
|
|
: m_ctx(ctx), m_cur(cur), m_end(end) {}
|
|
|
|
|
//---
|
|
|
|
|
CJsonIteratorArray()
|
|
|
|
|
: m_ctx(NULL), m_cur(0), m_end(0) {}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline bool IsValid() { return m_cur < m_end; }
|
2026-06-23 08:02:37 -05:00
|
|
|
__forceinline void Kill() { m_cur = m_end; }
|
2026-06-02 22:52:39 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void Next()
|
|
|
|
|
{
|
|
|
|
|
if(m_cur >= m_end)
|
|
|
|
|
return;
|
|
|
|
|
m_cur += m_ctx.GetStep(m_cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
CJsonNode Val()
|
|
|
|
|
{
|
|
|
|
|
if(m_cur >= m_end)
|
|
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
const int fin = m_cur + m_ctx.GetStep(m_cur);
|
|
|
|
|
return CJsonNode(m_ctx, m_cur, fin);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const CJsonIteratorArray EMPTY_JSON_ITERATOR_ARR;
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Iterador de objetos |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
struct CJsonIteratorObj
|
|
|
|
|
{
|
2026-06-23 08:02:37 -05:00
|
|
|
CJsonParser* const m_ctx;
|
2026-06-02 22:52:39 -05:00
|
|
|
int m_cur;
|
|
|
|
|
const int m_end;
|
|
|
|
|
|
2026-06-23 08:02:37 -05:00
|
|
|
|
2026-06-02 22:52:39 -05:00
|
|
|
//---
|
|
|
|
|
CJsonIteratorObj(CJsonParser* ctx, const int cur, const int end)
|
|
|
|
|
: m_ctx(ctx), m_cur(cur), m_end(end) {}
|
|
|
|
|
//---
|
|
|
|
|
CJsonIteratorObj()
|
|
|
|
|
: m_ctx(NULL), m_cur(0), m_end(0) {}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline bool IsValid() { return m_cur < m_end; }
|
2026-06-23 08:02:37 -05:00
|
|
|
__forceinline void Kill() { m_cur = m_end; }
|
2026-06-02 22:52:39 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void Next()
|
|
|
|
|
{
|
|
|
|
|
if(m_cur >= m_end)
|
|
|
|
|
return;
|
2026-06-20 17:29:49 -05:00
|
|
|
m_cur++; // salta KEY (2 pos)
|
2026-06-02 22:52:39 -05:00
|
|
|
m_cur += m_ctx.GetStep(m_cur); // salta VAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
string Key()
|
|
|
|
|
{
|
|
|
|
|
if(m_cur >= m_end)
|
|
|
|
|
return "";
|
2026-06-20 17:29:49 -05:00
|
|
|
//--- KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
2026-07-19 07:41:52 -05:00
|
|
|
const int s = int(m_ctx.m_cinta[m_cur] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int slen = int((m_ctx.m_cinta[m_cur] >> TSN_SBL_BIT_STR_LEN) & 0xFFFFFFF);
|
|
|
|
|
return CharArrayToString(m_ctx.m_raw, s, slen);
|
2026-06-02 22:52:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
CJsonNode Val()
|
|
|
|
|
{
|
|
|
|
|
if(m_cur >= m_end)
|
|
|
|
|
return EMPTY_JSON_NODE;
|
2026-06-20 17:29:49 -05:00
|
|
|
const int pos = m_cur + 1;
|
2026-06-02 22:52:39 -05:00
|
|
|
const int fin = pos + m_ctx.GetStep(pos);
|
|
|
|
|
return CJsonNode(m_ctx, pos, fin);
|
|
|
|
|
}
|
|
|
|
|
};
|
2026-06-26 17:53:09 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-02 22:52:39 -05:00
|
|
|
const CJsonIteratorObj EMPTY_JSON_ITERATOR_OBJ;
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| BeginArr / BeginObj |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonIteratorArray CJsonNode::BeginArr() const
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
if(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_ARR)
|
2026-06-02 22:52:39 -05:00
|
|
|
return EMPTY_JSON_ITERATOR_ARR;
|
2026-06-03 15:48:09 -05:00
|
|
|
return CJsonIteratorArray(m_ctx, m_idx + 2, m_end);
|
2026-06-02 22:52:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonIteratorObj CJsonNode::BeginObj() const
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
if(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_OBJ)
|
2026-06-02 22:52:39 -05:00
|
|
|
return EMPTY_JSON_ITERATOR_OBJ;
|
2026-06-03 15:48:09 -05:00
|
|
|
return CJsonIteratorObj(m_ctx, m_idx + 2, m_end);
|
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
|