2026-06-03 14:16:03 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-06-02 21:23:50 -05:00
|
|
|
//| JsonParser.mqh |
|
|
|
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
|
|
|
//| https://www.mql5.com/ |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
|
|
|
#property link "https://www.mql5.com/"
|
|
|
|
|
#property strict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef JSONPARSERBYLEO_SRC_JSONPARSER_MQH
|
|
|
|
|
#define JSONPARSERBYLEO_SRC_JSONPARSER_MQH
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-18 09:48:36 -05:00
|
|
|
#include "JsonAsmDef.mqh"
|
2026-07-19 13:56:15 -05:00
|
|
|
#include <TSN\\BSFL\\Dom.mqh>
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
namespace TSN
|
|
|
|
|
{
|
|
|
|
|
|
2026-06-03 07:50:45 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
struct CJsonNode;
|
2026-06-09 14:15:41 -05:00
|
|
|
//#define JSONPARSERBYLEO_DESACTIVE_SWAR
|
2026-06-03 07:50:45 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-19 07:41:52 -05:00
|
|
|
class CJsonParser : public CBaseStructuredLan
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-18 08:36:18 -05:00
|
|
|
private:
|
2026-06-02 21:23:50 -05:00
|
|
|
//---
|
|
|
|
|
int m_stak_num[512];
|
|
|
|
|
int m_stak_pos[512];
|
|
|
|
|
char m_stak_state[512];
|
|
|
|
|
int m_stak_size;
|
|
|
|
|
int m_stak_curr;
|
|
|
|
|
int m_stak_curr_state;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
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-06-03 14:16:03 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
public:
|
2026-07-19 07:41:52 -05:00
|
|
|
CJsonParser(void) {}
|
2026-06-02 21:23:50 -05:00
|
|
|
~CJsonParser(void) {}
|
|
|
|
|
|
2026-06-03 07:50:45 -05:00
|
|
|
//---
|
2026-06-03 08:32:38 -05:00
|
|
|
// Para data raw se puede usar el json uchar directamtne
|
2026-06-21 21:51:52 -05:00
|
|
|
bool AutoParseByFileExt(const int file_ext_type);
|
2026-07-19 07:41:52 -05:00
|
|
|
__forceinline void CorrectPadding() { CorrectPadingInternal(' ');}
|
2026-06-03 07:50:45 -05:00
|
|
|
|
2026-06-18 09:48:36 -05:00
|
|
|
//---
|
|
|
|
|
bool Parse();
|
|
|
|
|
bool ParseAssembly();
|
|
|
|
|
int ToJsonAsm(uchar& text[]) const;
|
2026-06-03 07:50:45 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline ENUM_TSN_JSON_LAST_ERR LastErr() const { return m_last_err; }
|
|
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//---
|
|
|
|
|
string Unescape(const int start, const int end) const;
|
2026-06-03 16:57:42 -05:00
|
|
|
int Unescape(const int start, const int end, uchar& res[]) const;
|
2026-06-02 22:52:39 -05:00
|
|
|
|
2026-06-03 07:50:45 -05:00
|
|
|
//---
|
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-06-03 07:50:45 -05:00
|
|
|
//---
|
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-06-23 08:02:37 -05:00
|
|
|
//--- Comparacion de strings
|
2026-06-20 13:57:50 -05:00
|
|
|
bool StrEquals(const string &str, const int curr) const;
|
2026-06-23 08:02:37 -05:00
|
|
|
bool StrEquals(const int other, const int curr) const;
|
2026-07-11 16:31:27 -05:00
|
|
|
|
2026-07-10 07:17:28 -05:00
|
|
|
//--
|
|
|
|
|
string CleanNode(int i, const int end) const;
|
2026-07-15 17:58:56 -05:00
|
|
|
int CleanNode(int i, const int end, uchar &out[], int k, bool ajustar_arr) const;
|
2026-07-10 07:17:28 -05:00
|
|
|
|
2026-06-03 07:50:45 -05:00
|
|
|
//---
|
2026-07-11 16:31:27 -05:00
|
|
|
CJsonNode GetRoot();
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool NodeHashing(int curr, const int obj_count, const int bend, int& table_pos);
|
2026-07-11 16:31:27 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-11 16:33:25 -05:00
|
|
|
void ErrorInfo(bool with_avanze = false) const;
|
2026-07-19 13:56:15 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void SerializeToDom(CDomNodeBase *&root, CDomNodeManager *&manager, int cur, const int end) const;
|
2026-06-02 21:23:50 -05:00
|
|
|
};
|
|
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CJsonParser::NodeHashing(int curr, const int obj_count, const int bend, int& table_pos)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
table_pos = FindNodePosOrCreate(curr); // Reservamos o obtenemos la posicion de este nodo
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_tables[table_pos].table_size = obj_count; // Numero de objetos
|
|
|
|
|
m_tables[table_pos].start = curr;
|
|
|
|
|
|
2026-06-28 18:47:50 -05:00
|
|
|
m_pfh.MaxValSeed(m_max_att++);
|
|
|
|
|
m_pfh.InitAlg(obj_count, 0.75, fmin(obj_count, 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-06-28 18:47:50 -05:00
|
|
|
curr += 2; // Ahora en key
|
2026-06-24 17:20:42 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-20 13:57:50 -05:00
|
|
|
while(curr < bend)
|
|
|
|
|
{
|
|
|
|
|
if(int(m_cinta[curr] & 0xF) != JSON_VTYPE_KEY)
|
|
|
|
|
{
|
|
|
|
|
curr += GetStep(curr);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
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-06-28 18:47:50 -05:00
|
|
|
ulong key_hash = FNV_OFFSET_BASIS;
|
2026-07-19 07:41:52 -05:00
|
|
|
int i = int(m_cinta[curr] >> TSN_SBL_BIT_STR_START); // len
|
|
|
|
|
const int len = i + int((m_cinta[curr] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN); // len
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-24 17:20:42 -05:00
|
|
|
//--- Hash 64
|
|
|
|
|
for(; i < len; i++)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
key_hash ^= m_raw[i];
|
2026-06-28 18:47:50 -05:00
|
|
|
key_hash *= FNV_PRIME;
|
2026-06-24 17:20:42 -05:00
|
|
|
}
|
2026-07-19 07:41:52 -05:00
|
|
|
// PrintFormat("Hash para %s = %I64u", CharArrayToString(m_raw, int(m_cinta[curr] >> TSN_SBL_BIT_STR_START),
|
|
|
|
|
// int((m_cinta[curr] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN)), key_hash);
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
|
2026-06-24 17:20:42 -05:00
|
|
|
//---
|
2026-06-28 18:47:50 -05:00
|
|
|
keys_h[pos_c] = key_hash;
|
|
|
|
|
posiciones[pos_c] = pos_c;
|
|
|
|
|
pos_c++;
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-24 17:20:42 -05:00
|
|
|
curr++; // salta KEY
|
|
|
|
|
curr += GetStep(curr); // salta VAL
|
|
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-28 18:47:50 -05:00
|
|
|
m_tables[table_pos].bucket_size = m_pfh.m_buckets_size;
|
|
|
|
|
const int fn = m_pfh.m_final_table_size;
|
|
|
|
|
m_tables[table_pos].final_table_size = fn;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Iniciamos..
|
|
|
|
|
ArrayResize(m_tables[table_pos].pos_index, fn);
|
|
|
|
|
ArrayResize(m_tables[table_pos].key_hash, fn);
|
|
|
|
|
ArrayInitialize(m_tables[table_pos].pos_index, -1);
|
|
|
|
|
ArrayInitialize(m_tables[table_pos].key_hash, 0ULL);
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-28 18:47:50 -05:00
|
|
|
return m_pfh.RunWValue(keys_h, posiciones, m_tables[table_pos].seeds, m_tables[table_pos].pos_index, m_tables[table_pos].key_hash);
|
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-20 13:57:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CJsonParser::StrEquals(const string &str, const int curr) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// m_cinta[m_cinta_pos++] = long(m_pos - 1) | long(start) << TSN_JSON_BIT_STR_START_END;
|
2026-07-19 07:41:52 -05:00
|
|
|
const int start = int(m_cinta[curr] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int len = int((m_cinta[curr] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
|
|
|
//PrintFormat("Exact = '%s', other = '%s'", CharArrayToString(m_raw, start, len), str);
|
2026-06-20 14:18:38 -05:00
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
const int l = StringLen(str);
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-20 14:18:38 -05:00
|
|
|
if(l != len)
|
2026-06-20 13:57:50 -05:00
|
|
|
return false;
|
|
|
|
|
for(int i = 0; i < l; i++)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
if(str[i] != m_raw[start + i])
|
2026-06-20 13:57:50 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-06-03 07:50:45 -05:00
|
|
|
|
2026-06-23 08:02:37 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CJsonParser::StrEquals(const int other, const int curr) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// m_cinta[m_cinta_pos++] = long(m_pos - 1) | long(start) << TSN_JSON_BIT_STR_START_END;
|
2026-07-19 07:41:52 -05:00
|
|
|
const int start = int(m_cinta[curr] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int len = int((m_cinta[curr] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
|
|
|
//PrintFormat("Exact = '%s', other = '%s'", CharArrayToString(m_raw, start, len), str);
|
|
|
|
|
const int s = int(m_cinta[other] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int l = int((m_cinta[other] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
2026-06-23 08:02:37 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(l != len)
|
|
|
|
|
return false;
|
|
|
|
|
for(int i = 0; i < l; i++)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[s + i] != m_raw[start + i])
|
2026-06-23 08:02:37 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-07-11 16:31:27 -05:00
|
|
|
|
2026-06-23 08:02:37 -05:00
|
|
|
|
2026-07-10 07:17:28 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
string CJsonParser::CleanNode(int i, const int end) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
string str;
|
|
|
|
|
int k = 0;
|
|
|
|
|
StringSetLength(str, (end - i) + 1);
|
|
|
|
|
|
|
|
|
|
// "\"\""
|
|
|
|
|
//---
|
|
|
|
|
bool in = false;
|
|
|
|
|
for(i; i <= end; i++)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[i];
|
2026-07-10 07:17:28 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(in)
|
|
|
|
|
{
|
|
|
|
|
str.SetChar(k++, c);
|
|
|
|
|
if(c == '\\')
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
str.SetChar(k++, m_raw[++i]);
|
2026-07-10 07:17:28 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
in = (c != '"');
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(c < 33)
|
|
|
|
|
continue;
|
|
|
|
|
str.SetChar(k++, c);
|
|
|
|
|
in = (c == '"');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//--
|
|
|
|
|
StringSetLength(str, k);
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-15 17:58:56 -05:00
|
|
|
int CJsonParser::CleanNode(int i, const int end, uchar &out[], int k, bool ajustar_arr) const
|
2026-07-10 07:17:28 -05:00
|
|
|
{
|
|
|
|
|
//---
|
2026-07-15 16:03:07 -05:00
|
|
|
const int needed = (end - i) + 1;
|
|
|
|
|
const int rsize = ArraySize(out);
|
|
|
|
|
const int e = needed + k;
|
|
|
|
|
if(rsize <= e)
|
|
|
|
|
{
|
|
|
|
|
ArrayResize(out, rsize + e);
|
|
|
|
|
}
|
2026-07-10 07:17:28 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool in = false;
|
|
|
|
|
for(i; i <= end; i++)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[i];
|
2026-07-10 07:17:28 -05:00
|
|
|
//---
|
|
|
|
|
if(in)
|
|
|
|
|
{
|
|
|
|
|
out[k++] = c;
|
|
|
|
|
if(c == '\\')
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
out[k++] = m_raw[++i];
|
2026-07-10 07:17:28 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
in = (c != '"');
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(c < 33)
|
|
|
|
|
continue;
|
|
|
|
|
out[k++] = c;
|
|
|
|
|
in = (c == '"');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--
|
2026-07-15 17:58:56 -05:00
|
|
|
if(ajustar_arr) // Ajustamos exacto
|
|
|
|
|
ArrayResize(out, k);
|
|
|
|
|
|
2026-07-17 15:07:22 -05:00
|
|
|
//--
|
2026-07-15 16:03:07 -05:00
|
|
|
return k - (e - needed);
|
2026-07-10 07:17:28 -05:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
}
|
2026-07-19 07:41:52 -05:00
|
|
|
case TSNJSON_RI_JSONASM_FILE:
|
2026-06-21 21:51:52 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
CorrectPadding(); // Auto
|
|
|
|
|
return ParseAssembly();
|
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-03 07:50:45 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-04 17:26:20 -05:00
|
|
|
//--- Especifico (C=caracter que se busca, T=Token asignado)
|
|
|
|
|
|
2026-06-14 15:51:39 -05:00
|
|
|
#define TSN_JSON_NEXT_ESPECIFIC_DO(C, T) \
|
2026-06-05 16:28:44 -05:00
|
|
|
while(true) \
|
|
|
|
|
{ \
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[m_pos] == C) \
|
2026-06-05 16:28:44 -05:00
|
|
|
{ \
|
2026-06-14 15:51:39 -05:00
|
|
|
m_next=T; \
|
|
|
|
|
break; \
|
2026-06-05 16:28:44 -05:00
|
|
|
} \
|
2026-06-14 15:51:39 -05:00
|
|
|
m_pos++;\
|
2026-06-05 16:28:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Generico
|
2026-06-18 08:36:18 -05:00
|
|
|
// 1 en la tabl to token es INVALID (dara error..de malformed..)
|
2026-06-04 17:26:20 -05:00
|
|
|
#define TSN_JSON_NEXT_NO_NEXT_KEY \
|
2026-06-05 16:28:44 -05:00
|
|
|
while(true) \
|
2026-06-18 08:36:18 -05:00
|
|
|
{ \
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar _c = m_raw[m_pos]; \
|
2026-06-20 15:44:08 -05:00
|
|
|
if(_c < 33) \
|
2026-06-02 21:23:50 -05:00
|
|
|
{ \
|
2026-06-18 08:36:18 -05:00
|
|
|
m_pos++; \
|
|
|
|
|
if(m_pos>=m_len) \
|
|
|
|
|
{ \
|
|
|
|
|
m_last_err=TSN_JSON_ERR_MALFOMED_LEN_SUPERADO; \
|
|
|
|
|
return false; \
|
|
|
|
|
} \
|
2026-06-02 21:23:50 -05:00
|
|
|
continue; \
|
|
|
|
|
} \
|
2026-06-05 16:28:44 -05:00
|
|
|
const uchar _locked = m_next; \
|
2026-06-20 15:44:08 -05:00
|
|
|
m_next = g_table_json_tokens[_c];\
|
2026-06-14 15:51:39 -05:00
|
|
|
if(((1 << m_next) & g_json_expected[m_stak_curr_state][_locked]) == 0)\
|
2026-06-02 21:23:50 -05:00
|
|
|
{ \
|
|
|
|
|
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON; \
|
|
|
|
|
return false; \
|
2026-06-05 16:28:44 -05:00
|
|
|
}\
|
|
|
|
|
break; \
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-20 15:44:08 -05:00
|
|
|
//---
|
|
|
|
|
#define TSN_JSON_NEXT_LLAVE_INI \
|
|
|
|
|
while(true) \
|
|
|
|
|
{ \
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar _c = m_raw[m_pos]; \
|
2026-06-20 15:44:08 -05:00
|
|
|
if(_c == '"') \
|
|
|
|
|
{ \
|
|
|
|
|
m_next=TSN_JSON_TOK_KEY; \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
if(_c== '}') \
|
|
|
|
|
{ \
|
|
|
|
|
m_next=TSN_JSON_TOK_LLAVE_END; \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
m_pos++;\
|
|
|
|
|
}
|
2026-06-05 16:28:44 -05:00
|
|
|
|
2026-06-09 14:15:41 -05:00
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
//--- Luego de una coma en array
|
|
|
|
|
// Luego de una , y KEY siempre siempre valor
|
|
|
|
|
#define TSN_JSON_NEXT_VALUE_COMM_KEY \
|
|
|
|
|
while(true) \
|
|
|
|
|
{ \
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar _c = m_raw[m_pos];\
|
2026-06-20 15:44:08 -05:00
|
|
|
if(_c < 33) \
|
2026-06-20 13:57:50 -05:00
|
|
|
{ \
|
|
|
|
|
m_pos++; \
|
|
|
|
|
continue; \
|
|
|
|
|
} \
|
2026-06-20 15:44:08 -05:00
|
|
|
m_next = g_table_json_tokens[_c];\
|
2026-06-20 13:57:50 -05:00
|
|
|
if(((1 << m_next) & TSN_JSON_F_ALL_I_VAL) == 0)\
|
|
|
|
|
{ \
|
|
|
|
|
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON; \
|
|
|
|
|
return false; \
|
|
|
|
|
}\
|
|
|
|
|
break; \
|
|
|
|
|
}
|
2026-06-05 16:28:44 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-03 08:32:38 -05:00
|
|
|
bool CJsonParser::Parse()
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-03 07:50:45 -05:00
|
|
|
//---
|
|
|
|
|
m_stak_size = 0;
|
2026-06-20 13:57:50 -05:00
|
|
|
//m_stak_curr_state = -1;
|
|
|
|
|
//m_stak_curr = -1;
|
2026-06-03 07:50:45 -05:00
|
|
|
m_last_err = TSN_JSON_NOT_ERR;
|
2026-06-20 13:57:50 -05:00
|
|
|
//m_next = TSN_JSON_TOK_INVALID;
|
2026-06-03 08:32:38 -05:00
|
|
|
m_pos = m_offset;
|
2026-06-03 07:50:45 -05:00
|
|
|
m_cinta_pos = 0;
|
2026-07-12 18:24:34 -05:00
|
|
|
m_tables_size = 0;
|
2026-06-19 20:41:32 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//--- Inicial
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar _f_c = m_raw[m_pos];
|
2026-06-26 17:53:09 -05:00
|
|
|
if(_f_c == '{')
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-26 17:53:09 -05:00
|
|
|
m_next = TSN_JSON_TOK_LLAVE_INI;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(_f_c == '[')
|
2026-06-20 15:44:08 -05:00
|
|
|
{
|
|
|
|
|
m_next = TSN_JSON_TOK_COR_INI;
|
|
|
|
|
}
|
2026-06-26 17:53:09 -05:00
|
|
|
else
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-26 17:53:09 -05:00
|
|
|
m_pos++;
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar _f__c = m_raw[m_pos];
|
2026-06-26 17:53:09 -05:00
|
|
|
if(_f__c < 33)
|
|
|
|
|
{
|
|
|
|
|
m_pos++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(_f__c == '{')
|
|
|
|
|
{
|
|
|
|
|
m_next = TSN_JSON_TOK_LLAVE_INI;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(_f__c == '[')
|
|
|
|
|
{
|
|
|
|
|
m_next = TSN_JSON_TOK_COR_INI;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_next = TSN_JSON_TOK_INVALID;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Bucle
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
switch(m_next)
|
|
|
|
|
{
|
|
|
|
|
case TSN_JSON_TOK_NUMBER:
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
long v = 0;
|
|
|
|
|
|
|
|
|
|
//--- Validamos signo
|
2026-06-24 19:19:43 -05:00
|
|
|
long mask = 0;
|
2026-07-19 07:41:52 -05:00
|
|
|
uchar ch = m_raw[m_pos];
|
2026-06-20 13:57:50 -05:00
|
|
|
if(ch == '-')
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-24 19:19:43 -05:00
|
|
|
mask = -1;
|
2026-06-24 18:59:32 -05:00
|
|
|
m_pos++; // Ahora en numero
|
2026-07-19 07:41:52 -05:00
|
|
|
ch = m_raw[m_pos];
|
2026-06-24 18:59:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
ch ^= '0';
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
//---
|
2026-06-26 17:53:09 -05:00
|
|
|
v = (v << 3) + (v << 1) + ch;
|
2026-06-24 18:59:32 -05:00
|
|
|
|
2026-06-26 17:53:09 -05:00
|
|
|
//--- *
|
2026-06-02 21:23:50 -05:00
|
|
|
m_pos++;
|
2026-06-24 19:19:43 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
ch = m_raw[m_pos] ^ '0';
|
2026-06-24 18:59:32 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(ch < 10)
|
2026-06-20 13:57:50 -05:00
|
|
|
{
|
2026-06-24 18:59:32 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(ch == 30 || (ch | 0x20) == 117) // .
|
2026-06-20 13:57:50 -05:00
|
|
|
{
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
double val = double(v);
|
|
|
|
|
if(ch == 30)
|
2026-06-20 13:57:50 -05:00
|
|
|
{
|
2026-06-24 18:59:32 -05:00
|
|
|
m_pos++;
|
|
|
|
|
long frac_int = 0;
|
|
|
|
|
int fract_digits = 0;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-24 19:19:43 -05:00
|
|
|
while(true)
|
2026-06-24 18:59:32 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[m_pos] ^ '0';
|
2026-06-24 18:59:32 -05:00
|
|
|
if(c > 9)
|
|
|
|
|
break;
|
2026-06-26 17:53:09 -05:00
|
|
|
frac_int = (frac_int << 3) + (frac_int << 1) + c;
|
2026-06-24 18:59:32 -05:00
|
|
|
fract_digits++;
|
|
|
|
|
m_pos++;
|
|
|
|
|
}
|
2026-06-24 19:19:43 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
val += frac_int * g_Exp10[fract_digits];
|
2026-06-20 13:57:50 -05:00
|
|
|
}
|
2026-06-24 18:59:32 -05:00
|
|
|
|
|
|
|
|
//--- 10e50.02500140
|
2026-07-19 07:41:52 -05:00
|
|
|
if((m_raw[m_pos] | 0x20) == 'e') // e or E
|
2026-06-20 13:57:50 -05:00
|
|
|
{
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
m_pos++;
|
|
|
|
|
bool exp_sign = true;
|
2026-07-19 07:41:52 -05:00
|
|
|
uchar _c = m_raw[m_pos];
|
2026-06-24 18:59:32 -05:00
|
|
|
if(_c == '-')
|
|
|
|
|
{
|
|
|
|
|
exp_sign = false;
|
|
|
|
|
m_pos++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(_c == '+')
|
|
|
|
|
{
|
|
|
|
|
m_pos++;
|
|
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
_c = m_raw[m_pos] ^ '0';
|
2026-06-24 18:59:32 -05:00
|
|
|
int exp_val = 0;
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2026-06-26 21:00:10 -05:00
|
|
|
exp_val = (exp_val << 3) + (exp_val << 1) + _c;
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
m_pos++;
|
2026-07-19 07:41:52 -05:00
|
|
|
_c = m_raw[m_pos] ^ '0';
|
2026-06-24 18:59:32 -05:00
|
|
|
if(_c > 9)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-24 19:19:43 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
val *= (exp_sign) ? g_Pow10[exp_val] : g_Exp10[exp_val];
|
|
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
//---
|
|
|
|
|
static BitInterpreter bit;
|
2026-06-24 19:19:43 -05:00
|
|
|
bit.double_value = val;
|
2026-06-26 17:53:09 -05:00
|
|
|
bit.long_value ^= (mask & (1LL << 63));
|
2026-06-24 18:59:32 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
|
|
|
|
|
m_cinta[m_cinta_pos++] = bit.long_value;
|
|
|
|
|
break;
|
2026-06-20 13:57:50 -05:00
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
else
|
2026-06-24 18:59:32 -05:00
|
|
|
{
|
|
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_INTEGER;
|
2026-06-26 17:53:09 -05:00
|
|
|
m_cinta[m_cinta_pos++] = (v ^ mask) - mask;
|
2026-06-24 18:59:32 -05:00
|
|
|
break; // Fin
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
|
2026-06-24 18:59:32 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//--- no hago el m_pos++ dado que ahora mismo estamo en el seg char
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-02 21:23:50 -05:00
|
|
|
case TSN_JSON_TOK_STRING:
|
|
|
|
|
{
|
|
|
|
|
//---
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(2)
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int start = ++m_pos;
|
2026-06-18 08:36:18 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-12 18:24:34 -05:00
|
|
|
#ifndef JSONPARSERBYLEO_DESACTIVE_SWAR
|
2026-06-18 08:36:18 -05:00
|
|
|
//--- Pase inicial 8 en 8
|
2026-07-12 18:24:34 -05:00
|
|
|
while(true)
|
2026-06-09 14:15:41 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
// 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;
|
2026-06-09 14:15:41 -05:00
|
|
|
|
2026-06-18 08:36:18 -05:00
|
|
|
//---
|
|
|
|
|
const ulong x_bs = chunk ^ TSNTABLES_SWAR_MASK_BACK_SLASH;
|
|
|
|
|
ulong has_bs = TSNTABLES_SWAR_HAS(x_bs);
|
|
|
|
|
const ulong x_qt = chunk ^ TSNTABLES_SWAR_MASK_COMILLA;
|
|
|
|
|
const ulong has_qt = TSNTABLES_SWAR_HAS(x_qt);
|
2026-06-09 14:15:41 -05:00
|
|
|
|
2026-06-18 08:36:18 -05:00
|
|
|
//---
|
2026-06-18 08:52:10 -05:00
|
|
|
if((has_bs | has_qt) == 0) // Caso comun. .. ninguno de los dos.. continuamos..
|
2026-06-18 08:36:18 -05:00
|
|
|
{
|
2026-07-12 18:24:34 -05:00
|
|
|
m_pos += 8;
|
2026-07-12 18:46:58 -05:00
|
|
|
if((m_pos + 7) >= m_len) // Ultimas 8 posicinoes son " " asi que seria invalido ya..
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_STRING_NOT_CLOSED;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-06-18 08:36:18 -05:00
|
|
|
continue;
|
2026-06-09 14:15:41 -05:00
|
|
|
}
|
|
|
|
|
|
2026-06-18 08:52:10 -05:00
|
|
|
//---
|
|
|
|
|
if(has_bs == 0) // Si not iene bs (pero confirmamos que no es 0)
|
|
|
|
|
// Entonces no tirne bs pero si qt salimos de una..
|
|
|
|
|
{
|
|
|
|
|
const ulong flag_real = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_pos += TSNTABLES_SWAR_64_GET_BYTE(flag_real);
|
|
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
|
2026-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-18 08:52:10 -05:00
|
|
|
m_pos++; // Luego del "
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 18:24:34 -05:00
|
|
|
//--- Hay bs si o si pero tambien puede haber "
|
|
|
|
|
const uchar compacted_bs = TSNTABLES_COMPACT_UL(has_bs);
|
|
|
|
|
// Aislamos los bits donde empeizan las rachas de \
|
|
|
|
|
const uchar starts = compacted_bs & ~(compacted_bs << 1);
|
|
|
|
|
// sumas especiifca para impar
|
|
|
|
|
const ushort sum_impar_wide = (ushort)compacted_bs + ushort(starts & TSNTABLES_MASK_IMPARES);
|
|
|
|
|
// Obtenemos finales de ambos...
|
|
|
|
|
const uchar end_par = (compacted_bs + (starts & TSNTABLES_MASK_PARES)) & ~compacted_bs;
|
|
|
|
|
const uchar end_impar = uchar(sum_impar_wide & 0xFF) & ~compacted_bs;
|
|
|
|
|
// Ahora ya sabemos donde esta los finaes impares..
|
|
|
|
|
const uchar end_final = (end_impar & TSNTABLES_MASK_PARES) | (end_par & TSNTABLES_MASK_IMPARES);
|
|
|
|
|
const uchar compacted_qt = TSNTABLES_COMPACT_UL(has_qt);
|
|
|
|
|
const uchar qt_final = compacted_qt & ~end_final;
|
|
|
|
|
//Print("nada");
|
2026-06-18 08:52:10 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-12 18:24:34 -05:00
|
|
|
if(qt_final != 0) // Hay un qt real de cierre
|
2026-06-18 08:36:18 -05:00
|
|
|
{
|
2026-07-12 18:24:34 -05:00
|
|
|
// Avanzamos y cerramos..
|
|
|
|
|
m_pos += g_table_i8[qt_final];
|
2026-06-18 08:36:18 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
|
2026-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-18 08:36:18 -05:00
|
|
|
m_pos++; // Luego del "
|
2026-07-12 18:24:34 -05:00
|
|
|
break;
|
2026-06-18 08:36:18 -05:00
|
|
|
}
|
2026-07-12 18:24:34 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pos += 8;
|
2026-07-19 07:41:52 -05:00
|
|
|
// Print(CharToString(m_raw[m_pos]));
|
2026-07-12 18:24:34 -05:00
|
|
|
if((sum_impar_wide & 0x100) != 0) // Overflow el ultimo char es \ y el siguiente escapa
|
|
|
|
|
{
|
|
|
|
|
//Print("siuu");
|
|
|
|
|
m_pos++; // Uno mas.. luego del currend
|
|
|
|
|
}
|
2026-06-18 08:36:18 -05:00
|
|
|
|
2026-07-12 18:24:34 -05:00
|
|
|
// No hay ... o es escapado en caso exista
|
|
|
|
|
if((m_pos + 7) >= m_len) // Ultimas 8 posicinoes son " " asi que seria invalido ya..
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_STRING_NOT_CLOSED;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-06-09 14:15:41 -05:00
|
|
|
}
|
2026-06-18 08:36:18 -05:00
|
|
|
|
2026-07-12 18:24:34 -05:00
|
|
|
#else // JSONPARSERBYLEO_DESACTIVE_SWAR
|
2026-06-18 08:36:18 -05:00
|
|
|
//--- Char por char
|
2026-06-14 15:51:39 -05:00
|
|
|
do
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[m_pos];
|
2026-06-18 08:36:18 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
if(c == '\\')
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-04 17:26:20 -05:00
|
|
|
m_pos += 2;
|
|
|
|
|
continue;
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
if(c == '"')
|
|
|
|
|
{
|
|
|
|
|
// STRING 1 slot: [tipo(4)|len(28low)|start(32high)]
|
2026-07-19 07:41:52 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING | long(m_pos - start) << TSN_SBL_BIT_STR_LEN |
|
|
|
|
|
long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-18 08:36:18 -05:00
|
|
|
// curr_end = INT_MAX;
|
|
|
|
|
m_pos++;
|
2026-06-04 17:26:20 -05:00
|
|
|
break;
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_pos++;
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
2026-06-14 15:51:39 -05:00
|
|
|
while(m_pos < m_len);
|
2026-07-12 22:12:12 -05:00
|
|
|
|
2026-07-12 22:10:11 -05:00
|
|
|
#endif // JSONPARSERBYLEO_DESACTIVE_SWAR
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-07-12 18:24:34 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_BOOL_TRUE:
|
|
|
|
|
{
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(1)
|
|
|
|
|
// t r u e W
|
|
|
|
|
// [-4] [-3] [-2] [-1] [0]
|
|
|
|
|
|
2026-06-18 08:36:18 -05:00
|
|
|
m_pos += 4;
|
2026-07-19 07:41:52 -05:00
|
|
|
// 5 | 1 << TSN_SBL_BIT_START_BOOL(4) = 21
|
|
|
|
|
m_cinta[m_cinta_pos++] = 21;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_BOOL_FALSE:
|
|
|
|
|
{
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(1)
|
|
|
|
|
// f a l s e W
|
|
|
|
|
// [] [-4] [-3] [-2 ] [-1] [0]
|
2026-06-18 08:36:18 -05:00
|
|
|
m_pos += 5;
|
2026-06-02 21:23:50 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_BOOLEAN;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_NULL:
|
|
|
|
|
{
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(1)
|
2026-06-09 14:15:41 -05:00
|
|
|
// n u l l W
|
2026-06-03 12:20:23 -05:00
|
|
|
// [-4][-3][-2][-1][]
|
2026-06-02 21:23:50 -05:00
|
|
|
|
2026-06-09 14:15:41 -05:00
|
|
|
//---
|
2026-06-18 08:36:18 -05:00
|
|
|
m_pos += 4;
|
2026-06-02 21:23:50 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_NULL;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_COMMA:
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
m_stak_num[m_stak_curr]++;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_pos++;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
if(m_stak_curr_state == TSN_JSON_CTX_IN_OBJ)
|
|
|
|
|
{
|
2026-06-14 15:51:39 -05:00
|
|
|
TSN_JSON_NEXT_ESPECIFIC_DO('"', TSN_JSON_TOK_KEY)
|
2026-06-04 17:26:20 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2026-06-20 13:57:50 -05:00
|
|
|
TSN_JSON_NEXT_VALUE_COMM_KEY
|
2026-06-04 17:26:20 -05:00
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_LLAVE_INI:
|
|
|
|
|
{
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(1)
|
2026-06-02 21:23:50 -05:00
|
|
|
m_cinta[m_cinta_pos] = JSON_VTYPE_OBJ;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_stak_curr = m_stak_size++;
|
2026-06-02 22:52:39 -05:00
|
|
|
m_stak_curr_state = TSN_JSON_CTX_IN_OBJ;
|
|
|
|
|
m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_OBJ;
|
2026-06-02 21:23:50 -05:00
|
|
|
m_stak_num[m_stak_curr] = 0;
|
|
|
|
|
m_stak_pos[m_stak_curr] = m_cinta_pos++;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-03 12:20:23 -05:00
|
|
|
m_cinta[m_cinta_pos++] = m_pos++;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-20 17:29:49 -05:00
|
|
|
TSN_JSON_NEXT_LLAVE_INI
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_COR_INI:
|
|
|
|
|
{
|
2026-06-03 12:20:23 -05:00
|
|
|
//TSN_JSON_RESERVAR(1)
|
2026-06-02 22:52:39 -05:00
|
|
|
m_cinta[m_cinta_pos] = JSON_VTYPE_ARR;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_stak_curr = m_stak_size++;
|
2026-06-02 22:52:39 -05:00
|
|
|
m_stak_curr_state = TSN_JSON_CTX_IN_ARR;
|
|
|
|
|
m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_ARR;
|
2026-06-02 21:23:50 -05:00
|
|
|
m_stak_num[m_stak_curr] = 0;
|
|
|
|
|
m_stak_pos[m_stak_curr] = m_cinta_pos++;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-03 12:20:23 -05:00
|
|
|
m_cinta[m_cinta_pos++] = m_pos++;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_JSON_TOK_LLAVE_END:
|
|
|
|
|
case TSN_JSON_TOK_COR_END:
|
|
|
|
|
{
|
2026-06-03 08:32:38 -05:00
|
|
|
//---
|
2026-06-03 18:53:05 -05:00
|
|
|
if(m_cinta_pos > m_stak_pos[m_stak_curr] + 2) // [a][a][v][c]
|
|
|
|
|
{
|
|
|
|
|
m_stak_num[m_stak_curr]++;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-03 08:32:38 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-03 07:50:45 -05:00
|
|
|
const int lp = m_stak_pos[m_stak_curr];
|
2026-07-19 07:41:52 -05:00
|
|
|
m_cinta[lp] |= long(m_stak_num[m_stak_curr]) << TSN_SBL_BIT_START_NUM_EL | long(m_cinta_pos - lp) << TSN_SBL_BIT_START_NUM_C;
|
2026-06-03 12:20:23 -05:00
|
|
|
m_cinta[lp + 1] |= long(m_pos) << TSN_JSON_BIT_END_T;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_stak_size = m_stak_curr--;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(m_stak_size == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-06-21 16:08:44 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_stak_curr_state = m_stak_state[m_stak_curr];
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_pos++;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-06-04 17:26:20 -05:00
|
|
|
TSN_JSON_NEXT_NO_NEXT_KEY
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
case TSN_JSON_TOK_KEY:
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
2026-06-04 17:26:20 -05:00
|
|
|
const int start = ++m_pos;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-20 15:44:08 -05:00
|
|
|
#ifndef JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
|
|
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
//--- Pase inicial 8 en 8
|
2026-07-12 18:24:34 -05:00
|
|
|
while(true)
|
2026-06-04 17:26:20 -05:00
|
|
|
{
|
2026-06-20 15:44:08 -05:00
|
|
|
// "asdasdasd".........."
|
2026-07-19 07:41:52 -05:00
|
|
|
// 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;
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-04 17:26:20 -05:00
|
|
|
//---
|
2026-06-20 15:44:08 -05:00
|
|
|
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
const ulong x_bs = chunk ^ TSNTABLES_SWAR_MASK_BACK_SLASH;
|
|
|
|
|
ulong has_bs = TSNTABLES_SWAR_HAS(x_bs);
|
2026-06-20 15:44:08 -05:00
|
|
|
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
|
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
const ulong x_qt = chunk ^ TSNTABLES_SWAR_MASK_COMILLA;
|
|
|
|
|
const ulong has_qt = TSNTABLES_SWAR_HAS(x_qt);
|
2026-06-04 17:26:20 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-06-20 15:44:08 -05:00
|
|
|
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
if((has_bs | has_qt) == 0) // Caso comun. .. ninguno de los dos.. continuamos..
|
2026-06-04 17:26:20 -05:00
|
|
|
{
|
2026-07-12 18:46:58 -05:00
|
|
|
m_pos += 8;
|
|
|
|
|
if((m_pos + 7) >= m_len) // Ultimas 8 posicinoes son " " asi que seria invalido ya..
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_KEY_NOT_CLOSED;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-06-18 08:36:18 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
2026-06-20 15:44:08 -05:00
|
|
|
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
|
|
|
|
if(has_qt == 0) // Caso comun. .. ninguno de los dos.. continuamos..
|
|
|
|
|
{
|
2026-07-12 18:46:58 -05:00
|
|
|
m_pos += 8;
|
|
|
|
|
if((m_pos + 7) >= m_len) // Ultimas 8 posicinoes son " " asi que seria invalido ya..
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_KEY_NOT_CLOSED;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-06-20 15:44:08 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2026-06-04 17:26:20 -05:00
|
|
|
|
2026-06-18 08:36:18 -05:00
|
|
|
//---
|
2026-06-27 07:49:32 -05:00
|
|
|
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
if(has_bs == 0) // Si not iene bs (pero confirmamos que no es 0)
|
|
|
|
|
// Entonces no tirne bs pero si qt salimos de una..
|
2026-06-18 08:36:18 -05:00
|
|
|
{
|
2026-06-27 07:49:32 -05:00
|
|
|
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
const ulong flag_real = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_pos += TSNTABLES_SWAR_64_GET_BYTE(flag_real);
|
2026-06-20 14:18:38 -05:00
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
|
2026-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-14 15:51:39 -05:00
|
|
|
m_pos++; // Luego del "
|
2026-06-04 17:26:20 -05:00
|
|
|
break;
|
2026-06-27 07:49:32 -05:00
|
|
|
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-04 17:26:20 -05:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 18:46:58 -05:00
|
|
|
//--- Hay bs si o si pero tambien puede haber "
|
|
|
|
|
const uchar compacted_bs = TSNTABLES_COMPACT_UL(has_bs);
|
|
|
|
|
// Aislamos los bits donde empeizan las rachas de \
|
|
|
|
|
const uchar starts = compacted_bs & ~(compacted_bs << 1);
|
|
|
|
|
// sumas especiifca para impar
|
|
|
|
|
const ushort sum_impar_wide = (ushort)compacted_bs + ushort(starts & TSNTABLES_MASK_IMPARES);
|
|
|
|
|
// Obtenemos finales de ambos...
|
|
|
|
|
const uchar end_par = (compacted_bs + (starts & TSNTABLES_MASK_PARES)) & ~compacted_bs;
|
|
|
|
|
const uchar end_impar = uchar(sum_impar_wide & 0xFF) & ~compacted_bs;
|
|
|
|
|
// Ahora ya sabemos donde esta los finaes impares..
|
|
|
|
|
const uchar end_final = (end_impar & TSNTABLES_MASK_PARES) | (end_par & TSNTABLES_MASK_IMPARES);
|
|
|
|
|
const uchar compacted_qt = TSNTABLES_COMPACT_UL(has_qt);
|
|
|
|
|
const uchar qt_final = compacted_qt & ~end_final;
|
|
|
|
|
//Print("nada");
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-12 18:46:58 -05:00
|
|
|
if(qt_final != 0) // Hay un qt real de cierre
|
2026-06-20 13:57:50 -05:00
|
|
|
{
|
2026-07-12 18:46:58 -05:00
|
|
|
// Avanzamos y cerramos..
|
|
|
|
|
m_pos += g_table_i8[qt_final];
|
|
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
|
2026-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-20 13:57:50 -05:00
|
|
|
m_pos++; // Luego del "
|
2026-07-12 18:46:58 -05:00
|
|
|
break;
|
2026-06-20 13:57:50 -05:00
|
|
|
}
|
2026-07-12 18:46:58 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pos += 8;
|
2026-07-19 07:41:52 -05:00
|
|
|
// Print(CharToString(m_raw[m_pos]));
|
2026-07-12 18:46:58 -05:00
|
|
|
if((sum_impar_wide & 0x100) != 0) // Overflow el ultimo char es \ y el siguiente escapa
|
|
|
|
|
{
|
|
|
|
|
//Print("siuu");
|
|
|
|
|
m_pos++; // Uno mas.. luego del currend
|
|
|
|
|
}
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-07-12 18:46:58 -05:00
|
|
|
// No hay ... o es escapado en caso exista
|
|
|
|
|
if((m_pos + 7) >= m_len) // Ultimas 8 posicinoes son " " asi que seria invalido ya..
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_KEY_NOT_CLOSED;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-06-27 07:49:32 -05:00
|
|
|
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-07-12 18:24:34 -05:00
|
|
|
#else // JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
|
2026-06-20 13:57:50 -05:00
|
|
|
|
|
|
|
|
//--- Char por char
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
|
2026-06-27 07:49:32 -05:00
|
|
|
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
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-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-20 13:57:50 -05:00
|
|
|
// curr_end = INT_MAX;
|
|
|
|
|
m_pos++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-27 07:49:32 -05:00
|
|
|
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[m_pos] == '"')
|
2026-06-20 15:44:08 -05:00
|
|
|
{
|
|
|
|
|
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
|
2026-07-19 07:41:52 -05:00
|
|
|
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
|
|
|
|
| long(start) << TSN_SBL_BIT_STR_START;
|
2026-06-20 15:44:08 -05:00
|
|
|
// curr_end = INT_MAX;
|
|
|
|
|
m_pos++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-27 07:49:32 -05:00
|
|
|
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
|
2026-06-20 15:44:08 -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)
|
|
|
|
|
{
|
2026-06-18 08:36:18 -05:00
|
|
|
m_last_err = TSN_JSON_ERR_KEY_NOT_CLOSED;
|
2026-06-14 15:51:39 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
}
|
2026-07-12 18:24:34 -05:00
|
|
|
#endif // JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
|
2026-06-04 17:26:20 -05:00
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
//--- Find :
|
2026-06-14 15:51:39 -05:00
|
|
|
while(true)
|
2026-06-04 17:26:20 -05:00
|
|
|
{
|
2026-06-14 15:51:39 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[m_pos] == ':')
|
2026-06-14 15:51:39 -05:00
|
|
|
break;
|
2026-06-04 17:26:20 -05:00
|
|
|
|
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;
|
|
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
}
|
2026-06-14 15:51:39 -05:00
|
|
|
//---
|
|
|
|
|
m_pos++; // Luego del
|
|
|
|
|
|
2026-06-04 17:26:20 -05:00
|
|
|
|
|
|
|
|
//--- 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;
|
|
|
|
|
}
|
2026-06-26 17:53:09 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
m_last_err = TSN_JSON_ERR_INVALID_CHAR;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_last_err = TSN_JSON_ERR_JSON_NOT_FINISH;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-06-04 17:26:20 -05:00
|
|
|
// "llabe":"llabe";
|
2026-06-02 21:23:50 -05:00
|
|
|
|
2026-06-20 13:57:50 -05:00
|
|
|
|
2026-06-02 21:23:50 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-06-20 13:57:50 -05:00
|
|
|
int CJsonParser::Unescape(const int start, const int end, uchar & res[]) const
|
2026-06-03 16:57:42 -05:00
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(res, (end - start) + 1);
|
|
|
|
|
int pos = 0;
|
2026-06-02 21:23:50 -05:00
|
|
|
|
2026-06-03 16:57:42 -05:00
|
|
|
//---
|
|
|
|
|
for(int i = start; i <= end; i++)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[i] == '\\')
|
2026-06-03 16:57:42 -05:00
|
|
|
{
|
|
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[i];
|
2026-06-19 22:08:57 -05:00
|
|
|
const uchar next = g_tsn_table_unescape_table[c];
|
2026-06-03 16:57:42 -05:00
|
|
|
switch(next)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
case TSN_TABLE_UNESCAPE_UNICODE:
|
2026-06-03 16:57:42 -05:00
|
|
|
{
|
|
|
|
|
if(i + 4 <= end)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
uint code = g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i]];
|
2026-06-03 16:57:42 -05:00
|
|
|
|
2026-06-20 18:08:19 -05:00
|
|
|
//--- Vericiacino para emojis....
|
|
|
|
|
if(code >= 0xD800 && code <= 0xDBFF)
|
|
|
|
|
{
|
|
|
|
|
// Otro mas \uxxxx
|
2026-07-19 07:41:52 -05:00
|
|
|
if(i + 6 <= end && m_raw[i + 1] == '\\' && m_raw[i + 2] == 'u')
|
2026-06-20 18:08:19 -05:00
|
|
|
{
|
|
|
|
|
const int j = i + 3;
|
2026-07-19 07:41:52 -05:00
|
|
|
uint low = g_arr_valid_hex_chars[m_raw[j]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 1]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 2]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 3]];
|
2026-06-20 18:08:19 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(low >= 0xDC00 && low <= 0xDFFF)
|
|
|
|
|
{
|
|
|
|
|
code = 0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
|
|
|
|
|
i = j + 3; // consumimos tambien el low surrogate
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
code = 0xFFFD; // low surrogate invalido
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
code = 0xFFFD; // huerfano, no hay low surrogate despues
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//--- Low surrogate suelto (sin high antes) -> invalido
|
|
|
|
|
else
|
|
|
|
|
if(code >= 0xDC00 && code <= 0xDFFF)
|
|
|
|
|
{
|
|
|
|
|
code = 0xFFFD;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 22:08:57 -05:00
|
|
|
//---
|
2026-06-03 16:57:42 -05:00
|
|
|
if(code < 0x80)
|
|
|
|
|
{
|
|
|
|
|
res[pos++] = uchar(code);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(code < 0x800)
|
|
|
|
|
{
|
|
|
|
|
res[pos++] = uchar(0xC0 | (code >> 6));
|
|
|
|
|
res[pos++] = uchar(0x80 | (code & 0x3F));
|
|
|
|
|
}
|
|
|
|
|
else
|
2026-06-20 18:08:19 -05:00
|
|
|
if(code < 0x10000)
|
|
|
|
|
{
|
|
|
|
|
res[pos++] = uchar(0xE0 | (code >> 12));
|
|
|
|
|
res[pos++] = uchar(0x80 | ((code >> 6) & 0x3F));
|
|
|
|
|
res[pos++] = uchar(0x80 | (code & 0x3F));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res[pos++] = uchar(0xF0 | (code >> 18));
|
|
|
|
|
res[pos++] = uchar(0x80 | ((code >> 12) & 0x3F));
|
|
|
|
|
res[pos++] = uchar(0x80 | ((code >> 6) & 0x3F));
|
|
|
|
|
res[pos++] = uchar(0x80 | (code & 0x3F));
|
|
|
|
|
}
|
2026-06-03 16:57:42 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
res[pos++] = 'u';
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
case TSN_TABLE_UNESCAPE_HEX:
|
|
|
|
|
{
|
|
|
|
|
if(i + 2 <= end)
|
|
|
|
|
{
|
|
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
uchar v = g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
v = (v << 4) | g_arr_valid_hex_chars[m_raw[i]];
|
2026-06-20 18:08:19 -05:00
|
|
|
//Print("Valor:" , v);
|
2026-06-19 22:08:57 -05:00
|
|
|
res[pos++] = v;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
res[pos++] = 'x';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_TABLE_UNESCAPE_INVALID:
|
|
|
|
|
{
|
|
|
|
|
res[pos++] = c;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-03 16:57:42 -05:00
|
|
|
default:
|
|
|
|
|
res[pos++] = next;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
continue;
|
2026-06-03 16:57:42 -05:00
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
res[pos++] = m_raw[i];
|
2026-06-03 16:57:42 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return ArrayResize(res, pos);
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
string CJsonParser::Unescape(const int start, const int end) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
string res = "";
|
|
|
|
|
StringSetLength(res, (end - start) + 1);
|
|
|
|
|
int pos = 0;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int i = start; i <= end; i++)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
if(m_raw[i] == '\\')
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
|
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
const uchar c = m_raw[i];
|
2026-06-19 22:08:57 -05:00
|
|
|
const uchar next = g_tsn_table_unescape_table[c];
|
2026-06-02 21:23:50 -05:00
|
|
|
switch(next)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
case TSN_TABLE_UNESCAPE_UNICODE:
|
2026-06-02 21:23:50 -05:00
|
|
|
{
|
|
|
|
|
if(i + 4 <= end)
|
|
|
|
|
{
|
2026-06-19 22:08:57 -05:00
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
uint code = g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
code = (code << 4) | g_arr_valid_hex_chars[m_raw[i]];
|
2026-06-19 22:08:57 -05:00
|
|
|
|
2026-06-20 18:08:19 -05:00
|
|
|
//--- High surrogate (0xD800-0xDBFF): el string es UTF-16, basta con
|
|
|
|
|
// validar que venga acompañado de un low surrogate valido despues
|
|
|
|
|
// y escribir ambas unidades tal cual (no hace falta combinar).
|
|
|
|
|
if(code >= 0xD800 && code <= 0xDBFF)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
if(i + 6 <= end && m_raw[i + 1] == '\\' && m_raw[i + 2] == 'u')
|
2026-06-20 18:08:19 -05:00
|
|
|
{
|
|
|
|
|
const int j = i + 3;
|
2026-07-19 07:41:52 -05:00
|
|
|
uint low = g_arr_valid_hex_chars[m_raw[j]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 1]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 2]];
|
|
|
|
|
low = (low << 4) | g_arr_valid_hex_chars[m_raw[j + 3]];
|
2026-06-20 18:08:19 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(low >= 0xDC00 && low <= 0xDFFF)
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, (ushort)code);
|
|
|
|
|
res.SetChar(pos++, (ushort)low);
|
|
|
|
|
i = j + 3; // consumimos tambien el low surrogate
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, 0xFFFD); // low surrogate invalido
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, 0xFFFD); // huerfano, no hay low surrogate despues
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//--- Low surrogate suelto (sin high antes) -> invalido
|
|
|
|
|
else
|
|
|
|
|
if(code >= 0xDC00 && code <= 0xDFFF)
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, 0xFFFD);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, (ushort)code);
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
res.SetChar(pos++, 'u');
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
case TSN_TABLE_UNESCAPE_HEX:
|
|
|
|
|
{
|
|
|
|
|
if(i + 2 <= end)
|
|
|
|
|
{
|
|
|
|
|
i++;
|
2026-07-19 07:41:52 -05:00
|
|
|
uchar v = g_arr_valid_hex_chars[m_raw[i++]];
|
|
|
|
|
v = (v << 4) | g_arr_valid_hex_chars[m_raw[i]];
|
2026-06-20 18:08:19 -05:00
|
|
|
//Print("Valor:" , v);
|
2026-06-19 22:08:57 -05:00
|
|
|
res.SetChar(pos++, v);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
res.SetChar(pos++, 'x');
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TSN_TABLE_UNESCAPE_INVALID:
|
|
|
|
|
{
|
|
|
|
|
res.SetChar(pos++, c);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
default:
|
|
|
|
|
res.SetChar(pos++, next);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
continue;
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
2026-06-19 22:08:57 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-19 07:41:52 -05:00
|
|
|
res.SetChar(pos++, m_raw[i]);
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
res.Truncate(pos);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-02 22:52:39 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-06-03 07:50:45 -05:00
|
|
|
//| |
|
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-06-04 17:26:20 -05:00
|
|
|
const int tipo = int(m_cinta[idx] & 0xF);
|
2026-06-03 07:50:45 -05:00
|
|
|
switch(tipo)
|
2026-06-02 22:52:39 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
case JSON_VTYPE_KEY:
|
|
|
|
|
return 1;
|
|
|
|
|
case JSON_VTYPE_OBJ:
|
|
|
|
|
case JSON_VTYPE_ARR:
|
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;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| GetStep: posiciones que ocupa el nodo idx en la cinta |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
__forceinline int CJsonParser::GetStep(const int idx)
|
|
|
|
|
const
|
|
|
|
|
{
|
2026-06-04 11:36:42 -05:00
|
|
|
switch(int(m_cinta[idx] & 0xF))
|
2026-06-03 07:50:45 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
case JSON_VTYPE_KEY:
|
|
|
|
|
return 1;
|
|
|
|
|
case JSON_VTYPE_OBJ:
|
|
|
|
|
case JSON_VTYPE_ARR:
|
|
|
|
|
return int(m_cinta[idx] >> TSN_SBL_BIT_START_NUM_C);
|
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;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-03 07:50:45 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CJsonNode CJsonParser::GetRoot()
|
|
|
|
|
{
|
|
|
|
|
if(m_cinta_pos == 0)
|
|
|
|
|
return EMPTY_JSON_NODE;
|
|
|
|
|
return CJsonNode(&this, 0, GetStep(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
2026-07-19 13:56:15 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CJsonParser::SerializeToDom(CDomNodeBase *&root, CDomNodeManager *&manager, int cur, const int end) const
|
|
|
|
|
{
|
|
|
|
|
//--- Temp
|
|
|
|
|
CDomNodeBase* prev_value; // valolr qeu devuelve key
|
|
|
|
|
CDomNodeBase* current_container[512]; // contenedor
|
|
|
|
|
int current_ends[512];
|
|
|
|
|
int sp = 0;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
manager = CDomNodeManager();
|
|
|
|
|
root = new CDomNodeBase(manager);
|
|
|
|
|
|
|
|
|
|
//--- 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);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
current_container[0] = root;
|
|
|
|
|
current_ends[sp] = end;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur += 2;
|
|
|
|
|
|
|
|
|
|
//--- It
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
//--- Check
|
|
|
|
|
if(cur >= current_ends[sp])
|
|
|
|
|
{
|
|
|
|
|
sp--; // Nivel menos
|
|
|
|
|
if(sp <= 0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
switch(tipo)
|
|
|
|
|
{
|
|
|
|
|
case JSON_VTYPE_KEY:
|
|
|
|
|
{
|
|
|
|
|
const int s = int(m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int slen = int((m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
|
|
|
const string str = Unescape(s, s + slen - 1);
|
|
|
|
|
prev_value = root[str];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_OBJ:
|
|
|
|
|
{
|
|
|
|
|
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) // [{}]
|
|
|
|
|
{
|
|
|
|
|
const int lock = sp++;
|
|
|
|
|
current_container[sp] = new CDomNodeBase(current_container[sp].m_ctx);
|
|
|
|
|
current_container[sp].NewObj(count);
|
|
|
|
|
current_container[lock].AddItem(current_container[sp]);
|
|
|
|
|
}
|
|
|
|
|
else // {key:{}}
|
|
|
|
|
{
|
|
|
|
|
sp++;
|
|
|
|
|
prev_value = new CDomNodeBase(current_container[sp].m_ctx);
|
|
|
|
|
prev_value.NewObj(count);
|
|
|
|
|
current_container[sp] = prev_value;
|
|
|
|
|
}
|
|
|
|
|
current_ends[sp] = cur + int(m_cinta[cur] >> TSN_SBL_BIT_START_NUM_C);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_ARR:
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
const int lock = sp++;
|
|
|
|
|
current_container[sp] = new CDomNodeBase(current_container[sp].m_ctx);
|
|
|
|
|
current_container[sp].NewArr(count);
|
|
|
|
|
current_container[lock].AddItem(current_container[sp]);
|
|
|
|
|
}
|
|
|
|
|
else // {key:[]}
|
|
|
|
|
{
|
|
|
|
|
sp++;
|
|
|
|
|
prev_value = new CDomNodeBase(current_container[sp].m_ctx);
|
|
|
|
|
prev_value.NewArr(count);
|
|
|
|
|
current_container[sp] = prev_value;
|
|
|
|
|
}
|
|
|
|
|
current_ends[sp] = cur + int(m_cinta[cur] >> TSN_SBL_BIT_START_NUM_C);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_INTEGER:
|
|
|
|
|
{
|
|
|
|
|
if(current_container[sp].m_type == JSON_VTYPE_ARR)
|
|
|
|
|
current_container[sp].AddItem(new CDomNodeBase(current_container[sp].m_ctx, JSON_VTYPE_INTEGER, m_cinta[cur + 1]));
|
|
|
|
|
else
|
|
|
|
|
prev_value = m_cinta[cur + 1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_REAL:
|
|
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_value = m_cinta[cur + 1];
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(current_container[sp].m_type == JSON_VTYPE_ARR)
|
|
|
|
|
current_container[sp].AddItem(new CDomNodeBase(current_container[sp].m_ctx, JSON_VTYPE_REAL, un.double_value));
|
|
|
|
|
else
|
|
|
|
|
prev_value = un.double_value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_BOOLEAN:
|
|
|
|
|
{
|
|
|
|
|
const bool v = ((m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1) != 0;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(current_container[sp].m_type == JSON_VTYPE_ARR)
|
|
|
|
|
current_container[sp].AddItem(new CDomNodeBase(current_container[sp].m_ctx, JSON_VTYPE_BOOLEAN, v));
|
|
|
|
|
else
|
|
|
|
|
prev_value = v;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_STRING:
|
|
|
|
|
{
|
|
|
|
|
const int s = int(m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
|
|
|
|
const int slen = int((m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
|
|
|
const string str = Unescape(s, s + slen - 1);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(current_container[sp].m_type == JSON_VTYPE_ARR)
|
|
|
|
|
current_container[sp].AddItem(new CDomNodeBase(current_container[sp].m_ctx, JSON_VTYPE_STRING, str));
|
|
|
|
|
else
|
|
|
|
|
prev_value = str;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_NULL:
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
if(current_container[sp].m_type == JSON_VTYPE_ARR)
|
|
|
|
|
current_container[sp].AddItem(new CDomNodeBase(current_container[sp].m_ctx));
|
|
|
|
|
else
|
|
|
|
|
prev_value.m_type = JSON_VTYPE_NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
cur += GetStepPure(cur);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
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);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
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-06-03 15:48:09 -05:00
|
|
|
string text = "[" + (string)p + "] " + EnumToString(tipo) + " | ";
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
switch(tipo)
|
|
|
|
|
{
|
2026-07-19 07:41:52 -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_BIT_STR_MASK_LEN);
|
|
|
|
|
text += "start=" + (string)s + " len=" + (string)slen + " key=\"" + CharArrayToString(m_raw, s, slen) + "\"";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case JSON_VTYPE_OBJ:
|
|
|
|
|
case JSON_VTYPE_ARR:
|
|
|
|
|
{
|
|
|
|
|
const int count = int((m_cinta[p] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
|
|
|
|
const int num_c = int(m_cinta[p] >> TSN_SBL_BIT_START_NUM_C);
|
|
|
|
|
const int raw_s = int(m_cinta[p + 1] & 0xFFFFFFFF);
|
|
|
|
|
const int raw_e = int(m_cinta[p + 1] >> TSN_JSON_BIT_END_T);
|
|
|
|
|
text += "count=" + (string)count + " num_c=" + (string)num_c + " raw_start=" + (string)raw_s + " raw_end=" + (string)raw_e;
|
|
|
|
|
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-06-04 17:26:20 -05:00
|
|
|
{
|
|
|
|
|
static BitInterpreter un;
|
|
|
|
|
un.long_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-07-19 07:41:52 -05:00
|
|
|
text += "val=" + (string)(bool)((m_cinta[p] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
|
2026-06-03 15:48:09 -05:00
|
|
|
break;
|
|
|
|
|
case JSON_VTYPE_STRING:
|
2026-06-04 17:26:20 -05:00
|
|
|
{
|
2026-07-19 07:41:52 -05:00
|
|
|
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_BIT_STR_MASK_LEN);
|
2026-07-12 18:24:34 -05:00
|
|
|
text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + Unescape(s, s + slen - 1) + "\"";
|
2026-06-04 17:26:20 -05:00
|
|
|
break;
|
|
|
|
|
}
|
2026-06-03 15:48:09 -05:00
|
|
|
case JSON_VTYPE_NULL:
|
|
|
|
|
text += "null";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Print(text);
|
2026-06-03 07:50:45 -05:00
|
|
|
p += GetStepPure(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-11 16:31:27 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CJsonParser::ErrorInfo(bool with_avanze = false) const
|
|
|
|
|
{
|
|
|
|
|
if(m_last_err == TSN_JSON_NOT_ERR)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int col, line;
|
|
|
|
|
GetLastErrorLocation(col, line);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
string desc;
|
|
|
|
|
switch(m_last_err)
|
|
|
|
|
{
|
|
|
|
|
case TSN_JSON_ERR_INVALID_CHAR_COMMA_IN_CTX_NO_OBJ_ARR:
|
|
|
|
|
desc = "Coma invalida fuera de un objeto o arreglo";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFORDMED_JSON:
|
|
|
|
|
desc = "JSON malformado";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_INVALID_CHAR:
|
|
|
|
|
desc = "Caracter invalido";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFORMED_TRUE:
|
|
|
|
|
desc = "Literal 'true' malformado";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFORMED_FALSE:
|
|
|
|
|
desc = "Literal 'false' malformado";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFORMED_NULL:
|
|
|
|
|
desc = "Literal 'null' malformado";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_STRING_NOT_CLOSED:
|
|
|
|
|
desc = "Cadena sin cerrar";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_INVALID_STATE:
|
|
|
|
|
desc = "Estado invalido del parser";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_JSON_NOT_FINISH:
|
|
|
|
|
desc = "El JSON no termino correctamente";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_EXPECTED_OBJ_ARR:
|
|
|
|
|
desc = "Se esperaba un objeto o un arreglo";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_OVERFLOW_IN_CINTA_RESIZE:
|
|
|
|
|
desc = "Overflow al redimensionar la cinta interna";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS:
|
|
|
|
|
desc = "Se esperaban dos puntos ':' despues de la clave";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_MALFOMED_LEN_SUPERADO:
|
|
|
|
|
desc = "Longitud maxima superada";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_KEY_NOT_CLOSED:
|
|
|
|
|
desc = "Clave sin cerrar";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_HAS_NOT_CONTENT:
|
|
|
|
|
desc = "El JSON no tiene contenido";
|
|
|
|
|
break;
|
|
|
|
|
case TSN_JSON_ERR_INVALID_EXT_FILE:
|
|
|
|
|
desc = "Extension de archivo invalida";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
desc = "Error desconocido";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
PrintFormat("%s [Line %d, Col %d]", desc, line, col);
|
|
|
|
|
|
|
|
|
|
if(with_avanze)
|
|
|
|
|
{
|
|
|
|
|
Print("Avanze: ");
|
2026-07-19 07:41:52 -05:00
|
|
|
Print(CharArrayToString(m_raw, 0, m_pos));
|
2026-07-11 16:31:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2026-06-02 21:23:50 -05:00
|
|
|
}
|
|
|
|
|
#endif // JSONPARSERBYLEO_SRC_JSONPARSER_MQH
|
2026-06-03 16:57:42 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-07-12 18:24:34 -05:00
|
|
|
/*
|
|
|
|
|
//
|
|
|
|
|
// a\\\"\nb
|
|
|
|
|
B = 0b01110100
|
|
|
|
|
-----
|
|
|
|
|
~B<<1 = 0b00010111
|
|
|
|
|
|
|
|
|
|
starts= 0b00010100
|
|
|
|
|
|
|
|
|
|
0b01110100
|
|
|
|
|
sum = 0b00010100
|
|
|
|
|
10001000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10001000
|
|
|
|
|
01110100 (and)
|
|
|
|
|
00000000
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
B = "\\a\\bb
|
|
|
|
|
B = 01101100
|
|
|
|
|
B<<1 = 11011000
|
|
|
|
|
~B = 00100111
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
|
starts = 01101100
|
|
|
|
|
00100111 and
|
|
|
|
|
00100100
|
|
|
|
|
--
|
|
|
|
|
= 01101100 +
|
|
|
|
|
00100100
|
|
|
|
|
10010000
|
|
|
|
|
--
|
|
|
|
|
eo = 10010000
|
|
|
|
|
01101100
|
|
|
|
|
00000000
|
|
|
|
|
*/
|
|
|
|
|
//+------------------------------------------------------------------+
|