JsonParserByLeo/Src/JsonCore/JsonParser.mqh
1621 lines
52 KiB
MQL5
Nique_372
2026-07-24 07:27:55 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-06-02 21:23:50 -05:00
//| JsonParser.mqh |
//| Copyright 2026, Niquel Mendoza. |
Nique_372
2026-10-08 13:39:44 -05:00
//| https://www.mql5.com |
Nique_372
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
Nique_372
2026-10-08 13:39:44 -05:00
#property link "https://www.mql5.com"
Nique_372
2026-06-02 21:23:50 -05:00
#property strict
Nique_372
2026-10-08 13:39:44 -05:00
#ifndef JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
#define JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
Nique_372
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-10-03 17:00:34 -05:00
#include "JsonDefines.mqh"
Nique_372
2026-10-27 10:45:12 -05:00
#include "JsonUE.mqh"
Nique_372
2026-06-02 21:23:50 -05:00
Nique_372
2026-08-03 09:31:58 -05:00
//---
#ifdef JSONPARSERBYLEO_DLL
Nique_372
2026-10-19 07:27:55 -05:00
#include "..\\DLL\\Main.mqh"
Nique_372
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-07-19 07:41:52 -05:00
class CJsonParser : public CBaseStructuredLan
Nique_372
2026-06-02 21:23:50 -05:00
{
Nique_372
2026-08-04 08:01:50 -05:00
protected:
Nique_372
2026-06-02 21:23:50 -05:00
//---
Nique_372
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
int m_index[];
int m_index_r;
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-06-02 21:23:50 -05:00
//---
ENUM_TSN_JSON_LAST_ERR m_last_err;
Nique_372
2026-07-19 07:41:52 -05:00
//---
int CalcRegType(const string& file_name) override final;
Nique_372
2026-09-30 07:39:54 -05:00
Nique_372
2026-06-02 21:23:50 -05:00
public:
Nique_372
2026-08-03 09:31:58 -05:00
CJsonParser(void);
Nique_372
2026-06-02 21:23:50 -05:00
~CJsonParser(void) {}
Nique_372
2026-10-08 21:46:49 -05:00
//--- Correct padding
Nique_372
2026-06-03 08:32:38 -05:00
// Para data raw se puede usar el json uchar directamtne
Nique_372
2026-09-18 14:11:09 -05:00
void CorrectPadding();
Nique_372
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
Nique_372
2026-09-18 14:11:09 -05:00
void CorrectPaddingSimd();
Nique_372
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-06-03 07:50:45 -05:00
Nique_372
2026-10-08 21:46:49 -05:00
//--- Parseo
bool AutoParseByFileExt(const int file_ext_type);
Nique_372
2026-06-18 09:48:36 -05:00
bool Parse();
Nique_372
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
Nique_372
2026-09-18 14:11:09 -05:00
__forceinline bool ParseSimd();
Nique_372
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-09-18 14:11:09 -05:00
Nique_372
2026-10-01 08:25:33 -05:00
//--- Errores
Nique_372
2026-06-03 07:50:45 -05:00
__forceinline ENUM_TSN_JSON_LAST_ERR LastErr() const { return m_last_err; }
Nique_372
2026-09-30 07:39:54 -05:00
void CatchErr();
Nique_372
2026-10-03 17:00:34 -05:00
void ErrorInfo(const string header = "");
Nique_372
2026-06-03 07:50:45 -05:00
Nique_372
2026-10-08 21:46:49 -05:00
//--- Config
Nique_372
2026-10-08 13:39:44 -05:00
void Options(const uint f);
Nique_372
2026-10-01 08:25:33 -05:00
//--- Step
Nique_372
2026-06-02 22:52:39 -05:00
__forceinline int GetStep(const int idx) const;
Nique_372
2026-06-03 07:50:45 -05:00
__forceinline int GetStepPure(const int idx) const;
Nique_372
2026-06-03 18:53:05 -05:00
Nique_372
2026-10-08 13:39:44 -05:00
//--- GetRoot
CJsonNode GetRoot();
Nique_372
2026-10-01 08:25:33 -05:00
//--- Info
Nique_372
2026-06-18 08:36:18 -05:00
void PrintCintaTypes(const int start, const int num) const;
Nique_372
2026-06-03 07:50:45 -05:00
Nique_372
2026-10-08 21:46:49 -05:00
//--- Node
Nique_372
2026-10-08 20:25:09 -05:00
void NodeHashing(int curr, const int obj_count, const int bend, int& table_pos);
Nique_372
2026-10-01 08:25:33 -05:00
bool SerializeToDom(CDomNodeBase* root, CDomNodeManager* manager, int cur, const int end);
Nique_372
2026-10-08 21:46:49 -05:00
//--- Strings\Keys
Nique_372
2026-10-06 08:01:09 -05:00
// uso en get value o exatcion
Nique_372
2026-10-08 13:39:44 -05:00
template<typename TKey>
Nique_372
2026-10-08 21:46:49 -05:00
__forceinline string GetRawAsStr(int idx) const
{
return CharArrayToString(m_raw, TSN_SBL_CLS_STR_START(idx, int), TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int));
}
Nique_372
2026-10-08 13:39:44 -05:00
template<typename TKey>
Nique_372
2026-10-08 21:46:49 -05:00
__forceinline int GetRawAsUArr(int idx, uchar &res[], int pos = 0) const
{
return ArrayCopy(res, m_raw, pos, TSN_SBL_CLS_STR_START(idx, int), TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int));
}
Nique_372
2026-10-08 21:07:14 -05:00
template<typename TKey>
Nique_372
2026-10-08 21:46:49 -05:00
__forceinline bool GetStrAsStr(int idx, string &res) const
{
Nique_372
2026-10-27 10:45:12 -05:00
return JSONPBL_MAKESTRING(m_raw,
TSN_SBL_CLS_STR_START(idx, int),
TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int),
res);
Nique_372
2026-10-08 21:46:49 -05:00
}
Nique_372
2026-10-08 21:07:14 -05:00
template<typename TKey>
Nique_372
2026-10-08 21:46:49 -05:00
__forceinline int GetStrAsUArr(int idx, uchar &res[], int pos = 0) const
{
Nique_372
2026-10-27 10:45:12 -05:00
return JSONPBL_MAKEUARR(m_raw,
TSN_SBL_CLS_STR_START(idx, int),
TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int),
res, pos, BSFL_UE_SURROGATES);
Nique_372
2026-10-08 21:46:49 -05:00
}
Nique_372
2026-10-06 08:01:09 -05:00
Nique_372
2026-10-08 20:25:09 -05:00
//--- Funciones para node (interno de uso interno)
Nique_372
2026-09-30 07:39:54 -05:00
template <typename T>
void ToArray(int cur, T& out_arr[], const int end) const;
template <typename T>
bool ExistInArray(int cur, const T val, const uint flags, const int end) const;
template <typename T>
bool ExistInArrayHomogeneo(int cur, const T val, const int end) const;
Nique_372
2026-10-08 13:39:44 -05:00
__forceinline int NodeAt(int cur, const int index) const;
int NodeFindByHashFvn1A64(const ulong kh, int cur, const int end);
__forceinline int NodeObjAtSlow(int cur, const int index) const;
int NodeKeyToPositionSlow(const ulong kh, int cur, const int end);
int NodeGetKeys(int cur, string &keys[], const int end) const;
Nique_372
2026-10-01 08:25:33 -05:00
Nique_372
2026-10-08 21:46:49 -05:00
//--- Print error general
Nique_372
2026-10-03 17:00:34 -05:00
static void PrintError(const string& header, const uchar& buf[], const int len,
int col, int line, ENUM_TSN_JSON_LAST_ERR err, string& salida, bool print = true);
Nique_372
2026-07-26 16:46:05 -05:00
//--- Tablas generales
Nique_372
2026-09-30 07:39:54 -05:00
static const string s_dtype_to_str[JSON_VTYPE_TOTAL];
Nique_372
2026-10-08 13:39:44 -05:00
static string s_str;
Nique_372
2026-07-26 16:46:05 -05:00
};
Nique_372
2026-08-03 09:31:58 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonParser::CJsonParser(void)
{
Nique_372
2026-10-19 13:26:09 -05:00
m_next = TSN_JSON_TOK_INVALID + 1; // Apunta a un valor invalido
// Estro para que en caso se usa parse simd (no de errores "fantasma" dado que m_next no se usa ahi)
Nique_372
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
m_index_r = ArrayResize(m_index, 256, 256);
#endif // JSONPARSERBYLEO_DLL
}
Nique_372
2026-07-26 16:46:05 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-10-08 13:39:44 -05:00
void CJsonParser::Options(const uint f)
Nique_372
2026-07-26 16:46:05 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
m_jit_enabled = (f & BSFL_OPT_F_ENABLE_JIT) != 0 ? TSN_SBL_BIT_JIT_INITIAL_V : TSN_SBL_BIT_JIT_INV_VAL;
}
Nique_372
2026-09-18 14:11:09 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#ifdef JSONPARSERBYLEO_DLL
void CJsonParser::CorrectPaddingSimd()
{
//---
const int new_len = m_len + 64;
ArrayResize(m_raw, new_len);
//---
int i = m_len;
m_raw[i++] = ' ';
m_raw[i++] = '^'; // para cor ini para que falle bien..
// esto es para el caso de " no cerrado o { asi tal cual.. entonces ahi
// porzariamos a econnotrar un "" el cual ya lo manejaria y seria invalido
m_raw[i++] = '"';
m_raw[i++] = ' ';
m_raw[i++] = '"';
// esto es para el key... los dos primeors eran para que no de fuera de rango en index..
// en caso tengos un { asi tal cual... ecnontrar una key... pero luego le sigue : pero ahora pondmores
// , asi que == ':' fallaria retornando false, lo neceismtos dado que , se procesa como estrucuutra en la dll
m_raw[i++] = ',';
//---
for(; i < new_len; i++)
m_raw[i] = ' '; // vacio
//--- Reservamos
if(m_len > m_cinta_reserve)
{
m_cinta_reserve = m_len;
Nique_372
2026-09-18 14:11:09 -05:00
ArrayResize(m_cinta, m_len);
}
//---
if(m_len > m_index_r)
Nique_372
2026-09-18 14:11:09 -05:00
{
m_index_r = m_len;
Nique_372
2026-09-18 14:11:09 -05:00
ArrayResize(m_index, m_index_r);
}
}
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-10-08 13:39:44 -05:00
// {"a":0}
Nique_372
2026-09-18 14:11:09 -05:00
//+------------------------------------------------------------------+
void CJsonParser::CorrectPadding()
{
//---
Nique_372
2026-09-30 07:39:54 -05:00
//const int new_len = ;
ArrayResize(m_raw, m_len + 11);
Nique_372
2026-09-18 14:11:09 -05:00
//--- Rellenamos
// esto es por el escapado. caso borde donde el json su ultimo char sea \ y avanze ++
// entonces con esto apaleamos eso..
m_raw[m_len] = ' ';
// este caracter es invalido por lo que en casos donde haya [ (sin mas asi tal cual)
// como no tenemos chekeos de rango entonces se tompara con este daond un error de malformacion
m_raw[m_len + 1] = '^';
m_raw[m_len + 2] = '"';
// justo luego 8 caracteres
m_raw[m_len + 3] = '\n'; // en una key invalida cargara a paritr de aqui 7 caracterres mas..
m_raw[m_len + 4] = '"'; // esto para poder encontrar el cierre de key... aparte en asm
// un token " asi suelto no es valido asi que daria error en caso haya un ; asi no mas.. sin \n (lo enocnr)
// igual por el padding pero luego avnazar a " pero este como tal no es token valido
Nique_372
2026-10-03 11:47:17 -05:00
// invalidos para que sigmoas si un valor esta fuera de rango como un string o algo asi
// falle aqui....
m_raw[m_len + 5] = '^'; //
Nique_372
2026-10-02 22:01:54 -05:00
m_raw[m_len + 6] = '^';
m_raw[m_len + 7] = '^';
m_raw[m_len + 8] = '^';
m_raw[m_len + 9] = '^';
m_raw[m_len + 10] = '^';
Nique_372
2026-09-18 14:11:09 -05:00
//--- Reservamos
if(m_len > m_cinta_reserve)
{
m_cinta_reserve = m_len;
ArrayResize(m_cinta, m_len);
}
}
Nique_372
2026-06-20 13:57:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-10-08 13:39:44 -05:00
// ponemos el jit attemp en vlao rinvalido, y table size le hacemos un pop..
#define BASESPARSERSAN_NODEHASHING_FINISH_ERR \
m_cinta[lock] = TSN_SBL_BIT_JIT_INV_VAL; \
m_tables_size--;
//---
Nique_372
2026-10-08 20:25:09 -05:00
void CJsonParser::NodeHashing(int curr, const int obj_count, const int bend, int& table_pos)
Nique_372
2026-06-20 13:57:50 -05:00
{
Nique_372
2026-09-23 15:25:08 -05:00
//--- inicial
BASESPARSERSLAN_START_NODE_HASH(table_pos, curr)
Nique_372
2026-06-20 13:57:50 -05:00
//---
m_tables[table_pos].table_size = obj_count; // Numero de objetos
Nique_372
2026-10-08 13:39:44 -05:00
//--- 4 siempre dado que menos no se permite..
Nique_372
2026-06-28 18:47:50 -05:00
m_pfh.MaxValSeed(m_max_att++);
Nique_372
2026-10-08 13:39:44 -05:00
m_pfh.InitAlg(obj_count, 0.70, 4);
Nique_372
2026-06-20 13:57:50 -05:00
//---
Nique_372
2026-06-21 20:08:59 -05:00
ArrayResize(m_tables[table_pos].pos_arr, obj_count);
Nique_372
2026-06-20 13:57:50 -05:00
//--- Obtnemos las posiciones de incio
Nique_372
2026-06-24 17:20:42 -05:00
ulong keys_h[];
Nique_372
2026-06-28 18:47:50 -05:00
int posiciones[];
Nique_372
2026-06-24 17:20:42 -05:00
ArrayResize(keys_h, obj_count);
Nique_372
2026-06-28 18:47:50 -05:00
ArrayResize(posiciones, obj_count);
Nique_372
2026-06-24 17:20:42 -05:00
int pos_c = 0;
Nique_372
2026-10-08 13:39:44 -05:00
const int lock = curr + 1;
curr += TSN_SBL_SLOT_OBJ_SIZE; // Ahora en key
Nique_372
2026-06-24 17:20:42 -05:00
//---
Nique_372
2026-06-20 13:57:50 -05:00
while(curr < bend)
{
//---
Nique_372
2026-06-24 17:20:42 -05:00
m_tables[table_pos].pos_arr[pos_c] = curr; // Assing
Nique_372
2026-06-20 13:57:50 -05:00
//---
Nique_372
2026-10-08 13:39:44 -05:00
const ulong v = m_cinta[curr];
ulong hash;
if(TSN_SBL_KEY_HAS_ISN_HASH(v)) // no tiene hash
Nique_372
2026-06-24 17:20:42 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
int i = int(v >> TSN_SBL_BIT_STR_START);
Nique_372
2026-10-27 10:45:12 -05:00
if(!JSONPBL_MAKEHASH(m_raw, i, m_len, hash))
Nique_372
2026-10-08 13:39:44 -05:00
{
BASESPARSERSAN_NODEHASHING_FINISH_ERR
Nique_372
2026-10-08 20:25:09 -05:00
return;
Nique_372
2026-10-08 13:39:44 -05:00
}
m_cinta[curr] |= TSN_SBL_KEY_FLAG_HASH; // lo ponemos como valido...
m_cinta[curr + TSN_SBL_KEY_OFF_HASH] = hash; // para reproducibildiad
Nique_372
2026-06-24 17:20:42 -05:00
}
Nique_372
2026-10-08 13:39:44 -05:00
else
hash = m_cinta[curr + TSN_SBL_KEY_OFF_HASH]; // en la siguiente posicion esta el hash lo obtenemos tal cual
Nique_372
2026-06-20 13:57:50 -05:00
Nique_372
2026-06-24 17:20:42 -05:00
//---
Nique_372
2026-10-08 13:39:44 -05:00
keys_h[pos_c] = hash;
Nique_372
2026-06-28 18:47:50 -05:00
posiciones[pos_c] = pos_c;
pos_c++;
Nique_372
2026-06-20 13:57:50 -05:00
//---
Nique_372
2026-10-08 13:39:44 -05:00
curr += TSN_SBL_KEYSLOT_SIZE; // salta KEY
Nique_372
2026-06-24 17:20:42 -05:00
curr += GetStep(curr); // salta VAL
}
Nique_372
2026-06-20 13:57:50 -05:00
Nique_372
2026-10-08 13:39:44 -05:00
//--- assing de tamaños
Nique_372
2026-06-28 18:47:50 -05:00
const int fn = m_pfh.m_final_table_size;
Nique_372
2026-10-08 13:39:44 -05:00
m_tables[table_pos].sizes = BSFL_T_PACK(m_pfh.m_buckets_size_last, m_pfh.m_final_table_size_last);
Nique_372
2026-07-28 21:39:04 -05:00
Nique_372
2026-10-08 13:39:44 -05:00
//--- resize de arrays iniciales
Nique_372
2026-06-28 18:47:50 -05:00
ArrayResize(m_tables[table_pos].pos_index, fn);
ArrayResize(m_tables[table_pos].key_hash, fn);
ArrayInitialize(m_tables[table_pos].key_hash, 0ULL);
Nique_372
2026-06-20 13:57:50 -05:00
//---
if(m_pfh.RunWValue(keys_h, posiciones, m_tables[table_pos].seeds, m_tables[table_pos].pos_index, m_tables[table_pos].key_hash))
Nique_372
2026-10-08 20:25:09 -05:00
return;
//----
Nique_372
2026-10-08 13:39:44 -05:00
BASESPARSERSAN_NODEHASHING_FINISH_ERR
Nique_372
2026-10-08 20:25:09 -05:00
return;
Nique_372
2026-06-20 13:57:50 -05:00
}
Nique_372
2026-06-24 17:20:42 -05:00
Nique_372
2026-07-19 07:41:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CJsonParser::CalcRegType(const string& file_name)
{
return (int)JPBL_HashExt(file_name);
}
Nique_372
2026-06-18 09:48:36 -05:00
Nique_372
2026-06-21 21:51:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CJsonParser::AutoParseByFileExt(const int file_ext_type)
{
switch(file_ext_type)
{
Nique_372
2026-07-19 07:41:52 -05:00
case TSN_SLF_RAW_FILE:
Nique_372
2026-06-21 21:51:52 -05:00
{
Nique_372
2026-07-19 07:41:52 -05:00
CorrectPadding(); // Auto
Nique_372
2026-06-21 21:51:52 -05:00
return Parse();
}
Nique_372
2026-07-19 07:41:52 -05:00
case TSN_SLF_RAW_EMBEBED:
Nique_372
2026-06-21 21:51:52 -05:00
{
Nique_372
2026-07-19 07:41:52 -05:00
return m_cinta_pos > 0 && m_len > 0;
Nique_372
2026-06-21 21:51:52 -05:00
}
default:
{
m_last_err = TSN_JSON_ERR_INVALID_EXT_FILE;
m_pos = 0;
return false;
}
}
}
Nique_372
2026-06-18 09:48:36 -05:00
Nique_372
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-08-02 16:49:10 -05:00
//| Macros de avanze |
Nique_372
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-08 19:54:46 -05:00
//--- para aumtenar el numero de elementos.
#define TSN_JSON_AUMENT curr_count++;
Nique_372
2026-09-30 07:39:54 -05:00
Nique_372
2026-10-02 22:01:54 -05:00
//--- Generico
// Luego de un valor siempre , o su fin
// 1 en la tabl to token es INVALID (dara error..de malformed..)
// Este se usa luego de un valor.. la idea es que luego de un valor "" numero t\f\n ] }
// tiene que haber o un }] o en todo caso , de continuacino solo eso...
#define TSN_JSON_NEXT_NO_NEXT_KEY \
uchar _c = m_raw[m_pos]; \
while(_c < 33) { _c = m_raw[++m_pos]; } \
m_next = g_table_json_tokens[_c]; \
Nique_372
2026-10-18 12:41:33 -05:00
if(((1 << m_next) & curr_state) == 0) \
Nique_372
2026-10-02 22:01:54 -05:00
{ \
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL; \
return false; \
Nique_372
2026-10-03 11:47:17 -05:00
}
Nique_372
2026-10-02 22:01:54 -05:00
Nique_372
2026-06-20 13:57:50 -05:00
//--- Luego de una coma en array
// Luego de una , y KEY siempre siempre valor
Nique_372
2026-09-30 07:39:54 -05:00
#define TSN_JSON_NEXT_VALUE_COMM_KEY \
uchar _c; \
while((_c=m_raw[++m_pos])<33) {} \
m_next = g_table_json_tokens[_c]; \
if(((1 << m_next) & TSN_JSON_F_ALL_I_VAL) == 0) \
{ \
Nique_372
2026-09-18 14:11:09 -05:00
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL; \
Nique_372
2026-09-30 07:39:54 -05:00
return false; \
}
Nique_372
2026-10-08 20:25:09 -05:00
//--- unrolled find key
#define TSN_JSON_FINDKEY_FINAL_U4 \
if(m_raw[m_pos] == '"') \
break; \
m_pos++; \
if(m_raw[m_pos] == '"') \
break; \
m_pos++; \
if(m_raw[m_pos] == '"') \
break; \
m_pos++; \
if(m_raw[m_pos] == '"') \
break; \
m_pos++;
Nique_372
2026-08-03 09:31:58 -05:00
Nique_372
2026-10-17 15:35:59 -05:00
//--- unrooled find normal
#define JSONPARSERBYLEO_FIND_FINAL_STR_IT \
if((c = m_raw[m_pos]) == '"') \
break; \
m_pos += (c == '\\') + 1; \
if((c = m_raw[m_pos]) == '"') \
break; \
m_pos += (c == '\\') + 1; \
if((c = m_raw[m_pos]) == '"') \
break; \
m_pos += (c == '\\') + 1; \
if((c = m_raw[m_pos]) == '"') \
break; \
m_pos += (c == '\\') + 1;
//+------------------------------------------------------------------+
Nique_372
2026-09-30 07:39:54 -05:00
//| Parseo de numeros |
//+------------------------------------------------------------------+
Nique_372
2026-09-30 07:39:54 -05:00
//--- make string
Nique_372
2026-10-08 13:39:44 -05:00
#define JSONPARSERBYLEO_NUM_MAKE_STRING m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING \
| ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_STR) \
| ulong(start) << TSN_SBL_BIT_STR_START;
Nique_372
2026-09-30 07:39:54 -05:00
Nique_372
2026-08-02 12:33:47 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-08-03 15:01:11 -05:00
//| Parse con simd |
Nique_372
2026-08-02 12:33:47 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-19 13:26:09 -05:00
// m_last_err = TSN_JSON_NOT_ERR; quizas no hague falta dado qeu en la DLL siemrpe se stea con noterr o eso
Nique_372
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
Nique_372
2026-09-18 14:11:09 -05:00
__forceinline bool CJsonParser::ParseSimd()
Nique_372
2026-06-02 21:23:50 -05:00
{
Nique_372
2026-08-03 15:01:11 -05:00
//--- Iniciales
Nique_372
2026-10-19 13:26:09 -05:00
m_pos = m_offset;
Nique_372
2026-07-12 18:24:34 -05:00
m_tables_size = 0;
Nique_372
2026-09-18 14:11:09 -05:00
return JsonParserResolve(m_raw,
m_cinta,
m_index,
m_len,
Nique_372
2026-10-19 07:27:55 -05:00
m_jit_enabled,
Nique_372
2026-09-18 14:11:09 -05:00
(int&)m_last_err,
m_cinta_pos,
m_pos
);
Nique_372
2026-08-02 16:49:10 -05:00
}
Nique_372
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
Nique_372
2026-08-03 15:01:11 -05:00
Nique_372
2026-08-02 16:49:10 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-08-03 15:01:11 -05:00
//| Parse normal |
Nique_372
2026-08-02 16:49:10 -05:00
//+------------------------------------------------------------------+
bool CJsonParser::Parse()
{
//---
m_last_err = TSN_JSON_NOT_ERR;
m_pos = m_offset;
m_cinta_pos = 0;
m_tables_size = 0;
Nique_372
2026-10-08 19:54:46 -05:00
//---
uint curr_state = 0;
uint curr_count = 0;
uint curr_padre = 0;
Nique_372
2026-08-02 16:49:10 -05:00
//--- Inicial
const uchar _f_c = m_raw[m_pos];
if(_f_c == '{')
m_next = TSN_JSON_TOK_LLAVE_INI;
else
if(_f_c == '[')
m_next = TSN_JSON_TOK_COR_INI;
Nique_372
2026-10-18 12:41:33 -05:00
else // No easy
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-08 19:54:46 -05:00
uchar __c = m_raw[++m_pos];
while(__c < 33)
__c = m_raw[++m_pos];
//---
if(__c == '{')
m_next = TSN_JSON_TOK_LLAVE_INI;
else
if(__c == '[')
m_next = TSN_JSON_TOK_COR_INI;
Nique_372
2026-10-18 12:41:33 -05:00
else // Single value
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-08 19:54:46 -05:00
m_next = TSN_JSON_TOK_INVALID;
Nique_372
2026-08-02 16:49:10 -05:00
}
}
//--- Bucle
while(true)
{
switch(m_next)
{
//---
case TSN_JSON_TOK_NUMBER_NEG:
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-09-30 07:39:54 -05:00
//--- solo 3 varaibles nada mas en general (garantizado)
long v = 0;
Nique_372
2026-10-08 13:39:44 -05:00
const uint start = m_pos;
Nique_372
2026-09-30 07:39:54 -05:00
uchar ch = m_raw[++m_pos] ^ '0';
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-09-30 07:39:54 -05:00
switch(0)
{
default: // scope con psoiblidad de break.
{
//--- primera iteracion sin cheking
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(v)
Nique_372
2026-09-30 07:39:54 -05:00
//--- Interesante: sigue siendo cero pero me pide mas digitios ?¿
if(!v)
{
m_last_err = TSN_JSON_ERR_LEADING_ZEROS;
m_next = TSN_JSON_TOK_INVALID;
continue;
}
//--- 19 iteraciones maximo
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_17(v)
Nique_372
2026-10-01 13:36:22 -05:00
STRCONV_TOV_ALG(v, ch)
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9)
{
if(v > 0)
break;
}
else // aun es valido asi que seguimos saltando el numero completo (parte entera) (pero ya sabmeos que es invalido)
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
}
//--- revismoos si es dec, si lo es saltamos la parte dec
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_DEC(ch))
break;
Nique_372
2026-09-30 07:39:54 -05:00
//--- pasamos a str y ya no caemos abajo de aqui:
JSONPARSERBYLEO_NUM_MAKE_STRING
TSN_JSON_AUMENT
TSN_JSON_NEXT_NO_NEXT_KEY
continue; // esto aplica a nivel de while
}
}
//--- vemos si decimal
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_DEC(ch))
Nique_372
2026-09-30 07:39:54 -05:00
{
long exponente = 0; // exponente
Nique_372
2026-10-08 13:39:44 -05:00
uint digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_PDEC(ch))
Nique_372
2026-09-30 07:39:54 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
uint ds = ++m_pos; // inicio
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[m_pos] ^ '0') > 9)
{
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP;
return false;
}
while(true)
{
Nique_372
2026-10-02 22:01:54 -05:00
//DOMBASEUTIL_NUM_PROCCES_FIRST_DEC(v, ch, m_pos, ds, digitos)
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
break;
}
//---
ds = (m_pos - ds); // numero de digitos de la parte decimal
digitos += ds;
exponente -= ds;
}
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_E(ch)) //
Nique_372
2026-09-30 07:39:54 -05:00
{
bool exp_positivo = true;
ch = m_raw[++m_pos] ^ '0';
if(ch > 9)
{
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_MINUS(ch))
Nique_372
2026-09-30 07:39:54 -05:00
exp_positivo = false;
if((ch = m_raw[++m_pos] ^ '0') > 9)
{
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_EXP;
return false; // sale
}
}
int expo = 0;
while(true) // siguimos acomulando en v
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(expo)
Nique_372
2026-09-30 07:39:54 -05:00
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_SKIP_LZ
Nique_372
2026-09-30 07:39:54 -05:00
} // pos apunta al curr no cero ch ya tiene su valor en caso sea 00000x (no numero) sale..
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
STRCONV_TOV_ALG(expo, ch)
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
{
Nique_372
2026-10-02 22:01:54 -05:00
if(expo > 0) // es valido
Nique_372
2026-09-30 07:39:54 -05:00
break; // no ov
}
else // sigue saltamos todo lo que hya
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
}
expo = INT_MAX;
Nique_372
2026-10-02 22:01:54 -05:00
break;
Nique_372
2026-09-30 07:39:54 -05:00
}
exponente += exp_positivo ? expo : -expo;
}
Nique_372
2026-10-02 22:01:54 -05:00
//--- 1 dado que start incluye el -
if(STRCONV_DOUBLE_SAFE_DBL_P(digitos, exponente, 1))
Nique_372
2026-09-30 07:39:54 -05:00
{
TsnBitInterprete bit;
Nique_372
2026-10-02 22:01:54 -05:00
bit.double_value = -STRCONV_TO_DOUBLE_ALG(exponente, v);
Nique_372
2026-09-30 07:39:54 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
Nique_372
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = bit.ulong_value;
Nique_372
2026-09-30 07:39:54 -05:00
}
else // make_string: numero grande o que ya no se peude representar con precision (a string)
{
JSONPARSERBYLEO_NUM_MAKE_STRING
}
}
else
{
m_cinta[m_cinta_pos++] = JSON_VTYPE_INTEGER;
m_cinta[m_cinta_pos++] = -v;
}
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_NUMBER:
{
//---
Nique_372
2026-10-08 13:39:44 -05:00
const uint start = m_pos;
Nique_372
2026-10-18 12:41:33 -05:00
// Primer valor
const uchar fc = m_raw[start] ^ '0';
ulong v = fc; // Tal cual sin mas..
// Segundo valor
uchar ch = m_raw[++m_pos] ^ '0';
Nique_372
2026-08-02 16:49:10 -05:00
Nique_372
2026-09-30 07:39:54 -05:00
//---
switch(0)
{
default: // scope con psoiblidad de break.
{
//---
Nique_372
2026-10-18 12:41:33 -05:00
if(ch > 9) // Mayor
break;
if(!v) // LZ
Nique_372
2026-09-30 07:39:54 -05:00
{
m_last_err = TSN_JSON_ERR_LEADING_ZEROS;
m_next = TSN_JSON_TOK_INVALID;
continue;
}
//--- 19 iteraciones maximo
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
Nique_372
2026-10-01 13:36:22 -05:00
STRCONV_TOV_ALG(v, ch)
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9)
{
if(fc == 1 && v > LONG_MAX)
break;
}
else // aun es valido asi que seguimos saltando el numero completo (parte entera) (pero ya sabmeos que es invalido)
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
}
Nique_372
2026-10-02 22:01:54 -05:00
//--- revismoos si es dec, si es asi lo mandamos para la funcion dec aqui solo big integer
if(STRCONV_DECX_CH_IS_DEC(ch))
break;
Nique_372
2026-09-30 07:39:54 -05:00
//--- pasamos a str y ya no caemos abajo de aqui:
JSONPARSERBYLEO_NUM_MAKE_STRING
TSN_JSON_AUMENT
TSN_JSON_NEXT_NO_NEXT_KEY
continue; // esto aplica a nivel de while
}
}
//--- vemos si decimal
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_DEC(ch)) // v por lo tanto llega bien aqui como entero unsigned valido
Nique_372
2026-09-30 07:39:54 -05:00
{
long exponente = 0; // exponente
Nique_372
2026-10-08 13:39:44 -05:00
uint digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_PDEC(ch)) // punto decimal (tomar precuacion aqui si v puede dar overflow y voltear no hay chekeo)
Nique_372
2026-09-30 07:39:54 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
uint ds = ++m_pos;
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[m_pos] ^ '0') > 9)
{
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP;
return false;
}
while(true)
{
Nique_372
2026-10-02 22:01:54 -05:00
//DOMBASEUTIL_NUM_PROCCES_FIRST_DEC(v, ch, m_pos, ds, digitos)
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
break;
}
//---
ds = (m_pos - ds); // numero de digitos de la parte decimal
digitos += ds;
exponente -= ds;
}
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_E(ch)) //
Nique_372
2026-09-30 07:39:54 -05:00
{
bool exp_positivo = true;
ch = m_raw[++m_pos] ^ '0';
if(ch > 9)
{
Nique_372
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_MINUS(ch))
Nique_372
2026-09-30 07:39:54 -05:00
exp_positivo = false;
if((ch = m_raw[++m_pos] ^ '0') > 9)
{
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_EXP;
return false; // sale
}
}
int expo = 0;
Nique_372
2026-10-02 22:01:54 -05:00
while(true)
Nique_372
2026-09-30 07:39:54 -05:00
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(expo)
Nique_372
2026-09-30 07:39:54 -05:00
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_SKIP_LZ
Nique_372
2026-09-30 07:39:54 -05:00
} // pos apunta al curr no cero ch ya tiene su valor en caso sea 00000x (no numero) sale..
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
STRCONV_TOV_ALG(expo, ch)
Nique_372
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
{
Nique_372
2026-10-02 22:01:54 -05:00
if(expo > 0) // es valido
Nique_372
2026-09-30 07:39:54 -05:00
break; // no ov
}
else // sigue saltamos todo lo que hya
{
Nique_372
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
Nique_372
2026-09-30 07:39:54 -05:00
}
expo = INT_MAX;
Nique_372
2026-10-02 22:01:54 -05:00
break;
Nique_372
2026-09-30 07:39:54 -05:00
}
exponente += exp_positivo ? expo : -expo;
}
Nique_372
2026-10-02 22:01:54 -05:00
//---
if(STRCONV_DOUBLE_SAFE_DBL(digitos, exponente))
Nique_372
2026-09-30 07:39:54 -05:00
{
TsnBitInterprete bit;
Nique_372
2026-10-02 22:01:54 -05:00
bit.double_value = STRCONV_TO_DOUBLE_ALG(exponente, v);
Nique_372
2026-09-30 07:39:54 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
Nique_372
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = bit.ulong_value;
Nique_372
2026-09-30 07:39:54 -05:00
}
Nique_372
2026-10-02 22:01:54 -05:00
else
Nique_372
2026-09-30 07:39:54 -05:00
{
JSONPARSERBYLEO_NUM_MAKE_STRING
}
}
else
{
m_cinta[m_cinta_pos++] = JSON_VTYPE_UINTEGER;
Nique_372
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = v;
Nique_372
2026-09-30 07:39:54 -05:00
}
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
Nique_372
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
//---
case TSN_JSON_TOK_STRING:
{
//---
Nique_372
2026-10-08 13:39:44 -05:00
const uint start = ++m_pos;
Nique_372
2026-08-02 16:49:10 -05:00
//---
#ifndef JSONPARSERBYLEO_DESACTIVE_SWAR
//--- Pase inicial 8 en 8
while(true)
{
// PrintFormat("Analizando: '%s'", CharArrayToString(m_raw, m_pos, 8));
const ulong chunk = (ulong)m_raw[m_pos]
| (ulong)m_raw[m_pos + 1] << 8
| (ulong)m_raw[m_pos + 2] << 16
| (ulong)m_raw[m_pos + 3] << 24
| (ulong)m_raw[m_pos + 4] << 32
| (ulong)m_raw[m_pos + 5] << 40
| (ulong)m_raw[m_pos + 6] << 48
| (ulong)m_raw[m_pos + 7] << 56;
//---
const ulong x_bs = chunk ^ TSNTABLES_SWAR_MASK_BACK_SLASH;
const ulong x_qt = chunk ^ TSNTABLES_SWAR_MASK_COMILLA;
Nique_372
2026-10-17 15:35:59 -05:00
ulong has_bs = TSNTABLES_SWAR_HAS(x_bs);
ulong has_qt = TSNTABLES_SWAR_HAS(x_qt);
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-10-17 15:35:59 -05:00
if((has_bs | has_qt) == 0) // Fast path
Nique_372
2026-08-02 16:49:10 -05:00
{
m_pos += 8;
continue;
}
//---
Nique_372
2026-10-18 12:41:33 -05:00
if(has_bs == 0) // Si not iene bs (pero confirmamos que no es 0) (Fast path)
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-17 15:35:59 -05:00
const ulong flag_real = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
Nique_372
2026-08-27 13:40:38 -05:00
m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag_real);
Nique_372
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
Nique_372
2026-10-08 13:39:44 -05:00
| ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_STR)
| ulong(start) << TSN_SBL_BIT_STR_START;
Nique_372
2026-08-02 16:49:10 -05:00
m_pos++; // Luego del "
break;
}
Nique_372
2026-10-17 15:35:59 -05:00
//--- Slow path
has_bs = TSNTABLES_SWAR_HAS_EXACT(x_bs);
has_qt = TSNTABLES_SWAR_HAS_EXACT(x_qt);
Nique_372
2026-08-02 16:49:10 -05:00
//--- Hay bs si o si pero tambien puede haber "
const uchar compacted_bs = TSNTABLES_COMPACT_UL(has_bs);
const uchar prev = (((compacted_bs << 1) | TSNTABLES_MASK_IMPARES) - compacted_bs) ^ TSNTABLES_MASK_IMPARES;
const uchar escaped = prev ^ compacted_bs;
//---
const uchar compacted_qt = TSNTABLES_COMPACT_UL(has_qt);
const uchar qt_final = compacted_qt & ~escaped;
//Print("nada");
//---
Nique_372
2026-09-18 14:11:09 -05:00
if(qt_final) // Hay un qt real de cierre
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-09-18 14:11:09 -05:00
//---
Nique_372
2026-08-02 16:49:10 -05:00
// Avanzamos y cerramos..
Nique_372
2026-08-27 13:40:38 -05:00
m_pos += g_tsntables_table_ctz_i8[qt_final];
Nique_372
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
Nique_372
2026-10-08 13:39:44 -05:00
| ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_STR)
| ulong(start) << TSN_SBL_BIT_STR_START;
Nique_372
2026-09-18 14:11:09 -05:00
//---
m_pos++;
Nique_372
2026-08-02 16:49:10 -05:00
break;
}
else
{
Nique_372
2026-10-17 15:35:59 -05:00
m_pos += 8;// + ((prev & compacted_bs) >> 7U);
Nique_372
2026-08-02 16:49:10 -05:00
// Print(CharToString(m_raw[m_pos]));
// escape
if(((prev & compacted_bs) >> 7U) != 0) // Overflow el ultimo char es \ y el siguiente escapa
{
//Print("siuu");
m_pos++; // Uno mas.. luego del currend
}
}
}
Nique_372
2026-10-17 15:35:59 -05:00
Nique_372
2026-08-02 16:49:10 -05:00
#else // JSONPARSERBYLEO_DESACTIVE_SWAR
//--- Char por char
Nique_372
2026-10-17 15:35:59 -05:00
uchar c;
while(true) // Find unrrolled 20
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-17 15:35:59 -05:00
JSONPARSERBYLEO_FIND_FINAL_STR_IT
JSONPARSERBYLEO_FIND_FINAL_STR_IT
JSONPARSERBYLEO_FIND_FINAL_STR_IT
JSONPARSERBYLEO_FIND_FINAL_STR_IT
JSONPARSERBYLEO_FIND_FINAL_STR_IT
Nique_372
2026-08-02 16:49:10 -05:00
}
Nique_372
2026-10-17 15:35:59 -05:00
//---
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING | ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_STR) |
ulong(start) << TSN_SBL_BIT_STR_START;
m_pos++;
Nique_372
2026-08-02 16:49:10 -05:00
#endif // JSONPARSERBYLEO_DESACTIVE_SWAR
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
Nique_372
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
//---
break;
}
Nique_372
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_BOOL_TRUE:
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-03 11:47:17 -05:00
const uint k = (uint)m_raw[++m_pos] | (uint)m_raw[++m_pos] << 8 | (uint)m_raw[++m_pos] << 16;
if(k != TSNJSON_VAL_TRUE)
Nique_372
2026-09-30 07:39:54 -05:00
return false;
Nique_372
2026-08-02 16:49:10 -05:00
Nique_372
2026-09-30 07:39:54 -05:00
//---
m_pos++;
Nique_372
2026-10-08 19:54:46 -05:00
m_cinta[m_cinta_pos++] = (JSON_VTYPE_BOOLEAN | 1ULL << TSN_SBL_BIT_START_BOOL);
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
Nique_372
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
Nique_372
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_BOOL_FALSE:
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-03 11:47:17 -05:00
//const uint k = (uint)m_raw[++m_pos] | (uint)m_raw[++m_pos] << 8 | (uint)m_raw[++m_pos] << 16 | (uint)m_raw[++m_pos] << 24;
Nique_372
2026-09-30 07:39:54 -05:00
if(m_raw[++m_pos] != 'a' || m_raw[++m_pos] != 'l' || m_raw[++m_pos] != 's' || m_raw[++m_pos] != 'e')
return false;
//---
m_pos++;
Nique_372
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_BOOLEAN;
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
Nique_372
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
case TSN_JSON_TOK_NULL:
{
Nique_372
2026-10-03 11:47:17 -05:00
const uint k = (uint)m_raw[++m_pos] | (uint)m_raw[++m_pos] << 8 | (uint)m_raw[++m_pos] << 16;
if(k != TSNJSON_VAL_NULL)
Nique_372
2026-09-30 07:39:54 -05:00
return false;
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-09-30 07:39:54 -05:00
m_pos++;
Nique_372
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_NULL;
//---
Nique_372
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
Nique_372
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
Nique_372
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_COMMA:
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-08 19:54:46 -05:00
if(curr_state == TSN_JSON_CTX_IN_OBJ)
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-09-30 07:39:54 -05:00
while(m_raw[++m_pos] != '"') {}
m_next = TSN_JSON_TOK_KEY;
Nique_372
2026-08-02 16:49:10 -05:00
}
else
{
TSN_JSON_NEXT_VALUE_COMM_KEY
}
break;
}
Nique_372
2026-10-17 15:35:59 -05:00
case TSN_JSON_TOK_LLAVE_INI:
Nique_372
2026-08-02 16:49:10 -05:00
{
Nique_372
2026-10-08 19:54:46 -05:00
//--- guardar lo uqe tenaismos (numero de elementos) (+1 para contar este nuevo elemento)
m_cinta[curr_padre] = curr_count + 1;
//--- nuevo, ahora guardamos la direccion de nuesto padre y la nuestar (rempalzao num el por mientas)
m_cinta[m_cinta_pos] = JSON_VTYPE_OBJ |
ulong(m_cinta_pos) << TSN_SBL_PARSE_START_CINTAPOS |
ulong(curr_padre) << TSN_SBL_BIT_START_NUM_C;
curr_padre = ++m_cinta_pos; // apunta al inicio + 1 (lo modificamos para count, ahora apunta aqui..)
m_cinta_pos++; // salta la posicion 1
//--- reiniciamos los estados
curr_state = TSN_JSON_CTX_IN_OBJ;
curr_count = 0;
Nique_372
2026-08-02 16:49:10 -05:00
Nique_372
2026-10-18 12:41:33 -05:00
//---
uchar _c = m_raw[++m_pos];
while(_c < 33)
_c = m_raw[++m_pos];
//---
if(_c == '"')
m_next = TSN_JSON_TOK_KEY;
else
Nique_372
2026-10-08 19:54:46 -05:00
if(_c == '}')
m_next = TSN_JSON_TOK_LLAVE_END;
Nique_372
2026-10-18 12:41:33 -05:00
else
{
Nique_372
2026-10-19 09:16:24 -05:00
m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_LLAVE_INI;
m_next = TSN_JSON_TOK_INVALID;
Nique_372
2026-10-08 19:54:46 -05:00
}
Nique_372
2026-10-18 12:41:33 -05:00
Nique_372
2026-08-02 16:49:10 -05:00
//---
break;
}
case TSN_JSON_TOK_COR_INI:
{
Nique_372
2026-10-08 19:54:46 -05:00
//--- guardar lo uqe tenaismos (numero de elementos) (+1 para contar este nuevo elemento)
m_cinta[curr_padre] = curr_count + 1;
//--- nuevo, ahora guardamos la direccion de nuesto padre y la nuestar (rempalzao num el por mientas)
m_cinta[m_cinta_pos] = JSON_VTYPE_ARR |
ulong(m_cinta_pos) << TSN_SBL_PARSE_START_CINTAPOS |
ulong(curr_padre) << TSN_SBL_BIT_START_NUM_C;
curr_padre = ++m_cinta_pos; // apunta al inicio + 1 (lo modificamos para count, ahora apunta aqui..)
m_cinta_pos++; // salta la posicion 1
//--- reiniciamos los estados
curr_state = TSN_JSON_CTX_IN_ARR;
curr_count = 0;
//--- Find
//- con el pre salta.. el [
Nique_372
2026-10-08 13:39:44 -05:00
uchar _c = m_raw[++m_pos];
Nique_372
2026-10-02 22:01:54 -05:00
while(_c < 33)
_c = m_raw[++m_pos];
Nique_372
2026-10-08 19:54:46 -05:00
//- check
Nique_372
2026-10-02 22:01:54 -05:00
m_next = g_table_json_tokens[_c];
if(((1 << m_next) & TSN_JSON_F_VAL_COR) == 0)
{
m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI;
return false;
}
Nique_372
2026-10-03 11:47:17 -05:00
Nique_372
2026-08-02 16:49:10 -05:00
//---
break;
}
case TSN_JSON_TOK_LLAVE_END:
{
Nique_372
2026-10-08 19:54:46 -05:00
//--- cacheamos el valor de cinta [curr_padre-1] = apunta a los datos
m_cinta[curr_padre] = m_jit_enabled; // le damos su valor final
const uint idata = --curr_padre;
const ulong v = m_cinta[idata];
// ahora si rehacemos el valor con todo ya listo.. (curr padre apunta a la posicion correcta)
m_cinta[idata] = JSON_VTYPE_OBJ | ulong(curr_count) << TSN_SBL_BIT_START_NUM_EL |
Nique_372
2026-10-08 20:25:09 -05:00
ulong(m_cinta_pos - ((v >> 1) & TSN_SBL_PARSE_MASK_CINTAPOS_S)) << TSN_SBL_BIT_START_NUM_C;
Nique_372
2026-08-02 16:49:10 -05:00
Nique_372
2026-10-08 19:54:46 -05:00
curr_padre = uint(v >> TSN_SBL_BIT_START_NUM_C); // ahora obtenemos su padre..
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-10-08 20:25:09 -05:00
if(curr_padre == idata) // dado que cur_padre apunta a la psocion 2.. [0][1 aqui] entonces con 1...
Nique_372
2026-10-08 19:54:46 -05:00
return true;
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-10-08 19:54:46 -05:00
curr_count = (uint)m_cinta[curr_padre]; // le devolvemos..
curr_state = TSN_JSON_MAKE_STATE(m_cinta[curr_padre - 1] & TSN_SBL_PARSE_MASK_OA_T);
Nique_372
2026-08-02 16:49:10 -05:00
m_pos++;
//---
TSN_JSON_NEXT_NO_NEXT_KEY
Nique_372
2026-10-08 19:54:46 -05:00
break;
}
case TSN_JSON_TOK_COR_END:
{
//--- cacheamos el valor de cinta [curr_padre-1] = apunta a los datos
const uint idata = --curr_padre;
const ulong v = m_cinta[idata];
// ahora si rehacemos el valor con todo ya listo.. (curr padre apunta a la posicion correcta)
m_cinta[idata] = JSON_VTYPE_ARR | ulong(curr_count) << TSN_SBL_BIT_START_NUM_EL |
Nique_372
2026-10-08 20:25:09 -05:00
ulong(m_cinta_pos - ((v >> 1) & TSN_SBL_PARSE_MASK_CINTAPOS_S)) << TSN_SBL_BIT_START_NUM_C;
Nique_372
2026-10-08 19:54:46 -05:00
curr_padre = uint(v >> TSN_SBL_BIT_START_NUM_C); // ahora obtenemos su padre..
Nique_372
2026-08-02 16:49:10 -05:00
//---
Nique_372
2026-10-08 20:25:09 -05:00
if(curr_padre == idata) // dado que cur_padre apunta a la psocion 2.. [0][1 aqui] entonces con 1...
Nique_372
2026-10-08 19:54:46 -05:00
return true;
//---
curr_count = (uint)m_cinta[curr_padre]; // le devolvemos..
curr_state = TSN_JSON_MAKE_STATE(m_cinta[curr_padre - 1] & TSN_SBL_PARSE_MASK_OA_T);
m_pos++;
//---
TSN_JSON_NEXT_NO_NEXT_KEY
Nique_372
2026-08-02 16:49:10 -05:00
break;
}
case TSN_JSON_TOK_KEY:
{
Nique_372
2026-10-08 13:39:44 -05:00
const uint start = ++m_pos;
Nique_372
2026-08-02 16:49:10 -05:00
Nique_372
2026-06-20 13:57:50 -05:00
//--- Char por char
Nique_372
2026-10-03 11:47:17 -05:00
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
Nique_372
2026-06-20 13:57:50 -05:00
while(true)
{
Nique_372
2026-07-19 07:41:52 -05:00
const uchar c = m_raw[m_pos];
Nique_372
2026-06-20 13:57:50 -05:00
if(c == '\\')
{
m_pos += 2;
continue;
}
if(c == '"')
{
Nique_372
2026-06-20 14:18:38 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
Nique_372
2026-10-08 13:39:44 -05:00
| ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_KEY)
| ulong(start) << TSN_SBL_BIT_STR_START;
Nique_372
2026-06-20 13:57:50 -05:00
m_pos++;
break;
}
Nique_372
2026-10-03 11:47:17 -05:00
m_pos++;
}
Nique_372
2026-10-03 11:47:17 -05:00
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS*/
//---
Nique_372
2026-10-08 20:25:09 -05:00
while(true)
{
TSN_JSON_FINDKEY_FINAL_U4
TSN_JSON_FINDKEY_FINAL_U4
TSN_JSON_FINDKEY_FINAL_U4
TSN_JSON_FINDKEY_FINAL_U4
}
Nique_372
2026-10-03 17:00:34 -05:00
Nique_372
2026-10-03 11:47:17 -05:00
//---
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
Nique_372
2026-10-08 13:39:44 -05:00
| ulong(m_pos - start) << TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_KEY)
| ulong(start) << TSN_SBL_BIT_STR_START;
Nique_372
2026-10-03 11:47:17 -05:00
m_pos++;
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
Nique_372
2026-10-08 13:39:44 -05:00
//---
m_cinta_pos++; // hash ignoramos.
Nique_372
2026-06-20 13:57:50 -05:00
//--- Find :
Nique_372
2026-10-18 12:41:33 -05:00
while(m_raw[m_pos] != ':')
{
Nique_372
2026-06-14 15:51:39 -05:00
//---
Nique_372
2026-10-18 12:41:33 -05:00
//if(m_raw[m_pos] == ':')
// break;
Nique_372
2026-06-14 15:51:39 -05:00
//---
Nique_372
2026-06-20 13:57:50 -05:00
m_pos++;
Nique_372
2026-06-14 15:51:39 -05:00
if(m_pos >= m_len)
{
m_last_err = TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS;
return false;
}
}
//--- Buscamos valor
Nique_372
2026-06-20 13:57:50 -05:00
TSN_JSON_NEXT_VALUE_COMM_KEY
Nique_372
2026-06-02 21:23:50 -05:00
//---
break;
}
default:
return false;
}
}
}
Nique_372
2026-06-20 13:57:50 -05:00
Nique_372
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-08 13:39:44 -05:00
//| GetStep |
Nique_372
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-06-03 07:50:45 -05:00
__forceinline int CJsonParser::GetStepPure(const int idx) const
Nique_372
2026-06-02 22:52:39 -05:00
{
Nique_372
2026-09-30 07:39:54 -05:00
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
Nique_372
2026-06-02 22:52:39 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
Nique_372
2026-07-19 07:41:52 -05:00
case JSON_VTYPE_OBJ:
Nique_372
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
Nique_372
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_INTEGER:
case JSON_VTYPE_REAL:
return 2;
Nique_372
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_BOOLEAN:
Nique_372
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_STRING:
Nique_372
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_NULL:
return 1;
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
return TSN_SBL_KEYSLOT_SIZE;
Nique_372
2026-09-23 15:25:08 -05:00
default:
return 1;
Nique_372
2026-06-03 07:50:45 -05:00
}
}
//+------------------------------------------------------------------+
__forceinline int CJsonParser::GetStep(const int idx)
const
{
Nique_372
2026-08-28 11:16:09 -05:00
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
Nique_372
2026-06-03 07:50:45 -05:00
{
Nique_372
2026-07-19 07:41:52 -05:00
case JSON_VTYPE_ARR:
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_OBJ:
Nique_372
2026-07-19 07:41:52 -05:00
return int(m_cinta[idx] >> TSN_SBL_BIT_START_NUM_C);
Nique_372
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
Nique_372
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_INTEGER:
case JSON_VTYPE_REAL:
return 2;
Nique_372
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_BOOLEAN:
Nique_372
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_STRING:
Nique_372
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_NULL:
return 1;
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
return TSN_SBL_KEYSLOT_SIZE;
Nique_372
2026-09-23 15:25:08 -05:00
default:
return 1;
Nique_372
2026-06-02 22:52:39 -05:00
}
}
Nique_372
2026-06-03 07:50:45 -05:00
//+------------------------------------------------------------------+
//| |
Nique_372
2026-07-19 13:56:15 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-01 08:25:33 -05:00
bool CJsonParser::SerializeToDom(CDomNodeBase *root, CDomNodeManager* manager, int cur, const int end)
Nique_372
2026-07-19 13:56:15 -05:00
{
//--- Temp
Nique_372
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_NOT_ERR;
Nique_372
2026-07-19 13:56:15 -05:00
CDomNodeBase* prev_value; // valolr qeu devuelve key
CDomNodeBase* current_container[JSONPARSERBYLEO_MAX_STACK]; // contenedor
int current_ends[JSONPARSERBYLEO_MAX_STACK];
Nique_372
2026-07-19 13:56:15 -05:00
int sp = 0;
//--- Inicial
const int c = int((m_cinta[cur] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
if((m_cinta[cur]&TSN_SBL_BIT_MASK_TYPE) == JSON_VTYPE_OBJ)
root.NewObj(c);
else
root.NewArr(c);
Nique_372
2026-07-19 15:11:32 -05:00
Nique_372
2026-07-19 13:56:15 -05:00
//---
current_container[0] = root;
current_ends[sp] = end;
//---
cur += 2;
//--- It
while(true)
{
//--- Check
Nique_372
2026-07-21 10:38:19 -05:00
while(cur >= current_ends[sp])
Nique_372
2026-07-19 13:56:15 -05:00
{
sp--; // Nivel menos
Nique_372
2026-07-19 15:11:32 -05:00
//Print("sp luego: ", sp);
if(sp < 0)
Nique_372
2026-10-01 08:25:33 -05:00
return true;
Nique_372
2026-07-19 13:56:15 -05:00
}
//---
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
Nique_372
2026-07-19 15:11:32 -05:00
//Print(EnumToString(tipo), " | ", cur, " | " , sp);
Nique_372
2026-07-19 13:56:15 -05:00
//---
switch(tipo)
{
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
Nique_372
2026-07-19 13:56:15 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
const int count = int((m_cinta[cur] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-07-19 13:56:15 -05:00
{
const int lock = sp++;
Nique_372
2026-07-19 15:11:32 -05:00
current_container[sp] = new CDomNodeBase(manager);
Nique_372
2026-10-08 13:39:44 -05:00
current_container[sp].NewArr(count);
Nique_372
2026-07-19 13:56:15 -05:00
current_container[lock].AddItem(current_container[sp]);
}
Nique_372
2026-10-08 13:39:44 -05:00
else // {key:[]}
Nique_372
2026-07-19 13:56:15 -05:00
{
sp++;
Nique_372
2026-10-08 13:39:44 -05:00
prev_value.NewArr(count);
Nique_372
2026-07-19 13:56:15 -05:00
current_container[sp] = prev_value;
}
current_ends[sp] = cur + int(m_cinta[cur] >> TSN_SBL_BIT_START_NUM_C);
break;
}
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_OBJ:
Nique_372
2026-07-19 13:56:15 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
const int count = (int((m_cinta[cur] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL)) << 1;
if(current_container[sp].m_type == JSON_VTYPE_ARR) // [{}]
Nique_372
2026-07-19 13:56:15 -05:00
{
const int lock = sp++;
Nique_372
2026-07-19 15:11:32 -05:00
current_container[sp] = new CDomNodeBase(manager);
Nique_372
2026-10-08 13:39:44 -05:00
current_container[sp].NewObj(count);
Nique_372
2026-07-19 13:56:15 -05:00
current_container[lock].AddItem(current_container[sp]);
}
Nique_372
2026-10-08 13:39:44 -05:00
else // {key:{}}
Nique_372
2026-07-19 13:56:15 -05:00
{
sp++;
Nique_372
2026-10-08 13:39:44 -05:00
prev_value.NewObj(count);
Nique_372
2026-07-19 13:56:15 -05:00
current_container[sp] = prev_value;
}
current_ends[sp] = cur + int(m_cinta[cur] >> TSN_SBL_BIT_START_NUM_C);
break;
}
Nique_372
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
{
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-10-08 21:07:14 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, m_cinta[cur + 1]));
Nique_372
2026-09-30 07:39:54 -05:00
else
Nique_372
2026-10-08 21:07:14 -05:00
prev_value = m_cinta[cur + 1];
Nique_372
2026-09-30 07:39:54 -05:00
break;
}
Nique_372
2026-07-19 13:56:15 -05:00
case JSON_VTYPE_INTEGER:
{
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-10-08 21:07:14 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, (long)m_cinta[cur + 1]));
Nique_372
2026-07-19 13:56:15 -05:00
else
Nique_372
2026-10-08 21:07:14 -05:00
prev_value = (long)m_cinta[cur + 1];
Nique_372
2026-07-19 13:56:15 -05:00
break;
}
case JSON_VTYPE_REAL:
{
Nique_372
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
Nique_372
2026-10-08 13:39:44 -05:00
un.ulong_value = m_cinta[cur + 1];
Nique_372
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-07-24 08:54:26 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, un.double_value));
Nique_372
2026-07-19 13:56:15 -05:00
else
prev_value = un.double_value;
break;
}
case JSON_VTYPE_BOOLEAN:
{
Nique_372
2026-10-08 19:54:46 -05:00
const bool v = (m_cinta[cur] >> TSN_SBL_BIT_START_BOOL) != 0;
Nique_372
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-07-24 08:54:26 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, v));
Nique_372
2026-07-19 13:56:15 -05:00
else
prev_value = v;
break;
}
case JSON_VTYPE_STRING:
{
Nique_372
2026-10-08 13:39:44 -05:00
//---
const int s = TSN_SBL_CLS_STR_START(cur, int);
const int slen = TSN_SBL_CLS_STR_LEN(cur, TSN_SBL_SLEN_STR, int);
Nique_372
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-10-01 08:25:33 -05:00
{
CDomNodeBase* ptr = new CDomNodeBase(TSN_SBL_BASE_TYPE_STR, manager);
current_container[sp].AddItem(ptr); // lo agregamos
const int idx = ptr.m_v.ix;
Nique_372
2026-10-08 13:39:44 -05:00
if(!JSONPBL_MAKESTRING(m_raw, s, slen, manager.m_string_stack[idx]))
Nique_372
2026-10-01 08:25:33 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
m_pos = s;
Nique_372
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
return false;
}
}
Nique_372
2026-07-19 13:56:15 -05:00
else
Nique_372
2026-10-01 08:25:33 -05:00
{
prev_value.Type(TSN_SBL_BASE_TYPE_STR); // lo hacemos string
const int idx = prev_value.m_v.ix;
Nique_372
2026-10-08 13:39:44 -05:00
if(!JSONPBL_MAKESTRING(m_raw, s, slen, manager.m_string_stack[idx]))
Nique_372
2026-10-01 08:25:33 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
m_pos = s;
Nique_372
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
return false;
}
}
Nique_372
2026-07-19 13:56:15 -05:00
break;
}
case JSON_VTYPE_NULL:
{
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
Nique_372
2026-07-19 15:11:32 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager));
Nique_372
2026-07-19 13:56:15 -05:00
else
prev_value.m_type = JSON_VTYPE_NULL;
break;
}
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
{
const int s = TSN_SBL_CLS_STR_START(cur, int);
const int slen = TSN_SBL_CLS_STR_LEN(cur, TSN_SBL_SLEN_KEY, int);
if(!JSONPBL_MAKESTRING(m_raw, s, slen, s_str))
{
m_pos = s;
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
return false;
}
prev_value = current_container[sp][s_str];
break;
}
Nique_372
2026-07-19 13:56:15 -05:00
default:
break;
}
//---
cur += GetStepPure(cur);
}
Nique_372
2026-10-01 08:25:33 -05:00
//---
return false;
Nique_372
2026-07-19 13:56:15 -05:00
}
//+------------------------------------------------------------------+
//| |
Nique_372
2026-06-03 07:50:45 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-06-18 08:36:18 -05:00
void CJsonParser::PrintCintaTypes(const int start, const int num) const
Nique_372
2026-06-03 07:50:45 -05:00
{
Nique_372
2026-06-18 08:36:18 -05:00
//---
int p = fmax(start, 0);
const int end = (num == WHOLE_ARRAY || (p + num) > m_cinta_pos) ? m_cinta_pos : (p + num);
Nique_372
2026-10-01 08:25:33 -05:00
//---
string text;
StringReserve(text, 256); // algo razonable.
Nique_372
2026-06-18 08:36:18 -05:00
//---
while(p < end)
Nique_372
2026-06-03 07:50:45 -05:00
{
Nique_372
2026-07-19 07:41:52 -05:00
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[p] & TSN_SBL_BIT_MASK_TYPE);
Nique_372
2026-10-01 08:25:33 -05:00
text = "[" + (string)p + "] " + EnumToString(tipo) + " | ";
Nique_372
2026-06-03 15:48:09 -05:00
//---
switch(tipo)
{
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
Nique_372
2026-07-19 07:41:52 -05:00
{
Nique_372
2026-10-08 13:39:44 -05:00
const int count = TSN_SBL_CLS_AO_NUM_EL(p, int);
const int num_c = TSN_SBL_CLS_AO_STEP(p, int);
text += "count=" + (string)count + " num_c=" + (string)num_c;
Nique_372
2026-07-19 07:41:52 -05:00
break;
}
case JSON_VTYPE_OBJ:
{
Nique_372
2026-10-08 13:39:44 -05:00
const int count = TSN_SBL_CLS_AO_NUM_EL(p, int);
const int num_c = TSN_SBL_CLS_AO_STEP(p, int);
const bool jit = TSN_SBL_CLS_OBJ_JIT(p + 1) != 0;
const ulong attemps = TSN_SBL_CLS_OBJ_JIT_ATTMP(p + 1);
text += "count=" + (string)count + " num_c=" + (string)num_c + " is_jit=" + (string)jit + " jit_attemps=" + (string)attemps;
Nique_372
2026-07-19 07:41:52 -05:00
break;
}
Nique_372
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
{
Nique_372
2026-10-24 12:45:01 -05:00
STRCONV_VALTOBUFFER_ULLSTR_WR(m_cinta[p + 1], s_str, w)
text += "val=" + s_str;
Nique_372
2026-09-30 07:39:54 -05:00
break;
}
Nique_372
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_INTEGER:
Nique_372
2026-07-19 07:41:52 -05:00
{
Nique_372
2026-06-03 15:48:09 -05:00
text += "val=" + (string)m_cinta[p + 1];
break;
Nique_372
2026-07-19 07:41:52 -05:00
}
Nique_372
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_REAL:
{
Nique_372
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
Nique_372
2026-10-08 13:39:44 -05:00
un.ulong_value = m_cinta[p + 1];
text += "val=" + (string)un.double_value;
break;
}
Nique_372
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_BOOLEAN:
Nique_372
2026-10-08 19:54:46 -05:00
text += "val=" + (string)(bool)((m_cinta[p] >> TSN_SBL_BIT_START_BOOL) & 1);
Nique_372
2026-06-03 15:48:09 -05:00
break;
case JSON_VTYPE_STRING:
{
Nique_372
2026-07-19 07:41:52 -05:00
const int s = int(m_cinta[p] >> TSN_SBL_BIT_STR_START);
Nique_372
2026-10-08 13:39:44 -05:00
const int slen = int((m_cinta[p] >> TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_STR)) & TSN_SBL_BIT_STR_MASK_LEN(TSN_SBL_SLEN_STR));
Nique_372
2026-10-01 08:25:33 -05:00
//---
Nique_372
2026-10-08 13:39:44 -05:00
if(JSONPBL_MAKESTRING(m_raw, s, slen, s_str))
text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + s_str + "\"";
Nique_372
2026-10-01 08:25:33 -05:00
else
text += "start=" + (string)s + " len=" + (string)slen + " val=Invalid";
break;
}
Nique_372
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_NULL:
text += "null";
break;
Nique_372
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
{
const int s = int(m_cinta[p] >> TSN_SBL_BIT_STR_START);
const int slen = int((m_cinta[p] >> TSN_SBL_BIT_STR_LEN(TSN_SBL_SLEN_KEY)) & TSN_SBL_BIT_STR_MASK_LEN(TSN_SBL_SLEN_KEY));
//---
if(JSONPBL_MAKESTRING(m_raw, s, slen, s_str))
text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + s_str + "\"";
else
text += "start=" + (string)s + " len=" + (string)slen + " val=Invalid";
break;
}
Nique_372
2026-09-23 15:25:08 -05:00
//---
default:
break;
Nique_372
2026-06-03 15:48:09 -05:00
}
Print(text);
Nique_372
2026-06-03 07:50:45 -05:00
p += GetStepPure(p);
}
}
Nique_372
2026-10-01 08:25:33 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-08 13:39:44 -05:00
//| Errores |
Nique_372
2026-10-01 08:25:33 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-03 17:00:34 -05:00
static void CJsonParser::PrintError(const string& header, const uchar& buf[], const int len,
int col, int line, ENUM_TSN_JSON_LAST_ERR err, string& salida, bool print = true)
Nique_372
2026-10-01 08:25:33 -05:00
{
//---
Nique_372
2026-10-03 17:00:34 -05:00
string out = "";
out.Reserve(256);
Nique_372
2026-10-01 08:25:33 -05:00
//---
Nique_372
2026-10-03 17:00:34 -05:00
if(header.Length())
out += "[" + header + "]\n";
Nique_372
2026-10-01 08:25:33 -05:00
//---
Nique_372
2026-10-03 17:00:34 -05:00
out += StringFormat("JSON error at line %d, col %d:\n", line, col);
Nique_372
2026-10-01 08:25:33 -05:00
//---
Nique_372
2026-10-03 17:00:34 -05:00
switch(err)
Nique_372
2026-10-01 08:25:33 -05:00
{
case TSN_JSON_ERR_INVALID_EXT_FILE:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid file extension por JsonParserByLeo";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_INVALID_CHAR:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid character found in json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding comma or context close (], })";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding valid value after '['";
Nique_372
2026-10-01 08:25:33 -05:00
break;
Nique_372
2026-10-18 12:41:33 -05:00
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_LLAVE_INI:
out += "Invalid character find in json, finding valid value ['}' or '\"'] after '{'";
break;
Nique_372
2026-10-01 08:25:33 -05:00
case TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding valid value";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid JSON key, One of two errors: \"Expected a ':' after a JSON key\" or \"Malformed JSON while searching for characters.\"";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFOMED_LEN_SUPERADO:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Len has superated, but json are not closed, malformed json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_JSON_NOT_FINISH:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Json read has finish but not closed in ] or }, malformed json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_LEADING_ZEROS:
Nique_372
2026-10-03 17:00:34 -05:00
out += "A number in JSON notation cannot have leading zeros.";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_EXP:
Nique_372
2026-10-03 17:00:34 -05:00
out += "A number was expected after the 'E' exponent; an invalid character was found.";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP:
Nique_372
2026-10-03 17:00:34 -05:00
out += "A numeric value was expected after the decimal point.";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_TRUE:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Malformed 'true' in json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_FALSE:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Malformed 'false' in json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_NULL:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Malformed 'null' in json";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Error materializing string; possible causes include an invalid escape character or a malformed \\u sequence.";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_NOT_STRUCUTURAL_CHARS_FOUND:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Not structural character found in this json ({ | } | [ | ] | : | ,)";
Nique_372
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_INVALID_STATE_IN_PARSE_DOUBLE_E:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Invalid state for Json Sax Parsing, in parse double value";
Nique_372
2026-10-01 08:25:33 -05:00
break;
//---
default:
Nique_372
2026-10-03 17:00:34 -05:00
out += "Unknow error";
Nique_372
2026-10-01 08:25:33 -05:00
break;
}
//---
Nique_372
2026-10-03 17:00:34 -05:00
CParserErrFormat::Format(len, buf, line, col, out, salida);
//---
if(print)
Print(salida);
}
//+------------------------------------------------------------------+
// Solo a que tener cuidado con true\false\null
// aparte tok invalid tambien dado que este ultimo retorna false
void CJsonParser::CatchErr()
{
//---
if(m_pos >= m_len)
m_pos = m_len - 1;
//---
if(m_last_err != TSN_JSON_NOT_ERR)
return; // ya tiene valor no hace falta
//---
switch(m_next)
Nique_372
2026-10-01 08:25:33 -05:00
{
Nique_372
2026-10-03 17:00:34 -05:00
case TSN_JSON_TOK_BOOL_TRUE:
m_last_err = TSN_JSON_ERR_MALFORMED_TRUE;
break;
case TSN_JSON_TOK_BOOL_FALSE:
m_last_err = TSN_JSON_ERR_MALFORMED_FALSE;
break;
case TSN_JSON_TOK_NULL:
m_last_err = TSN_JSON_ERR_MALFORMED_NULL;
break;
default:
{
Nique_372
2026-10-19 09:16:24 -05:00
if(m_next == TSN_JSON_TOK_INVALID) // Solo si es tok invalid (si no nada)
Nique_372
2026-10-03 17:00:34 -05:00
m_last_err = TSN_JSON_ERR_INVALID_CHAR;
break;
}
Nique_372
2026-10-01 08:25:33 -05:00
}
}
Nique_372
2026-09-30 07:39:54 -05:00
//+------------------------------------------------------------------+
Nique_372
2026-10-03 17:00:34 -05:00
void CJsonParser::ErrorInfo(const string header = "")
{
//---
CatchErr();
//---
if(m_last_err == TSN_JSON_NOT_ERR)
return;
//---
int col, line;
GetLastErrorLocation(col, line);
//---
string out = "";
PrintError(header, m_raw, m_len, col, line, m_last_err, out);
}
Nique_372
2026-10-08 13:39:44 -05:00
//+------------------------------------------------------------------+
//| Tablas finales |
//+------------------------------------------------------------------+
string CJsonParser::s_str = ""; // streimp para las funciones internas (que requiran string)
const string CJsonParser::s_dtype_to_str[JSON_VTYPE_TOTAL] =
{
"",
"",
"",
"ulong",
"long",
"double",
"bool",
"string",
""
};
Nique_372
2026-09-30 07:39:54 -05:00
//---
Nique_372
2026-06-02 21:23:50 -05:00
}
Nique_372
2026-10-08 13:39:44 -05:00
#endif // JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
//+------------------------------------------------------------------+