1995 lines
59 KiB
MQL5
1995 lines
59 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "JsonDefines.mqh"
| |
#include <TSN\\BSFL\\Dom.mqh>
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_DLL
| |
#include "DLL\\Main.mqh"
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
namespace TSN
| |
{
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
//#define JSONPARSERBYLEO_DESACTIVE_SWAR
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class CJsonParser : public CBaseStructuredLan
| |
{
| |
protected:
| |
//---
| |
uint m_stak_num[JSONPARSERBYLEO_MAX_STACK];
| |
int m_stak_pos[JSONPARSERBYLEO_MAX_STACK];
| |
ushort m_stak_state[JSONPARSERBYLEO_MAX_STACK];
| |
int m_stak_curr;
| |
ushort m_stak_curr_state;
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_DLL
| |
int m_index[];
| |
int m_index_r;
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
//---
| |
ENUM_TSN_JSON_LAST_ERR m_last_err;
| |
| |
//---
| |
int CalcRegType(const string& file_name) override final;
| |
| |
public:
| |
CJsonParser(void);
| |
~CJsonParser(void) {}
| |
| |
//--- Parse + Correct padding
| |
// Para data raw se puede usar el json uchar directamtne
| |
bool AutoParseByFileExt(const int file_ext_type);
| |
void CorrectPadding();
| |
#ifdef JSONPARSERBYLEO_DLL
| |
void CorrectPaddingSimd();
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
//---
| |
bool Parse();
| |
#ifdef JSONPARSERBYLEO_DLL
| |
__forceinline bool ParseSimd();
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
//--- Errores
| |
__forceinline ENUM_TSN_JSON_LAST_ERR LastErr() const { return m_last_err; }
| |
void CatchErr();
| |
void ErrorInfo(const string header = "");
| |
| |
//--- Step
| |
__forceinline int GetStep(const int idx) const;
| |
__forceinline int GetStepPure(const int idx) const;
| |
| |
| |
//--- Info
| |
void PrintCintaTypes(const int start, const int num) const;
| |
| |
//--- Comparacion
| |
// keys
| |
bool KeysEqual(const ulong key_hash_fnv1a64, const int curr) const;
| |
bool KeysEqual(const string& str, const int curr) const;
| |
// strings
| |
bool StrEquals(const string &str, const int curr) const;
| |
| |
//--- Clean node
| |
string CleanNode(int i, const int end) const;
| |
int CleanNode(int i, const int end, uchar &out[], int k, bool ajustar_arr) const;
| |
| |
//--- Extra (node-use)
| |
bool NodeHashing(int curr, const int obj_count, const int bend, int& table_pos);
| |
bool SerializeToDom(CDomNodeBase* root, CDomNodeManager* manager, int cur, const int end);
| |
| |
//--- Array
| |
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;
| |
| |
| |
//--- Make
| |
// uso en get value o exatcion
| |
static bool MakeString(const uchar &in[], int i, int len, string& res);
| |
static int MakeUArray(const uchar &in[], int i, int len, uchar &res[], int pos = 0);
| |
static bool MakeKeyHashFNV1A64(const uchar &in[], int& i, int len, ulong& hash);
| |
static bool EscapePointer(const string &in, int& p, int len, ulong& hash);
| |
| |
//---
| |
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);
| |
| |
//---
| |
CJsonNode GetRoot();
| |
| |
//--- Tablas generales
| |
static const string s_dtype_to_str[JSON_VTYPE_TOTAL];
| |
static const char s_slots_size_arrobj;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
CJsonParser::CJsonParser(void)
| |
{
| |
m_next = TSN_JSON_TOK_INVALID;
| |
#ifdef JSONPARSERBYLEO_DLL
| |
m_index_r = ArrayResize(m_index, 256, 256);
| |
#endif // JSONPARSERBYLEO_DLL
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
const string CJsonParser::s_dtype_to_str[JSON_VTYPE_TOTAL] =
| |
{
| |
"",
| |
"",
| |
"",
| |
"ulong",
| |
"long",
| |
"double",
| |
"bool",
| |
"string",
| |
""
| |
};
| |
const char CJsonParser::s_slots_size_arrobj = 2;
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#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;
| |
ArrayResize(m_cinta, m_len);
| |
}
| |
| |
//---
| |
if(m_len > m_index_r)
| |
{
| |
m_index_r = m_len;
| |
ArrayResize(m_index, m_index_r);
| |
}
| |
}
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
//+------------------------------------------------------------------+
| |
void CJsonParser::CorrectPadding()
| |
{
| |
//---
| |
//const int new_len = ;
| |
ArrayResize(m_raw, m_len + 11);
| |
| |
//--- 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
| |
// invalidos para que sigmoas si un valor esta fuera de rango como un string o algo asi
| |
// falle aqui....
| |
m_raw[m_len + 5] = '^'; //
| |
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] = '^';
| |
| |
//--- Reservamos
| |
if(m_len > m_cinta_reserve)
| |
{
| |
m_cinta_reserve = m_len;
| |
ArrayResize(m_cinta, m_len);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::NodeHashing(int curr, const int obj_count, const int bend, int& table_pos)
| |
{
| |
//--- inicial
| |
BASESPARSERSLAN_START_NODE_HASH(table_pos, curr)
| |
| |
//---
| |
m_tables[table_pos].table_size = obj_count; // Numero de objetos
| |
| |
//---
| |
m_pfh.MaxValSeed(m_max_att++);
| |
m_pfh.InitAlg(obj_count, 0.70, TSN_NODEBASEREAD_MIN_JIT_VALUES_TO_HASH_MIN);
| |
| |
//---
| |
ArrayResize(m_tables[table_pos].pos_arr, obj_count);
| |
| |
| |
//--- Obtnemos las posiciones de incio
| |
ulong keys_h[];
| |
int posiciones[];
| |
ArrayResize(keys_h, obj_count);
| |
ArrayResize(posiciones, obj_count);
| |
int pos_c = 0;
| |
curr += 2; // Ahora en key
| |
| |
//---
| |
while(curr < bend)
| |
{
| |
const long v = m_cinta[curr];
| |
if(int(v & TSN_SBL_BIT_MASK_TYPE) != JSON_VTYPE_KEY)
| |
{
| |
curr += GetStep(curr);
| |
continue;
| |
}
| |
| |
//---
| |
m_tables[table_pos].pos_arr[pos_c] = curr; // Assing
| |
| |
//---
| |
ulong key_hash = FNV_OFFSET_BASIS;
| |
int i = int(v >> TSN_SBL_BIT_STR_START); // len
| |
const int len = i + int((v >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN); // len
| |
| |
//--- Hash 64
| |
while(i < len)
| |
{
| |
key_hash ^= m_raw[i];
| |
key_hash *= FNV_PRIME;
| |
i++;
| |
}
| |
| |
// 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);
| |
| |
| |
//---
| |
keys_h[pos_c] = key_hash;
| |
posiciones[pos_c] = pos_c;
| |
pos_c++;
| |
| |
//---
| |
curr++; // salta KEY
| |
curr += GetStep(curr); // salta VAL
| |
}
| |
| |
// Cacheado
| |
const int fn = m_pfh.m_final_table_size;
| |
| |
//--- Last
| |
m_tables[table_pos].final_table_l = m_pfh.m_final_table_size_last;
| |
m_tables[table_pos].bucket_l = m_pfh.m_buckets_size_last;
| |
| |
| |
// Iniciamos..
| |
ArrayResize(m_tables[table_pos].pos_index, fn);
| |
//ArrayInitialize(m_tables[table_pos].pos_index, -1); no hace falta el que nos indica valides es key hash si key hash es invalido o no machte no llega aqui
| |
//---
| |
ArrayResize(m_tables[table_pos].key_hash, fn);
| |
ArrayInitialize(m_tables[table_pos].key_hash, 0ULL);
| |
| |
//---
| |
if(m_pfh.RunWValue(keys_h, posiciones, m_tables[table_pos].seeds, m_tables[table_pos].pos_index, m_tables[table_pos].key_hash))
| |
return true;
| |
| |
//----
| |
m_tables_size--; // pop
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
int CJsonParser::CalcRegType(const string& file_name)
| |
{
| |
return (int)JPBL_HashExt(file_name);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::KeysEqual(const string &str, const int curr) const
| |
{
| |
//---
| |
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);
| |
const int l = StringLen(str);
| |
//---
| |
if(l != len)
| |
return false;
| |
//---
| |
for(int i = 0; i < l; i++)
| |
if(str[i] != m_raw[start + i])
| |
return false;
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::KeysEqual(const ulong key_hash_fnv1a64, const int curr) const
| |
{
| |
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);
| |
ulong hash = FNV_OFFSET_BASIS;
| |
for(int i = start; i < (start + len); i++)
| |
{
| |
hash ^= m_raw[i];
| |
hash *= FNV_PRIME;
| |
}
| |
return hash == key_hash_fnv1a64;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
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 l = StringLen(str);
| |
| |
//---
| |
if(l != len)
| |
return false;
| |
for(int i = 0; i < l; i++)
| |
{
| |
if(str[i] != m_raw[start + i])
| |
return false;
| |
}
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
string CJsonParser::CleanNode(int i, const int end) const
| |
{
| |
//---
| |
string str;
| |
int k = 0;
| |
StringInit(str, (end - i) + 1, ' ');
| |
| |
// "\"\""
| |
//---
| |
bool in = false;
| |
for(i; i <= end; i++)
| |
{
| |
const uchar c = m_raw[i];
| |
| |
//---
| |
if(in)
| |
{
| |
str.SetChar(k++, c);
| |
if(c == '\\')
| |
{
| |
str.SetChar(k++, m_raw[++i]);
| |
continue;
| |
}
| |
in = (c != '"');
| |
}
| |
else
| |
{
| |
if(c < 33)
| |
continue;
| |
str.SetChar(k++, c);
| |
in = (c == '"');
| |
}
| |
}
| |
//--
| |
StringSetLength(str, k);
| |
return str;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
int CJsonParser::CleanNode(int i, const int end, uchar &out[], int k, bool ajustar_arr) const
| |
{
| |
//---
| |
const int needed = (end - i) + 1;
| |
const int rsize = ArraySize(out);
| |
const int e = needed + k;
| |
if(rsize <= e)
| |
{
| |
ArrayResize(out, rsize + e);
| |
}
| |
| |
//---
| |
bool in = false;
| |
for(i; i <= end; i++)
| |
{
| |
const uchar c = m_raw[i];
| |
//---
| |
if(in)
| |
{
| |
out[k++] = c;
| |
if(c == '\\')
| |
{
| |
out[k++] = m_raw[++i];
| |
continue;
| |
}
| |
in = (c != '"');
| |
}
| |
else
| |
{
| |
if(c < 33)
| |
continue;
| |
out[k++] = c;
| |
in = (c == '"');
| |
}
| |
}
| |
| |
//--
| |
if(ajustar_arr) // Ajustamos exacto
| |
ArrayResize(out, k);
| |
| |
//--
| |
return k - (e - needed);
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::AutoParseByFileExt(const int file_ext_type)
| |
{
| |
switch(file_ext_type)
| |
{
| |
case TSN_SLF_RAW_FILE:
| |
{
| |
CorrectPadding(); // Auto
| |
return Parse();
| |
}
| |
case TSN_SLF_RAW_EMBEBED:
| |
{
| |
return m_cinta_pos > 0 && m_len > 0;
| |
}
| |
default:
| |
{
| |
m_last_err = TSN_JSON_ERR_INVALID_EXT_FILE;
| |
m_pos = 0;
| |
return false;
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Macros de avanze |
| |
//+------------------------------------------------------------------+
| |
//---
| |
#define TSN_JSON_AUMENT m_stak_num[m_stak_curr]++;
| |
| |
//--- Se usa solo al incio de un llave ini validos " y }
| |
#define TSN_JSON_NEXT_LLAVE_INI \
| |
while(true) \
| |
{ \
| |
const uchar _c = m_raw[m_pos]; \
| |
if(_c == '"') \
| |
{ \
| |
m_next=TSN_JSON_TOK_KEY; \
| |
break; \
| |
} \
| |
if(_c== '}') \
| |
{ \
| |
m_next=TSN_JSON_TOK_LLAVE_END; \
| |
break; \
| |
} \
| |
m_pos++; \
| |
}
| |
| |
//--- 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]; \
| |
if(((1 << m_next) & m_stak_curr_state) == 0) \
| |
{ \
| |
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL; \
| |
return false; \
| |
}
| |
| |
| |
//--- Luego de una coma en array
| |
// Luego de una , y KEY siempre siempre valor
| |
#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) \
| |
{ \
| |
m_last_err= TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL; \
| |
return false; \
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Parseo de numeros |
| |
//+------------------------------------------------------------------+
| |
//--- make string
| |
#define JSONPARSERBYLEO_NUM_MAKE_STRING m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING \
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN \
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
| |
//+------------------------------------------------------------------+
| |
//| Parse con simd |
| |
//+------------------------------------------------------------------+
| |
#ifdef JSONPARSERBYLEO_DLL
| |
__forceinline bool CJsonParser::ParseSimd()
| |
{
| |
//--- Iniciales
| |
m_last_err = TSN_JSON_NOT_ERR;
| |
m_tables_size = 0;
| |
return JsonParserResolve(m_raw,
| |
m_cinta,
| |
m_index,
| |
m_len,
| |
m_offset,
| |
(int&)m_last_err,
| |
m_cinta_pos,
| |
m_pos
| |
);
| |
}
| |
#endif // JSONPARSERBYLEO_DLL
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Parse normal |
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::Parse()
| |
{
| |
//---
| |
m_stak_curr = -1;
| |
m_last_err = TSN_JSON_NOT_ERR;
| |
m_pos = m_offset;
| |
m_cinta_pos = 0;
| |
m_tables_size = 0;
| |
| |
//--- 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;
| |
}
| |
else
| |
{
| |
m_pos++;
| |
while(true)
| |
{
| |
const uchar _f__c = m_raw[m_pos];
| |
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;
| |
}
| |
}
| |
| |
//--- Bucle
| |
while(true)
| |
{
| |
switch(m_next)
| |
{
| |
//---
| |
case TSN_JSON_TOK_NUMBER_NEG:
| |
{
| |
//--- solo 3 varaibles nada mas en general (garantizado)
| |
long v = 0;
| |
const int start = m_pos;
| |
uchar ch = m_raw[++m_pos] ^ '0';
| |
//---
| |
switch(0)
| |
{
| |
default: // scope con psoiblidad de break.
| |
{
| |
//--- primera iteracion sin cheking
| |
DOMBASEUTIL_PARSE_NUM_U1(v)
| |
//--- 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
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_17(v)
| |
STRCONV_TOV_ALG(v, ch)
| |
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)
| |
{
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
}
| |
//--- revismoos si es dec, si lo es saltamos la parte dec
| |
if(STRCONV_DECX_CH_IS_DEC(ch))
| |
break;
| |
| |
//--- 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
| |
if(STRCONV_DECX_CH_IS_DEC(ch))
| |
{
| |
long exponente = 0; // exponente
| |
int digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
| |
if(STRCONV_DECX_CH_IS_PDEC(ch))
| |
{
| |
int ds = ++m_pos; // inicio
| |
if((ch = m_raw[m_pos] ^ '0') > 9)
| |
{
| |
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP;
| |
return false;
| |
}
| |
while(true)
| |
{
| |
//DOMBASEUTIL_NUM_PROCCES_FIRST_DEC(v, ch, m_pos, ds, digitos)
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
break;
| |
}
| |
//---
| |
ds = (m_pos - ds); // numero de digitos de la parte decimal
| |
digitos += ds;
| |
exponente -= ds;
| |
}
| |
if(STRCONV_DECX_CH_IS_E(ch)) //
| |
{
| |
bool exp_positivo = true;
| |
ch = m_raw[++m_pos] ^ '0';
| |
if(ch > 9)
| |
{
| |
if(STRCONV_DECX_CH_IS_MINUS(ch))
| |
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
| |
{
| |
DOMBASEUTIL_PARSE_NUM_U1(expo)
| |
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
| |
{
| |
DOMBASEUTIL_PARSE_SKIP_LZ
| |
} // pos apunta al curr no cero ch ya tiene su valor en caso sea 00000x (no numero) sale..
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
| |
STRCONV_TOV_ALG(expo, ch)
| |
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
| |
{
| |
if(expo > 0) // es valido
| |
break; // no ov
| |
}
| |
else // sigue saltamos todo lo que hya
| |
{
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
}
| |
expo = INT_MAX;
| |
break;
| |
}
| |
exponente += exp_positivo ? expo : -expo;
| |
}
| |
//--- 1 dado que start incluye el -
| |
if(STRCONV_DOUBLE_SAFE_DBL_P(digitos, exponente, 1))
| |
{
| |
TsnBitInterprete bit;
| |
bit.double_value = -STRCONV_TO_DOUBLE_ALG(exponente, v);
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
| |
m_cinta[m_cinta_pos++] = bit.long_value;
| |
}
| |
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;
| |
}
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
break;
| |
}
| |
| |
//---
| |
case TSN_JSON_TOK_NUMBER:
| |
{
| |
//---
| |
ulong v = 0;
| |
const int start = m_pos;
| |
uchar ch = m_raw[start] ^ '0';
| |
const uchar fc = ch;
| |
| |
//---
| |
switch(0)
| |
{
| |
default: // scope con psoiblidad de break.
| |
{
| |
//---
| |
DOMBASEUTIL_PARSE_NUM_U1(v)
| |
if(!v)
| |
{
| |
m_last_err = TSN_JSON_ERR_LEADING_ZEROS;
| |
m_next = TSN_JSON_TOK_INVALID;
| |
continue;
| |
}
| |
//--- 19 iteraciones maximo
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
| |
STRCONV_TOV_ALG(v, ch)
| |
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)
| |
{
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
}
| |
//--- 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;
| |
//--- 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
| |
if(STRCONV_DECX_CH_IS_DEC(ch)) // v por lo tanto llega bien aqui como entero unsigned valido
| |
{
| |
long exponente = 0; // exponente
| |
int digitos = m_pos - start; // digitos que se van acomulando (parte ent + dec)
| |
if(STRCONV_DECX_CH_IS_PDEC(ch)) // punto decimal (tomar precuacion aqui si v puede dar overflow y voltear no hay chekeo)
| |
{
| |
int ds = ++m_pos;
| |
if((ch = m_raw[m_pos] ^ '0') > 9)
| |
{
| |
m_last_err = TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP;
| |
return false;
| |
}
| |
while(true)
| |
{
| |
//DOMBASEUTIL_NUM_PROCCES_FIRST_DEC(v, ch, m_pos, ds, digitos)
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_18(v)
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
break;
| |
}
| |
//---
| |
ds = (m_pos - ds); // numero de digitos de la parte decimal
| |
digitos += ds;
| |
exponente -= ds;
| |
}
| |
if(STRCONV_DECX_CH_IS_E(ch)) //
| |
{
| |
bool exp_positivo = true;
| |
ch = m_raw[++m_pos] ^ '0';
| |
if(ch > 9)
| |
{
| |
if(STRCONV_DECX_CH_IS_MINUS(ch))
| |
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)
| |
{
| |
DOMBASEUTIL_PARSE_NUM_U1(expo)
| |
if(expo == 0) // leading zeros.. ahora mismo aun hay digitos pero el primero es 0..
| |
{
| |
DOMBASEUTIL_PARSE_SKIP_LZ
| |
} // pos apunta al curr no cero ch ya tiene su valor en caso sea 00000x (no numero) sale..
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(expo)
| |
STRCONV_TOV_ALG(expo, ch)
| |
if((ch = m_raw[++m_pos] ^ '0') > 9) // 10cimo digito
| |
{
| |
if(expo > 0) // es valido
| |
break; // no ov
| |
}
| |
else // sigue saltamos todo lo que hya
| |
{
| |
DOMBASEUTIL_NUM_SKIP_NUMBER
| |
}
| |
expo = INT_MAX;
| |
break;
| |
}
| |
exponente += exp_positivo ? expo : -expo;
| |
}
| |
//---
| |
if(STRCONV_DOUBLE_SAFE_DBL(digitos, exponente))
| |
{
| |
TsnBitInterprete bit;
| |
bit.double_value = STRCONV_TO_DOUBLE_ALG(exponente, v);
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_REAL;
| |
m_cinta[m_cinta_pos++] = bit.long_value;
| |
}
| |
else
| |
{
| |
JSONPARSERBYLEO_NUM_MAKE_STRING
| |
}
| |
}
| |
else
| |
{
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_UINTEGER;
| |
m_cinta[m_cinta_pos++] = (long)v;
| |
}
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
break;
| |
}
| |
| |
//---
| |
case TSN_JSON_TOK_STRING:
| |
{
| |
//---
| |
const int start = ++m_pos;
| |
| |
//---
| |
#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;
| |
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);
| |
| |
//---
| |
if((has_bs | has_qt) == 0) // Caso comun. .. ninguno de los dos.. continuamos..
| |
{
| |
m_pos += 8;
| |
continue;
| |
}
| |
| |
//---
| |
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_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
| |
| |
//---
| |
m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag_real);
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++; // Luego del "
| |
break;
| |
}
| |
| |
//--- 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");
| |
| |
//---
| |
if(qt_final) // Hay un qt real de cierre
| |
{
| |
//---
| |
// Avanzamos y cerramos..
| |
m_pos += g_tsntables_table_ctz_i8[qt_final];
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
| |
//---
| |
m_pos++;
| |
break;
| |
}
| |
else
| |
{
| |
m_pos += 8;
| |
// 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
| |
}
| |
}
| |
}
| |
#else // JSONPARSERBYLEO_DESACTIVE_SWAR
| |
//--- Char por char
| |
while(true)
| |
{
| |
const uchar c = m_raw[m_pos];
| |
if(c == '\\')
| |
{
| |
m_pos += 2;
| |
continue;
| |
}
| |
if(c == '"')
| |
{
| |
// STRING 1 slot: [tipo(4)|len(28low)|start(32high)]
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING | long(m_pos - start) << TSN_SBL_BIT_STR_LEN |
| |
long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++;
| |
break;
| |
}
| |
m_pos++;
| |
}
| |
#endif // JSONPARSERBYLEO_DESACTIVE_SWAR
| |
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
| |
//---
| |
break;
| |
}
| |
case TSN_JSON_TOK_BOOL_TRUE:
| |
{
| |
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)
| |
return false;
| |
| |
//---
| |
m_pos++;
| |
m_cinta[m_cinta_pos++] = (JSON_VTYPE_BOOLEAN | 1LL << 4);
| |
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
break;
| |
}
| |
case TSN_JSON_TOK_BOOL_FALSE:
| |
{
| |
//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;
| |
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++;
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_BOOLEAN;
| |
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
break;
| |
}
| |
case TSN_JSON_TOK_NULL:
| |
{
| |
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)
| |
return false;
| |
| |
//---
| |
m_pos++;
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_NULL;
| |
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
break;
| |
}
| |
case TSN_JSON_TOK_COMMA:
| |
{
| |
//---
| |
if(m_stak_curr_state == TSN_JSON_CTX_IN_OBJ)
| |
{
| |
while(m_raw[++m_pos] != '"') {}
| |
m_next = TSN_JSON_TOK_KEY;
| |
}
| |
else
| |
{
| |
TSN_JSON_NEXT_VALUE_COMM_KEY
| |
}
| |
break;
| |
}
| |
case TSN_JSON_TOK_LLAVE_INI:
| |
{
| |
//TSN_JSON_RESERVAR(1)
| |
m_cinta[m_cinta_pos] = JSON_VTYPE_OBJ;
| |
| |
//---
| |
m_stak_curr++;
| |
m_stak_curr_state = TSN_JSON_CTX_IN_OBJ;
| |
m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_OBJ;
| |
m_stak_num[m_stak_curr] = 0;
| |
m_stak_pos[m_stak_curr] = m_cinta_pos++;
| |
| |
//---
| |
m_cinta[m_cinta_pos++] = m_pos++;
| |
| |
//---
| |
TSN_JSON_NEXT_LLAVE_INI
| |
| |
//---
| |
break;
| |
}
| |
case TSN_JSON_TOK_COR_INI:
| |
{
| |
m_cinta[m_cinta_pos] = JSON_VTYPE_ARR;
| |
| |
//---
| |
m_stak_curr++;
| |
m_stak_curr_state = TSN_JSON_CTX_IN_ARR;
| |
m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_ARR;
| |
m_stak_num[m_stak_curr] = 0;
| |
m_stak_pos[m_stak_curr] = m_cinta_pos++;
| |
| |
//---
| |
m_cinta[m_cinta_pos++] = m_pos++;
| |
| |
//---
| |
uchar _c = m_raw[m_pos];
| |
while(_c < 33)
| |
_c = m_raw[++m_pos];
| |
| |
//---
| |
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;
| |
}
| |
| |
//---
| |
break;
| |
}
| |
case TSN_JSON_TOK_LLAVE_END:
| |
case TSN_JSON_TOK_COR_END:
| |
{
| |
//---
| |
const int lp = m_stak_pos[m_stak_curr];
| |
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;
| |
m_cinta[lp + 1] |= long(m_pos) << TSN_JSON_BIT_END_T;
| |
| |
//---
| |
if(--m_stak_curr < 0)
| |
return true;
| |
| |
//---
| |
m_stak_curr_state = m_stak_state[m_stak_curr];
| |
| |
//---
| |
m_pos++;
| |
| |
//---
| |
TSN_JSON_AUMENT
| |
TSN_JSON_NEXT_NO_NEXT_KEY
| |
| |
//---
| |
break;
| |
}
| |
case TSN_JSON_TOK_KEY:
| |
{
| |
const int start = ++m_pos;
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
| |
| |
//--- Pase inicial 8 en 8
| |
while(true)
| |
{
| |
// "asdasdasd".........."
| |
// 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;
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
const ulong x_bs = chunk ^ TSNTABLES_SWAR_MASK_BACK_SLASH;
| |
ulong has_bs = TSNTABLES_SWAR_HAS(x_bs);
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
| |
const ulong x_qt = chunk ^ TSNTABLES_SWAR_MASK_COMILLA;
| |
const ulong has_qt = TSNTABLES_SWAR_HAS(x_qt);
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
if((has_bs | has_qt) == 0) // Caso comun. .. ninguno de los dos.. continuamos..
| |
{
| |
m_pos += 8;
| |
continue;
| |
}
| |
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
if(has_qt == 0) // Caso comun. .. ninguno de los dos.. continuamos..
| |
{
| |
m_pos += 8;
| |
continue;
| |
}
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
| |
| |
//---
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
if(has_bs == 0) // Si not iene bs (pero confirmamos que no es 0)
| |
// Entonces no tirne bs pero si qt salimos de una..
| |
{
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
const ulong flag_real = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_qt);
| |
| |
//---
| |
m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag_real);
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++; // Luego del "
| |
break;
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
}
| |
| |
//---
| |
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;
| |
| |
//---
| |
if(qt_final) // Hay un qt real de cierre
| |
{
| |
//---
| |
// Avanzamos y cerramos..
| |
m_pos += g_tsntables_table_ctz_i8[qt_final];
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_STRING
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++; // Luego del "
| |
break;
| |
}
| |
else
| |
{
| |
m_pos += 8;
| |
// Print(CharToString(m_raw[m_pos]));
| |
if(((prev & compacted_bs) >> 7U) != 0) // Overflow el ultimo char es \ y el siguiente escapa
| |
{
| |
//Print("siuu");
| |
m_pos++; // Uno mas.. luego del currend
| |
}
| |
}
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
}
| |
| |
| |
#else // JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
| |
| |
//--- Char por char
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
while(true)
| |
{
| |
const uchar c = m_raw[m_pos];
| |
if(c == '\\')
| |
{
| |
m_pos += 2;
| |
continue;
| |
}
| |
if(c == '"')
| |
{
| |
//---
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++;
| |
break;
| |
}
| |
m_pos++;
| |
}
| |
#else // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS*/
| |
| |
//---
| |
while(m_raw[m_pos] != '"')
| |
m_pos++;
| |
| |
//---
| |
m_cinta[m_cinta_pos++] = JSON_VTYPE_KEY
| |
| long(m_pos - start) << TSN_SBL_BIT_STR_LEN
| |
| long(start) << TSN_SBL_BIT_STR_START;
| |
m_pos++;
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
| |
#endif // JSONPARSERBYLEO_ACTIVE_SWAR_KEYS
| |
| |
//--- Find :
| |
while(true)
| |
{
| |
//---
| |
if(m_raw[m_pos] == ':')
| |
break;
| |
| |
//---
| |
m_pos++;
| |
if(m_pos >= m_len)
| |
{
| |
m_last_err = TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS;
| |
return false;
| |
}
| |
}
| |
| |
//--- Buscamos valor
| |
TSN_JSON_NEXT_VALUE_COMM_KEY
| |
| |
//---
| |
break;
| |
}
| |
default:
| |
return false;
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
__forceinline int CJsonParser::GetStepPure(const int idx) const
| |
{
| |
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
| |
{
| |
case JSON_VTYPE_KEY:
| |
return 1;
| |
case JSON_VTYPE_OBJ:
| |
case JSON_VTYPE_ARR:
| |
case JSON_VTYPE_UINTEGER:
| |
case JSON_VTYPE_INTEGER:
| |
case JSON_VTYPE_REAL:
| |
return 2;
| |
case JSON_VTYPE_BOOLEAN:
| |
case JSON_VTYPE_STRING:
| |
case JSON_VTYPE_NULL:
| |
return 1;
| |
default:
| |
return 1;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| GetStep: posiciones que ocupa el nodo idx en la cinta |
| |
//+------------------------------------------------------------------+
| |
__forceinline int CJsonParser::GetStep(const int idx)
| |
const
| |
{
| |
switch(int(m_cinta[idx] & TSN_SBL_BIT_MASK_TYPE))
| |
{
| |
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);
| |
case JSON_VTYPE_UINTEGER:
| |
case JSON_VTYPE_INTEGER:
| |
case JSON_VTYPE_REAL:
| |
return 2;
| |
case JSON_VTYPE_BOOLEAN:
| |
case JSON_VTYPE_STRING:
| |
case JSON_VTYPE_NULL:
| |
return 1;
| |
default:
| |
return 1;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
CJsonNode CJsonParser::GetRoot()
| |
{
| |
if(m_cinta_pos == 0)
| |
return CJsonNode::EMPTY_NODE;
| |
return CJsonNode(&this, 0, GetStep(0));
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CJsonParser::SerializeToDom(CDomNodeBase *root, CDomNodeManager* manager, int cur, const int end)
| |
{
| |
//--- Temp
| |
m_last_err = TSN_JSON_NOT_ERR;
| |
CDomNodeBase* prev_value; // valolr qeu devuelve key
| |
CDomNodeBase* current_container[JSONPARSERBYLEO_MAX_STACK]; // contenedor
| |
int current_ends[JSONPARSERBYLEO_MAX_STACK];
| |
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);
| |
| |
//---
| |
current_container[0] = root;
| |
current_ends[sp] = end;
| |
| |
//---
| |
cur += 2;
| |
| |
//--- It
| |
while(true)
| |
{
| |
//--- Check
| |
while(cur >= current_ends[sp])
| |
{
| |
sp--; // Nivel menos
| |
//Print("sp luego: ", sp);
| |
if(sp < 0)
| |
return true;
| |
}
| |
//---
| |
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
| |
//Print(EnumToString(tipo), " | ", cur, " | " , sp);
| |
//---
| |
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);
| |
#ifdef JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
const string str = Unescape(s, s + slen - 1);
| |
#else
| |
const string str = CharArrayToString(m_raw, s, slen);
| |
#endif // JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS
| |
| |
prev_value = current_container[sp][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)) << 1;
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR) // [{}]
| |
{
| |
const int lock = sp++;
| |
current_container[sp] = new CDomNodeBase(manager);
| |
current_container[sp].NewObj(count);
| |
current_container[lock].AddItem(current_container[sp]);
| |
}
| |
else // {key:{}}
| |
{
| |
sp++;
| |
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(manager);
| |
current_container[sp].NewArr(count);
| |
current_container[lock].AddItem(current_container[sp]);
| |
}
| |
else // {key:[]}
| |
{
| |
sp++;
| |
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_UINTEGER:
| |
{
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR)
| |
current_container[sp].AddItem(new CDomNodeBase(manager, ulong(m_cinta[cur + 1])));
| |
else
| |
prev_value = (ulong)m_cinta[cur + 1];
| |
break;
| |
}
| |
case JSON_VTYPE_INTEGER:
| |
{
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR)
| |
current_container[sp].AddItem(new CDomNodeBase(manager, m_cinta[cur + 1]));
| |
else
| |
prev_value = m_cinta[cur + 1];
| |
break;
| |
}
| |
case JSON_VTYPE_REAL:
| |
{
| |
TsnBitInterprete un;
| |
un.long_value = m_cinta[cur + 1];
| |
| |
//---
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR)
| |
current_container[sp].AddItem(new CDomNodeBase(manager, 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(manager, 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);
| |
| |
//---
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR)
| |
{
| |
CDomNodeBase* ptr = new CDomNodeBase(TSN_SBL_BASE_TYPE_STR, manager);
| |
current_container[sp].AddItem(ptr); // lo agregamos
| |
const int idx = ptr.m_v.ix;
| |
if(!MakeString(m_raw, s, slen, manager.m_string_stack[idx]))
| |
{
| |
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
| |
return false;
| |
}
| |
}
| |
else
| |
{
| |
prev_value.Type(TSN_SBL_BASE_TYPE_STR); // lo hacemos string
| |
const int idx = prev_value.m_v.ix;
| |
if(!MakeString(m_raw, s, slen, manager.m_string_stack[idx]))
| |
{
| |
m_last_err = TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR;
| |
return false;
| |
}
| |
}
| |
break;
| |
}
| |
case JSON_VTYPE_NULL:
| |
{
| |
//---
| |
if(current_container[sp].m_type == JSON_VTYPE_ARR)
| |
current_container[sp].AddItem(new CDomNodeBase(manager));
| |
else
| |
prev_value.m_type = JSON_VTYPE_NULL;
| |
break;
| |
}
| |
default:
| |
break;
| |
}
| |
| |
//---
| |
cur += GetStepPure(cur);
| |
}
| |
| |
//---
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CJsonParser::PrintCintaTypes(const int start, const int num) const
| |
{
| |
//---
| |
int p = fmax(start, 0);
| |
const int end = (num == WHOLE_ARRAY || (p + num) > m_cinta_pos) ? m_cinta_pos : (p + num);
| |
| |
//---
| |
string str;
| |
string text;
| |
StringReserve(text, 256); // algo razonable.
| |
| |
//---
| |
while(p < end)
| |
{
| |
const ENUM_JSON_VTYPE tipo = ENUM_JSON_VTYPE(m_cinta[p] & TSN_SBL_BIT_MASK_TYPE);
| |
text = "[" + (string)p + "] " + EnumToString(tipo) + " | ";
| |
| |
//---
| |
switch(tipo)
| |
{
| |
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);
| |
//---
| |
if(MakeString(m_raw, s, slen, str))
| |
text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + str + "\"";
| |
else
| |
text += "start=" + (string)s + " len=" + (string)slen + " val=Invalid";
| |
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] & TSN_JSON_BIT_RAW_MASK_S);
| |
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;
| |
}
| |
case JSON_VTYPE_UINTEGER:
| |
{
| |
text += "val=" + CValueToBuffer::ULLToStr(ulong(m_cinta[p + 1]));
| |
break;
| |
}
| |
case JSON_VTYPE_INTEGER:
| |
{
| |
text += "val=" + (string)m_cinta[p + 1];
| |
break;
| |
}
| |
case JSON_VTYPE_REAL:
| |
{
| |
TsnBitInterprete un;
| |
un.long_value = m_cinta[p + 1];
| |
text += "val=" + (string)un.double_value;
| |
break;
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
text += "val=" + (string)(bool)((m_cinta[p] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
| |
break;
| |
case JSON_VTYPE_STRING:
| |
{
| |
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);
| |
//---
| |
if(MakeString(m_raw, s, slen, str))
| |
text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + str + "\"";
| |
else
| |
text += "start=" + (string)s + " len=" + (string)slen + " val=Invalid";
| |
break;
| |
}
| |
case JSON_VTYPE_NULL:
| |
text += "null";
| |
break;
| |
//---
| |
default:
| |
break;
| |
}
| |
| |
Print(text);
| |
p += GetStepPure(p);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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)
| |
{
| |
//---
| |
string out = "";
| |
out.Reserve(256);
| |
| |
//---
| |
if(header.Length())
| |
out += "[" + header + "]\n";
| |
| |
//---
| |
out += StringFormat("JSON error at line %d, col %d:\n", line, col);
| |
| |
//---
| |
switch(err)
| |
{
| |
case TSN_JSON_ERR_INVALID_EXT_FILE:
| |
out += "Invalid file extension por JsonParserByLeo";
| |
break;
| |
case TSN_JSON_ERR_INVALID_CHAR:
| |
out += "Invalid character found in json";
| |
break;
| |
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL:
| |
out += "Invalid character find in json, finding comma or context close (], })";
| |
break;
| |
case TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI:
| |
out += "Invalid character find in json, finding valid value after '['";
| |
break;
| |
case TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL:
| |
out += "Invalid character find in json, finding valid value";
| |
break;
| |
case TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS:
| |
out += "Invalid JSON key, One of two errors: \"Expected a ':' after a JSON key\" or \"Malformed JSON while searching for characters.\"";
| |
break;
| |
case TSN_JSON_ERR_MALFOMED_LEN_SUPERADO:
| |
out += "Len has superated, but json are not closed, malformed json";
| |
break;
| |
case TSN_JSON_ERR_JSON_NOT_FINISH:
| |
out += "Json read has finish but not closed in ] or }, malformed json";
| |
break;
| |
case TSN_JSON_ERR_LEADING_ZEROS:
| |
out += "A number in JSON notation cannot have leading zeros.";
| |
break;
| |
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_EXP:
| |
out += "A number was expected after the 'E' exponent; an invalid character was found.";
| |
break;
| |
case TSN_JSON_ERR_EXPECTED_NUMBER_AFECTER_DECIMALP:
| |
out += "A numeric value was expected after the decimal point.";
| |
break;
| |
case TSN_JSON_ERR_MALFORMED_TRUE:
| |
out += "Malformed 'true' in json";
| |
break;
| |
case TSN_JSON_ERR_MALFORMED_FALSE:
| |
out += "Malformed 'false' in json";
| |
break;
| |
case TSN_JSON_ERR_MALFORMED_NULL:
| |
out += "Malformed 'null' in json";
| |
break;
| |
case TSN_JSON_ERR_IN_MATERIALIZE_STRING_PARSE_ERR:
| |
out += "Error materializing string; possible causes include an invalid escape character or a malformed \\u sequence.";
| |
break;
| |
case TSN_JSON_ERR_OVERFLOW_IN_STACK:
| |
out += "Overflow for maxium stack";
| |
break;
| |
case TSN_JSON_ERR_NOT_STRUCUTURAL_CHARS_FOUND:
| |
out += "Not structural character found in this json ({ | } | [ | ] | : | ,)";
| |
break;
| |
case TSN_JSON_ERR_INVALID_STATE_IN_PARSE_DOUBLE_E:
| |
out += "Invalid state for Json Sax Parsing, in parse double value";
| |
break;
| |
//---
| |
default:
| |
out += "Unknow error";
| |
break;
| |
}
| |
| |
//---
| |
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)
| |
{
| |
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:
| |
{
| |
if(m_next == TSN_JSON_TOK_INVALID)
| |
m_last_err = TSN_JSON_ERR_INVALID_CHAR;
| |
break;
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Arrays helpers para evitar la resolcuino de ctx en todo mommento |
| |
//+------------------------------------------------------------------+
| |
template <typename T>
| |
void CJsonParser::ToArray(int cur, T& out_arr[], const int end) const
| |
{
| |
//---
| |
int k = 0;
| |
switch(int(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
| |
{
| |
case JSON_VTYPE_UINTEGER:
| |
{
| |
while(cur < end)
| |
{
| |
out_arr[k++] = T(ulong(m_cinta[cur + 1]));
| |
cur += 2;
| |
}
| |
break;
| |
}
| |
case JSON_VTYPE_INTEGER:
| |
{
| |
while(cur < end)
| |
{
| |
out_arr[k++] = T(m_cinta[cur + 1]);
| |
cur += 2;
| |
}
| |
break;
| |
}
| |
case JSON_VTYPE_REAL:
| |
{
| |
while(cur < end)
| |
{
| |
TsnBitInterprete bit;
| |
bit.long_value = m_cinta[cur + 1];
| |
out_arr[k++] = T(bit.double_value);
| |
cur += 2;
| |
}
| |
break;
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
{
| |
while(cur < end)
| |
{
| |
out_arr[k++] = T((m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1);
| |
cur++;
| |
}
| |
break;
| |
}
| |
case JSON_VTYPE_STRING:
| |
{
| |
while(cur < end)
| |
{
| |
static string str;
| |
if(MakeString(m_raw, TSN_SBL_CLS_STR_START(cur), TSN_SBL_CLS_STR_LEN(cur), str))
| |
out_arr[k++] = T(str);
| |
//---
| |
cur++;
| |
}
| |
break;
| |
}
| |
default:
| |
break;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename T>
| |
bool CJsonParser::ExistInArray(int cur, const T val, const uint flags, const int end) const
| |
{
| |
while(cur < end)
| |
{
| |
//---
| |
uint ct = uint(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE);
| |
if(((1U << ct) & flags) == 0)
| |
{
| |
cur += GetStepPure(cur);
| |
continue;
| |
}
| |
| |
//---
| |
switch(ct)
| |
{
| |
case JSON_VTYPE_UINTEGER:
| |
{
| |
if((ulong)m_cinta[cur + 1] == T(val))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_INTEGER:
| |
{
| |
if(m_cinta[cur + 1] == T(val))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_REAL:
| |
{
| |
bit.long_value = m_cinta[cur + 1];
| |
if(bit.double_value == T(val))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_BOOLEAN:
| |
{
| |
if(val == T((m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_STRING:
| |
{
| |
static string str;
| |
if(MakeString(m_raw, TSN_SBL_CLS_STR_START(cur), TSN_SBL_CLS_STR_LEN(cur), str) && val == T(str))
| |
return true;
| |
break;
| |
}
| |
case JSON_VTYPE_NULL:
| |
return true;
| |
default:
| |
return false;
| |
}
| |
//---
| |
cur += GetStepPure(cur);
| |
}
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename T>
| |
bool CJsonParser::ExistInArrayHomogeneo(int cur, const T val, const int end) const
| |
{
| |
switch(int(m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
| |
{
| |
case TSN_SBL_BASE_TYPE_UINT:
| |
{
| |
while(cur < end)
| |
{
| |
if(val == T(ulong(m_cinta[cur + 1])))
| |
return true;
| |
cur += 2;
| |
}
| |
}
| |
case TSN_SBL_BASE_TYPE_INT:
| |
{
| |
while(cur < end)
| |
{
| |
if(val == T(m_cinta[cur + 1]))
| |
return true;
| |
cur += 2;
| |
}
| |
return false;
| |
}
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
while(cur < end)
| |
{
| |
TsnBitInterprete bit;
| |
bit.long_value = m_cinta[cur + 1];
| |
if(val == T(bit.double_value))
| |
return true;
| |
cur += 2;
| |
}
| |
return false;
| |
}
| |
case TSN_SBL_BASE_TYPE_BOL:
| |
{
| |
while(cur < end)
| |
{
| |
if(val == T((m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1))
| |
return true;
| |
cur++;
| |
}
| |
return false;
| |
}
| |
case TSN_SBL_BASE_TYPE_STR:
| |
{
| |
while(cur < end)
| |
{
| |
static string str;
| |
if(MakeString(m_raw, TSN_SBL_CLS_STR_START(cur), TSN_SBL_CLS_STR_LEN(cur), str) && val == T(str))
| |
return true;
| |
cur++;
| |
}
| |
break;
| |
}
| |
default:
| |
return false;
| |
}
| |
return false;
| |
}
| |
| |
//---
| |
}
| |
#endif // JSONPARSERBYLEO_SRC_JSONPARSER_MQH
|