764 lines
24 KiB
MQL5
764 lines
24 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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_MQH
| |
#define JSONPARSERBYLEO_SRC_JSONNODE_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "JsonAsm.mqh"
| |
#include "JsonDomSerializer.mqh"
| |
| |
//---
| |
#include <TSN\\MQLArticles\\Utils\\EnumReg.mqh>
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
namespace TSN
| |
{
| |
// Layour de los demas en repo base
| |
// Layout cinta:
| |
// NULL 1 pos [tipo(4)]
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#define CJsonIteratorArray TSN::CNodeBaseIteradorArray<TSN::CJsonParser, TSN::CJsonNode>
| |
#define CJsonIteratorArrayFast TSN::CNodeBaseIteradorArrayFast<TSN::CJsonParser, TSN::CJsonNode>
| |
#define CJsonIteratorObj TSN::CNodeBaseIteratorObj<TSN::CJsonParser, TSN::CJsonNode>
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
struct CJsonNode : CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>
| |
{
| |
public:
| |
//---
| |
CJsonNode()
| |
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(NULL, -1, -1, -1) {}
| |
//--- Resuelve m_node_pos una unica vez aqui (igual que YML_NODE_RPOS en YAML)
| |
CJsonNode(CJsonParser* _ctx, const int _idx, const int _end)
| |
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _end, NODEBASEF_RES_BASE(_ctx, _idx)) {}
| |
| |
CJsonNode(CJsonParser* _ctx, const int _idx)
| |
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _idx + _ctx.GetStep(_idx), NODEBASEF_RES_BASE(_ctx, _idx)) {}
| |
| |
// Exclusivo de copia (Aqui NO RESUELVE NADA NI GET STE NI NADA) (constructor de clonacion)
| |
CJsonNode(CJsonParser* _ctx, const int _idx, const int _end, const int _node_pos)
| |
: CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>(_ctx, _idx, _end, _node_pos) {}
| |
| |
| |
//--- Acceso
| |
CJsonNode operator[](const string& key);
| |
//CJsonNode At(const int index) const;
| |
| |
| |
//--- Array
| |
template <typename T>
| |
int ToArray(T& out_arr[]) const;
| |
// Exist?
| |
template <typename T>
| |
bool ExistInArray(const uint flags, const T val) const;
| |
bool ExistInArrayStr(const string& val) const;
| |
| |
//--- String
| |
string ToString(const string def = "") const;
| |
int ToStringUArray(uchar& data[]) const;
| |
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.
| |
| |
//-- to bytes (asume hex string)
| |
int HexToBytes(uchar& buf[]) const;
| |
| |
// Interpolacion
| |
template <typename TInterpolate>
| |
string Interpolate(const TInterpolate& cs, const string def) const;
| |
| |
//---
| |
string ComplexToString(bool clean) const;
| |
int ComplexToData(uchar& data[], bool clean, int dst_start = 0, bool ajustar_arr = true) const;
| |
| |
//--- Int
| |
long ToInt(const long def) const;
| |
bool ToIntSafe(long& val) const;
| |
| |
//--- Double
| |
double ToDouble(const double def) const;
| |
bool ToDoubleSafe(double& val) const;
| |
| |
//--- MqlParam
| |
bool ToMqlParam(MqlParam& param, const string stype) const;
| |
bool ToMqlParam(MqlParam& param, const ENUM_DATATYPE type) const;
| |
| |
| |
//--- Is
| |
__forceinline bool IsNull() const;
| |
| |
//--- Navegacion raw
| |
static const CJsonNode EMPTY_NODE;
| |
static void OnMute(CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode>& node);
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
const CJsonNode CJsonNode::EMPTY_NODE;
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
static void CJsonNode::OnMute(CNodeSFLBase<CJsonParser, ENUM_JSON_VTYPE, CJsonNode> &node)
| |
{
| |
node.RecalcNodePos(); // Posicion...
| |
node.m_end = node.m_idx + node.m_ctx.GetStep(node.m_idx); // Calculamos el fin...
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| To MqlParam |
| |
//+------------------------------------------------------------------+
| |
__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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
string CJsonNode::ComplexToString(bool clean) const
| |
{
| |
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)
| |
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);
| |
return clean ? m_ctx.CleanNode(start, end) : CharArrayToString(m_ctx.m_raw, start, (end - start) + 1);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
int CJsonNode::ComplexToData(uchar &data[], bool clean, int dst_start = 0, bool ajustar_arr = true) const
| |
{
| |
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)
| |
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);
| |
return clean ? m_ctx.CleanNode(start, end, data, dst_start, ajustar_arr) :
| |
ArrayCopy(data, m_ctx.m_raw, dst_start, start, (end - start) + 1);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
CJsonNode CJsonNode::operator[](const string& key)
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_OBJ)
| |
return EMPTY_NODE;
| |
| |
//--- Iterar pares KEY+VAL
| |
// Print("Call");
| |
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & TSN_SBL_BIT_MASK_IS_HASHSING) == 0)
| |
{
| |
//Print("No esta hasheado buscando o(n)");
| |
//---
| |
int c = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_C_HASH) & TSN_SBL_BIT_MASK_NUM_C_HASH;
| |
//Print("Contador actual: ", c);
| |
if(c >= TSN_NODEBASEREAD_MIN_JIT_ATTEMPS_TO_PHASH) // Veriricamos si supero
| |
{
| |
if(NodeHashing())
| |
{
| |
//Print("Hasheado");
| |
//--- Obtenemos posicion
| |
int val_pos = m_ctx.PerfectHashComputeHash(key, m_node_pos);
| |
if(val_pos == -1)
| |
{
| |
return EMPTY_NODE;
| |
}
| |
else
| |
{
| |
val_pos++; // Luego de key
| |
return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
| |
}
| |
}
| |
//Print("No se pudo hashear");
| |
// Si llega aqui es por que fallo.. en ese caso reiniciamos los intetnos..
| |
| |
//---
| |
c = 0;
| |
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);
| |
}
| |
else
| |
{
| |
// Aun no.. solo aumentamos y modificamos..
| |
c++;
| |
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);
| |
}
| |
| |
//--- Linear probing.. de siempre...
| |
int cur = m_idx + 2;
| |
while(cur < m_end)
| |
{
| |
if(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_KEY)
| |
{
| |
cur += m_ctx.GetStep(cur);
| |
continue;
| |
}
| |
if(m_ctx.KeysEqual(key, cur))
| |
{
| |
const int val_pos = cur + 1;
| |
return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
| |
}
| |
| |
//---
| |
cur++; // salta KEY
| |
cur += m_ctx.GetStep(cur); // salta VAL
| |
}
| |
return EMPTY_NODE;
| |
}
| |
| |
//--- m_node_pos ya viene resuelto desde el constructor
| |
int val_pos = m_ctx.PerfectHashComputeHash(key, m_node_pos);
| |
if(val_pos == -1)
| |
{
| |
return EMPTY_NODE;
| |
}
| |
else
| |
{
| |
val_pos++; // Luego de key
| |
return CJsonNode(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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_INTEGER:
| |
return string(m_ctx.m_cinta[m_idx + 1]);
| |
case JSON_VTYPE_REAL:
| |
{
| |
TsnBitInterprete un;
| |
un.long_value = m_ctx.m_cinta[m_idx + 1];
| |
return string(un.double_value);
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
return ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & 1) != 0 ? "true" : "false";
| |
case JSON_VTYPE_STRING:
| |
{
| |
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);
| |
}
| |
}
| |
| |
return def;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename TInterpolate>
| |
string CJsonNode::Interpolate(const TInterpolate& cs, const string def) const
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
| |
return def;
| |
| |
//---
| |
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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
string CJsonNode::ToStringNoEscape(const string def = "") const
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
| |
return def;
| |
| |
//---
| |
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);
| |
| |
//---
| |
return def;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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 0;
| |
| |
//---
| |
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, data);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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 0;
| |
| |
//---
| |
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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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 int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
__forceinline bool CJsonNode::CompareStrWith(const string &str) const
| |
{
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_STRING)
| |
return false;
| |
return m_ctx.StrEquals(str, m_idx);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
ArrayResize(buf, (slen >> 1) + sob);
| |
int w = 0;
| |
| |
//---
| |
exact_len += start; // para que peuda empzar bien..
| |
int i = start;
| |
| |
//---
| |
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]];
| |
| |
//---
| |
return w;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Arrays |
| |
//+------------------------------------------------------------------+
| |
template <typename T>
| |
int CJsonNode::ToArray(T &out_arr[]) const
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_ARR)
| |
return 0;
| |
| |
//---
| |
const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
| |
ArrayResize(out_arr, count);
| |
| |
//---
| |
int cur = m_idx + 2;
| |
int k = 0;
| |
| |
//---
| |
switch(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
| |
{
| |
case JSON_VTYPE_INTEGER:
| |
{
| |
while(cur < m_end)
| |
{
| |
out_arr[k++] = T(m_ctx.m_cinta[cur + 1]);
| |
cur += 2;
| |
}
| |
return count;
| |
}
| |
case JSON_VTYPE_REAL:
| |
{
| |
while(cur < m_end)
| |
{
| |
TsnBitInterprete bit;
| |
bit.long_value = m_ctx.m_cinta[cur + 1];
| |
out_arr[k++] = T(bit.double_value);
| |
cur += 2;
| |
}
| |
return count;
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
{
| |
while(cur < m_end)
| |
{
| |
out_arr[k++] = T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
| |
cur++;
| |
}
| |
return count;
| |
}
| |
case JSON_VTYPE_STRING:
| |
{
| |
while(cur < m_end)
| |
{
| |
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++;
| |
}
| |
return count;
| |
}
| |
}
| |
| |
//---
| |
return 0;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename T>
| |
bool CJsonNode::ExistInArray(const uint flags, const T val) const
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_ARR)
| |
return false;
| |
| |
//---
| |
int cur = m_idx + 2;
| |
while(cur < m_end)
| |
{
| |
//---
| |
const uint ct = 1U << uint(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
| |
if((ct & flags) == 0)
| |
{
| |
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:
| |
{
| |
bit.long_value = m_ctx.m_cinta[cur + 1];
| |
if(bit.double_value == T(val))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
{
| |
if(val == T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_STRING:
| |
{
| |
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)))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_NULL:
| |
{
| |
return true;
| |
}
| |
}
| |
| |
//---
| |
cur += m_ctx.GetStep(cur);
| |
}
| |
| |
//---
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonNode::ExistInArrayStr(const string& val) const
| |
{
| |
//---
| |
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_ARR)
| |
return false;
| |
| |
//---
| |
int cur = m_idx + 2;
| |
while(cur < m_end)
| |
{
| |
//---
| |
const int ct = int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
| |
if(ct != JSON_VTYPE_STRING)
| |
{
| |
cur += m_ctx.GetStep(cur);
| |
continue;
| |
}
| |
| |
//---
| |
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 == m_ctx.Unescape(start, start + slen - 1))
| |
return true;
| |
| |
//---
| |
cur += m_ctx.GetStep(cur);
| |
}
| |
| |
//---
| |
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_INT:
| |
return m_ctx.m_cinta[m_idx + 1];
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete 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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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_INT:
| |
val = m_ctx.m_cinta[m_idx + 1];
| |
return true;
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete 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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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_INT:
| |
return double(m_ctx.m_cinta[m_idx + 1]);
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete 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));
| |
}
| |
}
| |
| |
return def;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonNode::ToDoubleSafe(double & 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_INT:
| |
val = double(m_ctx.m_cinta[m_idx + 1]);
| |
return true;
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete 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;
| |
}
| |
}
| |
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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;
| |
}
| |
}
| |
//+------------------------------------------------------------------+
| |
#endif // JSONPARSERBYLEO_SRC_JSONNODE_MQH
|