JsonParserByLeo/Src/JsonCore/JsonParser.mqh

1926 lines
64 KiB
MQL5

2026-07-24 07:27:55 -05:00
//+------------------------------------------------------------------+
2026-06-02 21:23:50 -05:00
//| JsonParser.mqh |
//| Copyright 2026, Niquel Mendoza. |
2026-10-08 13:39:44 -05:00
//| https://www.mql5.com |
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
2026-10-08 13:39:44 -05:00
#property link "https://www.mql5.com"
2026-06-02 21:23:50 -05:00
#property strict
2026-10-08 13:39:44 -05:00
#ifndef JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
#define JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-10-03 17:00:34 -05:00
#include "JsonDefines.mqh"
2026-06-02 21:23:50 -05:00
2026-08-03 09:31:58 -05:00
//---
#ifdef JSONPARSERBYLEO_DLL
2026-10-19 07:27:55 -05:00
#include "..\\DLL\\Main.mqh"
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-19 07:41:52 -05:00
class CJsonParser : public CBaseStructuredLan
2026-06-02 21:23:50 -05:00
{
2026-08-04 08:01:50 -05:00
protected:
2026-06-02 21:23:50 -05:00
//---
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
int m_index[];
int m_index_r;
#endif // JSONPARSERBYLEO_DLL
2026-06-02 21:23:50 -05:00
//---
ENUM_TSN_JSON_LAST_ERR m_last_err;
2026-07-19 07:41:52 -05:00
//---
int CalcRegType(const string& file_name) override final;
2026-09-30 07:39:54 -05:00
2026-06-02 21:23:50 -05:00
public:
2026-08-03 09:31:58 -05:00
CJsonParser(void);
2026-06-02 21:23:50 -05:00
~CJsonParser(void) {}
2026-10-08 21:46:49 -05:00
//--- Correct padding
2026-06-03 08:32:38 -05:00
// Para data raw se puede usar el json uchar directamtne
2026-09-18 14:11:09 -05:00
void CorrectPadding();
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
2026-09-18 14:11:09 -05:00
void CorrectPaddingSimd();
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
2026-06-03 07:50:45 -05:00
2026-10-08 21:46:49 -05:00
//--- Parseo
bool AutoParseByFileExt(const int file_ext_type);
2026-06-18 09:48:36 -05:00
bool Parse();
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
2026-09-18 14:11:09 -05:00
__forceinline bool ParseSimd();
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
2026-09-18 14:11:09 -05:00
2026-10-01 08:25:33 -05:00
//--- Errores
2026-06-03 07:50:45 -05:00
__forceinline ENUM_TSN_JSON_LAST_ERR LastErr() const { return m_last_err; }
2026-09-30 07:39:54 -05:00
void CatchErr();
2026-10-03 17:00:34 -05:00
void ErrorInfo(const string header = "");
2026-06-03 07:50:45 -05:00
2026-10-08 21:46:49 -05:00
//--- Config
2026-10-08 13:39:44 -05:00
void Options(const uint f);
2026-10-01 08:25:33 -05:00
//--- Step
2026-06-02 22:52:39 -05:00
__forceinline int GetStep(const int idx) const;
2026-06-03 07:50:45 -05:00
__forceinline int GetStepPure(const int idx) const;
2026-06-03 18:53:05 -05:00
2026-10-08 13:39:44 -05:00
//--- GetRoot
CJsonNode GetRoot();
2026-10-01 08:25:33 -05:00
//--- Info
2026-06-18 08:36:18 -05:00
void PrintCintaTypes(const int start, const int num) const;
2026-06-03 07:50:45 -05:00
2026-10-08 21:46:49 -05:00
//--- Node
2026-10-08 20:25:09 -05:00
void NodeHashing(int curr, const int obj_count, const int bend, int& table_pos);
2026-10-01 08:25:33 -05:00
bool SerializeToDom(CDomNodeBase* root, CDomNodeManager* manager, int cur, const int end);
2026-10-08 21:46:49 -05:00
//--- Strings\Keys
2026-10-06 08:01:09 -05:00
// uso en get value o exatcion
2026-10-08 13:39:44 -05:00
template<typename TKey>
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));
}
2026-10-08 13:39:44 -05:00
template<typename TKey>
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));
}
2026-10-08 21:07:14 -05:00
template<typename TKey>
2026-10-08 21:46:49 -05:00
__forceinline bool GetStrAsStr(int idx, string &res) const
{
return CBSFLUnescape::MakeString<CJsonParser>(m_raw,
TSN_SBL_CLS_STR_START(idx, int),
TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int), res);
}
2026-10-08 21:07:14 -05:00
template<typename TKey>
2026-10-08 21:46:49 -05:00
__forceinline int GetStrAsUArr(int idx, uchar &res[], int pos = 0) const
{
return CBSFLUnescape::MakeUArray<CJsonParser, BSFL_UE_SURROGATES>(m_raw,
TSN_SBL_CLS_STR_START(idx, int),
TSN_SBL_CLS_STR_LEN(idx, (2 - sizeof(TKey)), int), res, pos);
}
2026-10-06 08:01:09 -05:00
2026-10-08 20:25:09 -05:00
//--- Funciones para node (interno de uso interno)
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;
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;
2026-10-01 08:25:33 -05:00
2026-10-08 21:46:49 -05:00
//--- Print error general
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);
2026-07-26 16:46:05 -05:00
//--- Tablas generales
2026-09-30 07:39:54 -05:00
static const string s_dtype_to_str[JSON_VTYPE_TOTAL];
2026-10-05 21:58:00 -05:00
// unescape
static const uchar s_unescape_table[256];
// escape
static const uchar s_escape_table[256];
2026-10-08 13:39:44 -05:00
static string s_str;
2026-07-26 16:46:05 -05:00
};
2026-08-03 09:31:58 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonParser::CJsonParser(void)
{
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)
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
m_index_r = ArrayResize(m_index, 256, 256);
#endif // JSONPARSERBYLEO_DLL
}
2026-07-26 16:46:05 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
void CJsonParser::Options(const uint f)
2026-07-26 16:46:05 -05:00
{
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;
}
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;
2026-09-18 14:11:09 -05:00
ArrayResize(m_cinta, m_len);
}
//---
if(m_len > m_index_r)
2026-09-18 14:11:09 -05:00
{
m_index_r = m_len;
2026-09-18 14:11:09 -05:00
ArrayResize(m_index, m_index_r);
}
}
#endif // JSONPARSERBYLEO_DLL
2026-10-08 13:39:44 -05:00
// {"a":0}
2026-09-18 14:11:09 -05:00
//+------------------------------------------------------------------+
void CJsonParser::CorrectPadding()
{
//---
2026-09-30 07:39:54 -05:00
//const int new_len = ;
ArrayResize(m_raw, m_len + 11);
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
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] = '^'; //
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] = '^';
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);
}
}
2026-06-20 13:57:50 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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--;
//---
2026-10-08 20:25:09 -05:00
void CJsonParser::NodeHashing(int curr, const int obj_count, const int bend, int& table_pos)
2026-06-20 13:57:50 -05:00
{
2026-09-23 15:25:08 -05:00
//--- inicial
BASESPARSERSLAN_START_NODE_HASH(table_pos, curr)
2026-06-20 13:57:50 -05:00
//---
m_tables[table_pos].table_size = obj_count; // Numero de objetos
2026-10-08 13:39:44 -05:00
//--- 4 siempre dado que menos no se permite..
2026-06-28 18:47:50 -05:00
m_pfh.MaxValSeed(m_max_att++);
2026-10-08 13:39:44 -05:00
m_pfh.InitAlg(obj_count, 0.70, 4);
2026-06-20 13:57:50 -05:00
//---
2026-06-21 20:08:59 -05:00
ArrayResize(m_tables[table_pos].pos_arr, obj_count);
2026-06-20 13:57:50 -05:00
//--- Obtnemos las posiciones de incio
2026-06-24 17:20:42 -05:00
ulong keys_h[];
2026-06-28 18:47:50 -05:00
int posiciones[];
2026-06-24 17:20:42 -05:00
ArrayResize(keys_h, obj_count);
2026-06-28 18:47:50 -05:00
ArrayResize(posiciones, obj_count);
2026-06-24 17:20:42 -05:00
int pos_c = 0;
2026-10-08 13:39:44 -05:00
const int lock = curr + 1;
curr += TSN_SBL_SLOT_OBJ_SIZE; // Ahora en key
2026-06-24 17:20:42 -05:00
//---
2026-06-20 13:57:50 -05:00
while(curr < bend)
{
//---
2026-06-24 17:20:42 -05:00
m_tables[table_pos].pos_arr[pos_c] = curr; // Assing
2026-06-20 13:57:50 -05:00
//---
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
2026-06-24 17:20:42 -05:00
{
2026-10-08 13:39:44 -05:00
int i = int(v >> TSN_SBL_BIT_STR_START);
if(!CBSFLUnescape::MakeHash<CJsonParser>(m_raw, i, m_len, hash))
{
BASESPARSERSAN_NODEHASHING_FINISH_ERR
2026-10-08 20:25:09 -05:00
return;
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
2026-06-24 17:20:42 -05:00
}
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
2026-06-20 13:57:50 -05:00
2026-06-24 17:20:42 -05:00
//---
2026-10-08 13:39:44 -05:00
keys_h[pos_c] = hash;
2026-06-28 18:47:50 -05:00
posiciones[pos_c] = pos_c;
pos_c++;
2026-06-20 13:57:50 -05:00
//---
2026-10-08 13:39:44 -05:00
curr += TSN_SBL_KEYSLOT_SIZE; // salta KEY
2026-06-24 17:20:42 -05:00
curr += GetStep(curr); // salta VAL
}
2026-06-20 13:57:50 -05:00
2026-10-08 13:39:44 -05:00
//--- assing de tamaños
2026-06-28 18:47:50 -05:00
const int fn = m_pfh.m_final_table_size;
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);
2026-07-28 21:39:04 -05:00
2026-10-08 13:39:44 -05:00
//--- resize de arrays iniciales
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);
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))
2026-10-08 20:25:09 -05:00
return;
//----
2026-10-08 13:39:44 -05:00
BASESPARSERSAN_NODEHASHING_FINISH_ERR
2026-10-08 20:25:09 -05:00
return;
2026-06-20 13:57:50 -05:00
}
2026-06-24 17:20:42 -05:00
2026-07-19 07:41:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CJsonParser::CalcRegType(const string& file_name)
{
return (int)JPBL_HashExt(file_name);
}
2026-06-18 09:48:36 -05:00
2026-06-21 21:51:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CJsonParser::AutoParseByFileExt(const int file_ext_type)
{
switch(file_ext_type)
{
2026-07-19 07:41:52 -05:00
case TSN_SLF_RAW_FILE:
2026-06-21 21:51:52 -05:00
{
2026-07-19 07:41:52 -05:00
CorrectPadding(); // Auto
2026-06-21 21:51:52 -05:00
return Parse();
}
2026-07-19 07:41:52 -05:00
case TSN_SLF_RAW_EMBEBED:
2026-06-21 21:51:52 -05:00
{
2026-07-19 07:41:52 -05:00
return m_cinta_pos > 0 && m_len > 0;
2026-06-21 21:51:52 -05:00
}
default:
{
m_last_err = TSN_JSON_ERR_INVALID_EXT_FILE;
m_pos = 0;
return false;
}
}
}
2026-06-18 09:48:36 -05:00
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
2026-08-02 16:49:10 -05:00
//| Macros de avanze |
2026-06-02 21:23:50 -05:00
//+------------------------------------------------------------------+
2026-10-08 19:54:46 -05:00
//--- para aumtenar el numero de elementos.
#define TSN_JSON_AUMENT curr_count++;
2026-09-30 07:39:54 -05:00
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]; \
2026-10-18 12:41:33 -05:00
if(((1 << m_next) & curr_state) == 0) \
2026-10-02 22:01:54 -05:00
{ \
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL; \
return false; \
2026-10-03 11:47:17 -05:00
}
2026-10-02 22:01:54 -05:00
2026-06-20 13:57:50 -05:00
//--- Luego de una coma en array
// Luego de una , y KEY siempre siempre valor
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) \
{ \
2026-09-18 14:11:09 -05:00
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL; \
2026-09-30 07:39:54 -05:00
return false; \
}
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++;
2026-08-03 09:31:58 -05:00
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;
//+------------------------------------------------------------------+
2026-09-30 07:39:54 -05:00
//| Parseo de numeros |
//+------------------------------------------------------------------+
2026-09-30 07:39:54 -05:00
//--- make string
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;
2026-09-30 07:39:54 -05:00
2026-08-02 12:33:47 -05:00
//+------------------------------------------------------------------+
2026-08-03 15:01:11 -05:00
//| Parse con simd |
2026-08-02 12:33:47 -05:00
//+------------------------------------------------------------------+
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
2026-08-03 09:31:58 -05:00
#ifdef JSONPARSERBYLEO_DLL
2026-09-18 14:11:09 -05:00
__forceinline bool CJsonParser::ParseSimd()
2026-06-02 21:23:50 -05:00
{
2026-08-03 15:01:11 -05:00
//--- Iniciales
2026-10-19 13:26:09 -05:00
m_pos = m_offset;
2026-07-12 18:24:34 -05:00
m_tables_size = 0;
2026-09-18 14:11:09 -05:00
return JsonParserResolve(m_raw,
m_cinta,
m_index,
m_len,
2026-10-19 07:27:55 -05:00
m_jit_enabled,
2026-09-18 14:11:09 -05:00
(int&)m_last_err,
m_cinta_pos,
m_pos
);
2026-08-02 16:49:10 -05:00
}
2026-08-03 09:31:58 -05:00
#endif // JSONPARSERBYLEO_DLL
2026-08-03 15:01:11 -05:00
2026-08-02 16:49:10 -05:00
//+------------------------------------------------------------------+
2026-08-03 15:01:11 -05:00
//| Parse normal |
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;
2026-10-08 19:54:46 -05:00
//---
uint curr_state = 0;
uint curr_count = 0;
uint curr_padre = 0;
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;
2026-10-18 12:41:33 -05:00
else // No easy
2026-08-02 16:49:10 -05:00
{
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;
2026-10-18 12:41:33 -05:00
else // Single value
2026-08-02 16:49:10 -05:00
{
2026-10-08 19:54:46 -05:00
m_next = TSN_JSON_TOK_INVALID;
2026-08-02 16:49:10 -05:00
}
}
//--- Bucle
while(true)
{
switch(m_next)
{
//---
case TSN_JSON_TOK_NUMBER_NEG:
2026-08-02 16:49:10 -05:00
{
2026-09-30 07:39:54 -05:00
//--- solo 3 varaibles nada mas en general (garantizado)
long v = 0;
2026-10-08 13:39:44 -05:00
const uint start = m_pos;
2026-09-30 07:39:54 -05:00
uchar ch = m_raw[++m_pos] ^ '0';
2026-08-02 16:49:10 -05:00
//---
2026-09-30 07:39:54 -05:00
switch(0)
{
default: // scope con psoiblidad de break.
{
//--- primera iteracion sin cheking
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(v)
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
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_17(v)
2026-10-01 13:36:22 -05:00
STRCONV_TOV_ALG(v, ch)
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)
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
2026-09-30 07:39:54 -05:00
}
//--- revismoos si es dec, si lo es saltamos la parte dec
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_DEC(ch))
break;
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
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_DEC(ch))
2026-09-30 07:39:54 -05:00
{
long exponente = 0; // exponente
2026-10-08 13:39:44 -05:00
uint digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_PDEC(ch))
2026-09-30 07:39:54 -05:00
{
2026-10-08 13:39:44 -05:00
uint ds = ++m_pos; // inicio
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)
{
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
2026-09-30 07:39:54 -05:00
break;
}
//---
ds = (m_pos - ds); // numero de digitos de la parte decimal
digitos += ds;
exponente -= ds;
}
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_E(ch)) //
2026-09-30 07:39:54 -05:00
{
bool exp_positivo = true;
ch = m_raw[++m_pos] ^ '0';
if(ch > 9)
{
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_MINUS(ch))
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
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(expo)
2026-09-30 07:39:54 -05:00
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_SKIP_LZ
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..
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
STRCONV_TOV_ALG(expo, ch)
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
{
2026-10-02 22:01:54 -05:00
if(expo > 0) // es valido
2026-09-30 07:39:54 -05:00
break; // no ov
}
else // sigue saltamos todo lo que hya
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
2026-09-30 07:39:54 -05:00
}
expo = INT_MAX;
2026-10-02 22:01:54 -05:00
break;
2026-09-30 07:39:54 -05:00
}
exponente += exp_positivo ? expo : -expo;
}
2026-10-02 22:01:54 -05:00
//--- 1 dado que start incluye el -
if(STRCONV_DOUBLE_SAFE_DBL_P(digitos, exponente, 1))
2026-09-30 07:39:54 -05:00
{
TsnBitInterprete bit;
2026-10-02 22:01:54 -05:00
bit.double_value = -STRCONV_TO_DOUBLE_ALG(exponente, v);
2026-09-30 07:39:54 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = bit.ulong_value;
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;
}
2026-08-02 16:49:10 -05:00
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
2026-08-02 16:49:10 -05:00
//---
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_NUMBER:
{
//---
2026-10-08 13:39:44 -05:00
const uint start = m_pos;
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';
2026-08-02 16:49:10 -05:00
2026-09-30 07:39:54 -05:00
//---
switch(0)
{
default: // scope con psoiblidad de break.
{
//---
2026-10-18 12:41:33 -05:00
if(ch > 9) // Mayor
break;
if(!v) // LZ
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
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
2026-10-01 13:36:22 -05:00
STRCONV_TOV_ALG(v, ch)
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)
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
2026-09-30 07:39:54 -05:00
}
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;
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
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
2026-09-30 07:39:54 -05:00
{
long exponente = 0; // exponente
2026-10-08 13:39:44 -05:00
uint digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
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)
2026-09-30 07:39:54 -05:00
{
2026-10-08 13:39:44 -05:00
uint ds = ++m_pos;
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)
{
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
2026-09-30 07:39:54 -05:00
break;
}
//---
ds = (m_pos - ds); // numero de digitos de la parte decimal
digitos += ds;
exponente -= ds;
}
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_E(ch)) //
2026-09-30 07:39:54 -05:00
{
bool exp_positivo = true;
ch = m_raw[++m_pos] ^ '0';
if(ch > 9)
{
2026-10-02 22:01:54 -05:00
if(STRCONV_DECX_CH_IS_MINUS(ch))
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;
2026-10-02 22:01:54 -05:00
while(true)
2026-09-30 07:39:54 -05:00
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_U1(expo)
2026-09-30 07:39:54 -05:00
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_SKIP_LZ
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..
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
STRCONV_TOV_ALG(expo, ch)
2026-09-30 07:39:54 -05:00
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
{
2026-10-02 22:01:54 -05:00
if(expo > 0) // es valido
2026-09-30 07:39:54 -05:00
break; // no ov
}
else // sigue saltamos todo lo que hya
{
2026-10-02 22:01:54 -05:00
DOMBASEUTIL_NUM_SKIP_NUMBER
2026-09-30 07:39:54 -05:00
}
expo = INT_MAX;
2026-10-02 22:01:54 -05:00
break;
2026-09-30 07:39:54 -05:00
}
exponente += exp_positivo ? expo : -expo;
}
2026-10-02 22:01:54 -05:00
//---
if(STRCONV_DOUBLE_SAFE_DBL(digitos, exponente))
2026-09-30 07:39:54 -05:00
{
TsnBitInterprete bit;
2026-10-02 22:01:54 -05:00
bit.double_value = STRCONV_TO_DOUBLE_ALG(exponente, v);
2026-09-30 07:39:54 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = bit.ulong_value;
2026-09-30 07:39:54 -05:00
}
2026-10-02 22:01:54 -05:00
else
2026-09-30 07:39:54 -05:00
{
JSONPARSERBYLEO_NUM_MAKE_STRING
}
}
else
{
m_cinta[m_cinta_pos++] = JSON_VTYPE_UINTEGER;
2026-10-08 13:39:44 -05:00
m_cinta[m_cinta_pos++] = v;
2026-09-30 07:39:54 -05:00
}
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
//---
case TSN_JSON_TOK_STRING:
{
//---
2026-10-08 13:39:44 -05:00
const uint start = ++m_pos;
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;
2026-10-17 15:35:59 -05:00
ulong has_bs = TSNTABLES_SWAR_HAS(x_bs);
ulong has_qt = TSNTABLES_SWAR_HAS(x_qt);
2026-08-02 16:49:10 -05:00
//---
2026-10-17 15:35:59 -05:00
if((has_bs | has_qt) == 0) // Fast path
2026-08-02 16:49:10 -05:00
{
m_pos += 8;
continue;
}
//---
2026-10-18 12:41:33 -05:00
if(has_bs == 0) // Si not iene bs (pero confirmamos que no es 0) (Fast path)
2026-08-02 16:49:10 -05:00
{
2026-10-17 15:35:59 -05:00
const ulong flag_real = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
2026-08-27 13:40:38 -05:00
m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag_real);
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
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;
2026-08-02 16:49:10 -05:00
m_pos++; // Luego del "
break;
}
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);
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");
//---
2026-09-18 14:11:09 -05:00
if(qt_final) // Hay un qt real de cierre
2026-08-02 16:49:10 -05:00
{
2026-09-18 14:11:09 -05:00
//---
2026-08-02 16:49:10 -05:00
// Avanzamos y cerramos..
2026-08-27 13:40:38 -05:00
m_pos += g_tsntables_table_ctz_i8[qt_final];
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
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;
2026-09-18 14:11:09 -05:00
//---
m_pos++;
2026-08-02 16:49:10 -05:00
break;
}
else
{
2026-10-17 15:35:59 -05:00
m_pos += 8;// + ((prev & compacted_bs) >> 7U);
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
}
}
}
2026-10-17 15:35:59 -05:00
2026-08-02 16:49:10 -05:00
#else // JSONPARSERBYLEO_DESACTIVE_SWAR
//--- Char por char
2026-10-17 15:35:59 -05:00
uchar c;
while(true) // Find unrrolled 20
2026-08-02 16:49:10 -05:00
{
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
2026-08-02 16:49:10 -05:00
}
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++;
2026-08-02 16:49:10 -05:00
#endif // JSONPARSERBYLEO_DESACTIVE_SWAR
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
//---
break;
}
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_BOOL_TRUE:
2026-08-02 16:49:10 -05:00
{
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)
2026-09-30 07:39:54 -05:00
return false;
2026-08-02 16:49:10 -05:00
2026-09-30 07:39:54 -05:00
//---
m_pos++;
2026-10-08 19:54:46 -05:00
m_cinta[m_cinta_pos++] = (JSON_VTYPE_BOOLEAN | 1ULL << TSN_SBL_BIT_START_BOOL);
2026-08-02 16:49:10 -05:00
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_BOOL_FALSE:
2026-08-02 16:49:10 -05:00
{
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;
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++;
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_BOOLEAN;
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
case TSN_JSON_TOK_NULL:
{
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)
2026-09-30 07:39:54 -05:00
return false;
2026-08-02 16:49:10 -05:00
//---
2026-09-30 07:39:54 -05:00
m_pos++;
2026-08-02 16:49:10 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_NULL;
//---
2026-09-18 14:11:09 -05:00
TSN_JSON_AUMENT
2026-08-02 16:49:10 -05:00
TSN_JSON_NEXT_NO_NEXT_KEY
break;
}
2026-09-30 07:39:54 -05:00
case TSN_JSON_TOK_COMMA:
2026-08-02 16:49:10 -05:00
{
2026-10-08 19:54:46 -05:00
if(curr_state == TSN_JSON_CTX_IN_OBJ)
2026-08-02 16:49:10 -05:00
{
2026-09-30 07:39:54 -05:00
while(m_raw[++m_pos] != '"') {}
m_next = TSN_JSON_TOK_KEY;
2026-08-02 16:49:10 -05:00
}
else
{
TSN_JSON_NEXT_VALUE_COMM_KEY
}
break;
}
2026-10-17 15:35:59 -05:00
case TSN_JSON_TOK_LLAVE_INI:
2026-08-02 16:49:10 -05:00
{
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;
2026-08-02 16:49:10 -05:00
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
2026-10-08 19:54:46 -05:00
if(_c == '}')
m_next = TSN_JSON_TOK_LLAVE_END;
2026-10-18 12:41:33 -05:00
else
{
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;
2026-10-08 19:54:46 -05:00
}
2026-10-18 12:41:33 -05:00
2026-08-02 16:49:10 -05:00
//---
break;
}
case TSN_JSON_TOK_COR_INI:
{
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 [
2026-10-08 13:39:44 -05:00
uchar _c = m_raw[++m_pos];
2026-10-02 22:01:54 -05:00
while(_c < 33)
_c = m_raw[++m_pos];
2026-10-08 19:54:46 -05:00
//- check
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;
}
2026-10-03 11:47:17 -05:00
2026-08-02 16:49:10 -05:00
//---
break;
}
case TSN_JSON_TOK_LLAVE_END:
{
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 |
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;
2026-08-02 16:49:10 -05:00
2026-10-08 19:54:46 -05:00
curr_padre = uint(v >> TSN_SBL_BIT_START_NUM_C); // ahora obtenemos su padre..
2026-08-02 16:49:10 -05:00
//---
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...
2026-10-08 19:54:46 -05:00
return true;
2026-08-02 16:49:10 -05:00
//---
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);
2026-08-02 16:49:10 -05:00
m_pos++;
//---
TSN_JSON_NEXT_NO_NEXT_KEY
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 |
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;
2026-10-08 19:54:46 -05:00
curr_padre = uint(v >> TSN_SBL_BIT_START_NUM_C); // ahora obtenemos su padre..
2026-08-02 16:49:10 -05:00
//---
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...
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
2026-08-02 16:49:10 -05:00
break;
}
case TSN_JSON_TOK_KEY:
{
2026-10-08 13:39:44 -05:00
const uint start = ++m_pos;
2026-08-02 16:49:10 -05:00
2026-06-20 13:57:50 -05:00
//--- Char por char
2026-10-03 11:47:17 -05:00
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
2026-06-20 13:57:50 -05:00
while(true)
{
2026-07-19 07:41:52 -05:00
const uchar c = m_raw[m_pos];
2026-06-20 13:57:50 -05:00
if(c == '\\')
{
m_pos += 2;
continue;
}
if(c == '"')
{
2026-06-20 14:18:38 -05:00
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
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;
2026-06-20 13:57:50 -05:00
m_pos++;
break;
}
2026-10-03 11:47:17 -05:00
m_pos++;
}
2026-10-03 11:47:17 -05:00
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS*/
//---
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
}
2026-10-03 17:00:34 -05:00
2026-10-03 11:47:17 -05:00
//---
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
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;
2026-10-03 11:47:17 -05:00
m_pos++;
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
2026-10-08 13:39:44 -05:00
//---
m_cinta_pos++; // hash ignoramos.
2026-06-20 13:57:50 -05:00
//--- Find :
2026-10-18 12:41:33 -05:00
while(m_raw[m_pos] != ':')
{
2026-06-14 15:51:39 -05:00
//---
2026-10-18 12:41:33 -05:00
//if(m_raw[m_pos] == ':')
// break;
2026-06-14 15:51:39 -05:00
//---
2026-06-20 13:57:50 -05:00
m_pos++;
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
2026-06-20 13:57:50 -05:00
TSN_JSON_NEXT_VALUE_COMM_KEY
2026-06-02 21:23:50 -05:00
//---
break;
}
default:
return false;
}
}
}
2026-06-20 13:57:50 -05:00
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
//| GetStep |
2026-06-02 22:52:39 -05:00
//+------------------------------------------------------------------+
2026-06-03 07:50:45 -05:00
__forceinline int CJsonParser::GetStepPure(const int idx) const
2026-06-02 22:52:39 -05:00
{
2026-09-30 07:39:54 -05:00
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
2026-06-02 22:52:39 -05:00
{
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
2026-07-19 07:41:52 -05:00
case JSON_VTYPE_OBJ:
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_INTEGER:
case JSON_VTYPE_REAL:
return 2;
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_BOOLEAN:
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_STRING:
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_NULL:
return 1;
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
return TSN_SBL_KEYSLOT_SIZE;
2026-09-23 15:25:08 -05:00
default:
return 1;
2026-06-03 07:50:45 -05:00
}
}
//+------------------------------------------------------------------+
__forceinline int CJsonParser::GetStep(const int idx)
const
{
2026-08-28 11:16:09 -05:00
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
2026-06-03 07:50:45 -05:00
{
2026-07-19 07:41:52 -05:00
case JSON_VTYPE_ARR:
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_OBJ:
2026-07-19 07:41:52 -05:00
return int(m_cinta[idx] >> TSN_SBL_BIT_START_NUM_C);
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_INTEGER:
case JSON_VTYPE_REAL:
return 2;
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_BOOLEAN:
2026-06-03 07:50:45 -05:00
case JSON_VTYPE_STRING:
2026-06-02 22:52:39 -05:00
case JSON_VTYPE_NULL:
return 1;
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_KEY:
return TSN_SBL_KEYSLOT_SIZE;
2026-09-23 15:25:08 -05:00
default:
return 1;
2026-06-02 22:52:39 -05:00
}
}
2026-06-03 07:50:45 -05:00
//+------------------------------------------------------------------+
//| |
2026-07-19 13:56:15 -05:00
//+------------------------------------------------------------------+
2026-10-01 08:25:33 -05:00
bool CJsonParser::SerializeToDom(CDomNodeBase *root, CDomNodeManager* manager, int cur, const int end)
2026-07-19 13:56:15 -05:00
{
//--- Temp
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_NOT_ERR;
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];
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);
2026-07-19 15:11:32 -05:00
2026-07-19 13:56:15 -05:00
//---
current_container[0] = root;
current_ends[sp] = end;
//---
cur += 2;
//--- It
while(true)
{
//--- Check
2026-07-21 10:38:19 -05:00
while(cur >= current_ends[sp])
2026-07-19 13:56:15 -05:00
{
sp--; // Nivel menos
2026-07-19 15:11:32 -05:00
//Print("sp luego: ", sp);
if(sp < 0)
2026-10-01 08:25:33 -05:00
return true;
2026-07-19 13:56:15 -05:00
}
//---
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
2026-07-19 15:11:32 -05:00
//Print(EnumToString(tipo), " | ", cur, " | " , sp);
2026-07-19 13:56:15 -05:00
//---
switch(tipo)
{
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
2026-07-19 13:56:15 -05:00
{
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)
2026-07-19 13:56:15 -05:00
{
const int lock = sp++;
2026-07-19 15:11:32 -05:00
current_container[sp] = new CDomNodeBase(manager);
2026-10-08 13:39:44 -05:00
current_container[sp].NewArr(count);
2026-07-19 13:56:15 -05:00
current_container[lock].AddItem(current_container[sp]);
}
2026-10-08 13:39:44 -05:00
else // {key:[]}
2026-07-19 13:56:15 -05:00
{
sp++;
2026-10-08 13:39:44 -05:00
prev_value.NewArr(count);
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;
}
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_OBJ:
2026-07-19 13:56:15 -05:00
{
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) // [{}]
2026-07-19 13:56:15 -05:00
{
const int lock = sp++;
2026-07-19 15:11:32 -05:00
current_container[sp] = new CDomNodeBase(manager);
2026-10-08 13:39:44 -05:00
current_container[sp].NewObj(count);
2026-07-19 13:56:15 -05:00
current_container[lock].AddItem(current_container[sp]);
}
2026-10-08 13:39:44 -05:00
else // {key:{}}
2026-07-19 13:56:15 -05:00
{
sp++;
2026-10-08 13:39:44 -05:00
prev_value.NewObj(count);
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;
}
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
{
if(current_container[sp].m_type == JSON_VTYPE_ARR)
2026-10-08 21:07:14 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, m_cinta[cur + 1]));
2026-09-30 07:39:54 -05:00
else
2026-10-08 21:07:14 -05:00
prev_value = m_cinta[cur + 1];
2026-09-30 07:39:54 -05:00
break;
}
2026-07-19 13:56:15 -05:00
case JSON_VTYPE_INTEGER:
{
if(current_container[sp].m_type == JSON_VTYPE_ARR)
2026-10-08 21:07:14 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, (long)m_cinta[cur + 1]));
2026-07-19 13:56:15 -05:00
else
2026-10-08 21:07:14 -05:00
prev_value = (long)m_cinta[cur + 1];
2026-07-19 13:56:15 -05:00
break;
}
case JSON_VTYPE_REAL:
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_cinta[cur + 1];
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
2026-07-24 08:54:26 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, un.double_value));
2026-07-19 13:56:15 -05:00
else
prev_value = un.double_value;
break;
}
case JSON_VTYPE_BOOLEAN:
{
2026-10-08 19:54:46 -05:00
const bool v = (m_cinta[cur] >> TSN_SBL_BIT_START_BOOL) != 0;
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
2026-07-24 08:54:26 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager, v));
2026-07-19 13:56:15 -05:00
else
prev_value = v;
break;
}
case JSON_VTYPE_STRING:
{
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);
2026-07-19 13:56:15 -05:00
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
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;
2026-10-08 13:39:44 -05:00
if(!JSONPBL_MAKESTRING(m_raw, s, slen, manager.m_string_stack[idx]))
2026-10-01 08:25:33 -05:00
{
2026-10-08 13:39:44 -05:00
m_pos = s;
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
return false;
}
}
2026-07-19 13:56:15 -05:00
else
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;
2026-10-08 13:39:44 -05:00
if(!JSONPBL_MAKESTRING(m_raw, s, slen, manager.m_string_stack[idx]))
2026-10-01 08:25:33 -05:00
{
2026-10-08 13:39:44 -05:00
m_pos = s;
2026-10-01 08:25:33 -05:00
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
return false;
}
}
2026-07-19 13:56:15 -05:00
break;
}
case JSON_VTYPE_NULL:
{
//---
if(current_container[sp].m_type == JSON_VTYPE_ARR)
2026-07-19 15:11:32 -05:00
current_container[sp].AddItem(new CDomNodeBase(manager));
2026-07-19 13:56:15 -05:00
else
prev_value.m_type = JSON_VTYPE_NULL;
break;
}
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;
}
2026-07-19 13:56:15 -05:00
default:
break;
}
//---
cur += GetStepPure(cur);
}
2026-10-01 08:25:33 -05:00
//---
return false;
2026-07-19 13:56:15 -05:00
}
//+------------------------------------------------------------------+
//| |
2026-06-03 07:50:45 -05:00
//+------------------------------------------------------------------+
2026-06-18 08:36:18 -05:00
void CJsonParser::PrintCintaTypes(const int start, const int num) const
2026-06-03 07:50:45 -05:00
{
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);
2026-10-01 08:25:33 -05:00
//---
string text;
StringReserve(text, 256); // algo razonable.
2026-06-18 08:36:18 -05:00
//---
while(p < end)
2026-06-03 07:50:45 -05:00
{
2026-07-19 07:41:52 -05:00
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[p] & TSN_SBL_BIT_MASK_TYPE);
2026-10-01 08:25:33 -05:00
text = "[" + (string)p + "] " + EnumToString(tipo) + " | ";
2026-06-03 15:48:09 -05:00
//---
switch(tipo)
{
2026-10-08 13:39:44 -05:00
case JSON_VTYPE_ARR:
2026-07-19 07:41:52 -05:00
{
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;
2026-07-19 07:41:52 -05:00
break;
}
case JSON_VTYPE_OBJ:
{
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;
2026-07-19 07:41:52 -05:00
break;
}
2026-09-30 07:39:54 -05:00
case JSON_VTYPE_UINTEGER:
{
text += "val=" + CValueToBuffer::ULLToStr(ulong(m_cinta[p + 1]));
break;
}
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_INTEGER:
2026-07-19 07:41:52 -05:00
{
2026-06-03 15:48:09 -05:00
text += "val=" + (string)m_cinta[p + 1];
break;
2026-07-19 07:41:52 -05:00
}
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_REAL:
{
2026-08-28 08:28:32 -05:00
TsnBitInterprete un;
2026-10-08 13:39:44 -05:00
un.ulong_value = m_cinta[p + 1];
text += "val=" + (string)un.double_value;
break;
}
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_BOOLEAN:
2026-10-08 19:54:46 -05:00
text += "val=" + (string)(bool)((m_cinta[p] >> TSN_SBL_BIT_START_BOOL) & 1);
2026-06-03 15:48:09 -05:00
break;
case JSON_VTYPE_STRING:
{
2026-07-19 07:41:52 -05:00
const int s = int(m_cinta[p] >> TSN_SBL_BIT_STR_START);
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));
2026-10-01 08:25:33 -05:00
//---
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 + "\"";
2026-10-01 08:25:33 -05:00
else
text += "start=" + (string)s + " len=" + (string)slen + " val=Invalid";
break;
}
2026-06-03 15:48:09 -05:00
case JSON_VTYPE_NULL:
text += "null";
break;
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;
}
2026-09-23 15:25:08 -05:00
//---
default:
break;
2026-06-03 15:48:09 -05:00
}
Print(text);
2026-06-03 07:50:45 -05:00
p += GetStepPure(p);
}
}
2026-10-01 08:25:33 -05:00
//+------------------------------------------------------------------+
2026-10-08 13:39:44 -05:00
//| Errores |
2026-10-01 08:25:33 -05:00
//+------------------------------------------------------------------+
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)
2026-10-01 08:25:33 -05:00
{
//---
2026-10-03 17:00:34 -05:00
string out = "";
out.Reserve(256);
2026-10-01 08:25:33 -05:00
//---
2026-10-03 17:00:34 -05:00
if(header.Length())
out += "[" + header + "]\n";
2026-10-01 08:25:33 -05:00
//---
2026-10-03 17:00:34 -05:00
out += StringFormat("JSON error at line %d, col %d:\n", line, col);
2026-10-01 08:25:33 -05:00
//---
2026-10-03 17:00:34 -05:00
switch(err)
2026-10-01 08:25:33 -05:00
{
case TSN_JSON_ERR_INVALID_EXT_FILE:
2026-10-03 17:00:34 -05:00
out += "Invalid file extension por JsonParserByLeo";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_INVALID_CHAR:
2026-10-03 17:00:34 -05:00
out += "Invalid character found in json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL:
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding comma or context close (], })";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI:
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding valid value after '['";
2026-10-01 08:25:33 -05:00
break;
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;
2026-10-01 08:25:33 -05:00
case TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL:
2026-10-03 17:00:34 -05:00
out += "Invalid character find in json, finding valid value";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS:
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.\"";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFOMED_LEN_SUPERADO:
2026-10-03 17:00:34 -05:00
out += "Len has superated, but json are not closed, malformed json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_JSON_NOT_FINISH:
2026-10-03 17:00:34 -05:00
out += "Json read has finish but not closed in ] or }, malformed json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_LEADING_ZEROS:
2026-10-03 17:00:34 -05:00
out += "A number in JSON notation cannot have leading zeros.";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_EXP:
2026-10-03 17:00:34 -05:00
out += "A number was expected after the 'E' exponent; an invalid character was found.";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP:
2026-10-03 17:00:34 -05:00
out += "A numeric value was expected after the decimal point.";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_TRUE:
2026-10-03 17:00:34 -05:00
out += "Malformed 'true' in json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_FALSE:
2026-10-03 17:00:34 -05:00
out += "Malformed 'false' in json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_MALFORMED_NULL:
2026-10-03 17:00:34 -05:00
out += "Malformed 'null' in json";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR:
2026-10-03 17:00:34 -05:00
out += "Error materializing string; possible causes include an invalid escape character or a malformed \\u sequence.";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_NOT_STRUCUTURAL_CHARS_FOUND:
2026-10-03 17:00:34 -05:00
out += "Not structural character found in this json ({ | } | [ | ] | : | ,)";
2026-10-01 08:25:33 -05:00
break;
case TSN_JSON_ERR_INVALID_STATE_IN_PARSE_DOUBLE_E:
2026-10-03 17:00:34 -05:00
out += "Invalid state for Json Sax Parsing, in parse double value";
2026-10-01 08:25:33 -05:00
break;
//---
default:
2026-10-03 17:00:34 -05:00
out += "Unknow error";
2026-10-01 08:25:33 -05:00
break;
}
//---
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)
2026-10-01 08:25:33 -05:00
{
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:
{
2026-10-19 09:16:24 -05:00
if(m_next == TSN_JSON_TOK_INVALID) // Solo si es tok invalid (si no nada)
2026-10-03 17:00:34 -05:00
m_last_err = TSN_JSON_ERR_INVALID_CHAR;
break;
}
2026-10-01 08:25:33 -05:00
}
}
2026-09-30 07:39:54 -05:00
//+------------------------------------------------------------------+
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);
}
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",
""
};
const uchar CJsonParser::s_unescape_table[256] =
{
// char idx ascii
//--- WS \ Invalid
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2026-09-30 07:39:54 -05:00
//---
2026-10-08 13:39:44 -05:00
'"', // 0 0x22 \" = "
0xFF, // 1 0x23 #
0xFF, // 2 0x24 $
0xFF, // 3 0x25 %
0xFF, // 4 0x26 &
0xFF, // 5 0x27 ' \' = '
0xFF, // 6 0x28 (
0xFF, // 7 0x29 )
0xFF, // 8 0x2A *
0xFF, // 9 0x2B +
0xFF, // 10 0x2C ,
0xFF, // 11 0x2D -
0xFF, // 12 0x2E .
'/', // 13 0x2F / \/ = /
0xFF, // 14 0x30
0xFF, // 15 0x31 1
0xFF, // 16 0x32 2
0xFF, // 17 0x33 3
0xFF, // 18 0x34 4
0xFF, // 19 0x35 5
0xFF, // 20 0x36 6
0xFF, // 21 0x37 7
0xFF, // 22 0x38 8
0xFF, // 23 0x39 9
0xFF, // 24 0x3A :
0xFF, // 25 0x3B ;
0xFF, // 26 0x3C <
0xFF, // 27 0x3D =
0xFF, // 28 0x3E >
0xFF, // 29 0x3F ?
0xFF, // 30 0x40 @
0xFF, // 31 0x41 A
0xFF, // 32 0x42 B
0xFF, // 33 0x43 C
0xFF, // 34 0x44 D
0xFF, // 35 0x45 E
0xFF, // 36 0x46 F
0xFF, // 37 0x47 G
0xFF, // 38 0x48 H
0xFF, // 39 0x49 I
0xFF, // 40 0x4A J
0xFF, // 41 0x4B K
0xFF, // 42 0x4C L
0xFF, // 43 0x4D M
0xFF, // 44 0x4E N
0xFF, // 45 0x4F O
0xFF, // 46 0x50 P
0xFF, // 47 0x51 Q
0xFF, // 48 0x52 R
0xFF, // 49 0x53 S
0xFF, // 50 0x54 T
0xFF, // 51 0x55 U
0xFF, // 52 0x56 V
0xFF, // 53 0x57 W
0xFF, // 54 0x58 X
0xFF, // 55 0x59 Y
0xFF, // 56 0x5A Z
0xFF, // 57 0x5B [
'\\', // 58 0x5C \ \\ =
0xFF, // 59 0x5D ]
0xFF, // 60 0x5E ^
0xFF, // 61 0x5F _
0xFF, // 62 0x60 `
0xFF, // 63 0x61 a
0x08, // 64 0x62 b \b = backspace
0xFF, // 65 0x63 c
0xFF, // 66 0x64 d
0xFF, // 67 0x65 e
0x0C, // 68 0x66 f \f = form feed
0xFF, // 69 0x67 g
0xFF, // 70 0x68 h
0xFF, // 71 0x69 i
0xFF, // 72 0x6A j
0xFF, // 73 0x6B k
0xFF, // 74 0x6C l
0xFF, // 75 0x6D m
0x0A, // 76 0x6E n \n = newline
0xFF, // 77 0x6F o
0xFF, // 78 0x70 p
0xFF, // 79 0x71 q
0x0D, // 80 0x72 r \r = carriage return
0xFF, // 81 0x73 s
0x09, // 82 0x74 t \t = tab
TSN_TABLE_UNESCAPE_UNICODE, // 83 0x75 u \uXXXX unicode
0xFF, // 84 0x76 v
0xFF, // 85 0x77 w
0xFF, // 86 0x78 x
0xFF, // 87 0x79 y
0xFF, // 88 0x7A z
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x7B - 0x7F
//--- Extended / high range (0x80 - 0xFF): all invalid for JSON escape context
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
const uchar CJsonParser::s_escape_table[256] =
{
//--- 0x00–0x1F: caracteres de control
TSN_TABLE_ESCAPE_UNICODE, // 0x00 \0 null
TSN_TABLE_ESCAPE_UNICODE, // 0x01 
TSN_TABLE_ESCAPE_UNICODE, // 0x02 
TSN_TABLE_ESCAPE_UNICODE, // 0x03 
TSN_TABLE_ESCAPE_UNICODE, // 0x04 
TSN_TABLE_ESCAPE_UNICODE, // 0x05 
TSN_TABLE_ESCAPE_UNICODE, // 0x06 
TSN_TABLE_ESCAPE_UNICODE, // 0x07
'b', // 0x08 \b backspace
't', // 0x09 \t tab
'n', // 0x0A \n newline
TSN_TABLE_ESCAPE_UNICODE, // 0x0B \v
'f', // 0x0C \f form feed
'r', // 0x0D \r carriage return
TSN_TABLE_ESCAPE_UNICODE, // 0x0E 
TSN_TABLE_ESCAPE_UNICODE, // 0x0F 
TSN_TABLE_ESCAPE_UNICODE, // 0x10 
TSN_TABLE_ESCAPE_UNICODE, // 0x11 
TSN_TABLE_ESCAPE_UNICODE, // 0x12 
TSN_TABLE_ESCAPE_UNICODE, // 0x13 
TSN_TABLE_ESCAPE_UNICODE, // 0x14 
TSN_TABLE_ESCAPE_UNICODE, // 0x15 
TSN_TABLE_ESCAPE_UNICODE, // 0x16 
TSN_TABLE_ESCAPE_UNICODE, // 0x17 
TSN_TABLE_ESCAPE_UNICODE, // 0x18 
TSN_TABLE_ESCAPE_UNICODE, // 0x19 
TSN_TABLE_ESCAPE_UNICODE, // 0x1A 
TSN_TABLE_ESCAPE_UNICODE, // 0x1B
TSN_TABLE_ESCAPE_UNICODE, // 0x1C 
TSN_TABLE_ESCAPE_UNICODE, // 0x1D 
TSN_TABLE_ESCAPE_UNICODE, // 0x1E 
TSN_TABLE_ESCAPE_UNICODE, // 0x1F 
//--- 0x20–0x21: imprimibles
0xFF, // 0x20 ' ' space
0xFF, // 0x21 !
//--- 0x22: comilla doble
'"', // 0x22 \"
//--- 0x23–0x26: imprimibles
0xFF, // 0x23 #
0xFF, // 0x24 $
0xFF, // 0x25 %
0xFF, // 0x26 &
//--- 0x27: comilla simple
0xFF, // 0x27 \'
//--- 0x28–0x2E: imprimibles
0xFF, // 0x28 (
0xFF, // 0x29 )
0xFF, // 0x2A *
0xFF, // 0x2B +
0xFF, // 0x2C ,
0xFF, // 0x2D -
0xFF, // 0x2E .
//--- 0x2F: slash
'/', // 0x2F \/
//--- 0x30–0x5B: imprimibles
0xFF, // 0x30 0
0xFF, // 0x31 1
0xFF, // 0x32 2
0xFF, // 0x33 3
0xFF, // 0x34 4
0xFF, // 0x35 5
0xFF, // 0x36 6
0xFF, // 0x37 7
0xFF, // 0x38 8
0xFF, // 0x39 9
0xFF, // 0x3A :
0xFF, // 0x3B ;
0xFF, // 0x3C <
0xFF, // 0x3D =
0xFF, // 0x3E >
0xFF, // 0x3F ?
0xFF, // 0x40 @
0xFF, // 0x41 A
0xFF, // 0x42 B
0xFF, // 0x43 C
0xFF, // 0x44 D
0xFF, // 0x45 E
0xFF, // 0x46 F
0xFF, // 0x47 G
0xFF, // 0x48 H
0xFF, // 0x49 I
0xFF, // 0x4A J
0xFF, // 0x4B K
0xFF, // 0x4C L
0xFF, // 0x4D M
0xFF, // 0x4E N
0xFF, // 0x4F O
0xFF, // 0x50 P
0xFF, // 0x51 Q
0xFF, // 0x52 R
0xFF, // 0x53 S
0xFF, // 0x54 T
0xFF, // 0x55 U
0xFF, // 0x56 V
0xFF, // 0x57 W
0xFF, // 0x58 X
0xFF, // 0x59 Y
0xFF, // 0x5A Z
0xFF, // 0x5B [
//--- 0x5C: backslash
'\\', // 0x5C \\
//--- 0x5D–0x7E: imprimibles
0xFF, // 0x5D ]
0xFF, // 0x5E ^
0xFF, // 0x5F _
0xFF, // 0x60 `
0xFF, // 0x61 a
0xFF, // 0x62 b
0xFF, // 0x63 c
0xFF, // 0x64 d
0xFF, // 0x65 e
0xFF, // 0x66 f
0xFF, // 0x67 g
0xFF, // 0x68 h
0xFF, // 0x69 i
0xFF, // 0x6A j
0xFF, // 0x6B k
0xFF, // 0x6C l
0xFF, // 0x6D m
0xFF, // 0x6E n
0xFF, // 0x6F o
0xFF, // 0x70 p
0xFF, // 0x71 q
0xFF, // 0x72 r
0xFF, // 0x73 s
0xFF, // 0x74 t
0xFF, // 0x75 u
0xFF, // 0x76 v
0xFF, // 0x77 w
0xFF, // 0x78 x
0xFF, // 0x79 y
0xFF, // 0x7A z
0xFF, // 0x7B {
0xFF, // 0x7C |
0xFF, // 0x7D }
0xFF, // 0x7E ~
//--- 0x7F: DEL (control)
TSN_TABLE_ESCAPE_UNICODE, // 0x7F 
//--- 0x80–0xFF: extended ASCII → \uXXXX
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0x80–0x87
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, // 0x88–0x8F
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0x90–0x97
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0x98–0x9F
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xA0–0xA7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xA8–0xAF
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xB0–0xB7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xB8–0xBF
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xC0–0xC7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xC8–0xCF
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xD0–0xD7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xD8–0xDF
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xE0–0xE7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xE8–0xEF
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xF0–0xF7
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE,
TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, TSN_TABLE_ESCAPE_UNICODE, // 0xF8–0xFF
};
2026-06-02 21:23:50 -05:00
}
2026-10-08 13:39:44 -05:00
#endif // JSONPARSERBYLEO_SRC_JSONCORE_JSONPARSER_MQH
//+------------------------------------------------------------------+