//+------------------------------------------------------------------+
| |
//| Parser.cpp |
| |
//| Copyright 2026, Niquel Mendoza. |
| |
//| https://www.mql5.com/ |
| |
//+------------------------------------------------------------------+
| |
| |
//+------------------------------------------------------------------+
| |
//| Pre-Defines |
| |
//+------------------------------------------------------------------+
| |
#pragma once
| |
#define TSNPARSERIN_CPP_DLL
| |
#define TSN_TARGET_AVX2
| |
| |
//+------------------------------------------------------------------+
| |
//| Includes |
| |
//+------------------------------------------------------------------+
| |
//--- Includes extra
| |
#include "..\\..\\..\\BasesParserSLan\\Src\\Def.mqh"
| |
#include "..\\JsonDefines.mqh"
| |
#include <cstdio>
| |
| |
//--- Definiciones base
| |
#if defined(TSN_TARGET_AVX512)
| |
#include <immintrin.h>
| |
// kernel con __m512i, _mm512_*, 1 carga de 64 bytes
| |
| |
#elif defined(TSN_TARGET_AVX2)
| |
#include <immintrin.h>
| |
// kernel con __m256i, _mm256_*, 2 cargas de 32 bytes (lo que ya armamos)
| |
| |
#elif defined(TSN_TARGET_SSE42)
| |
#include <immintrin.h>
| |
// kernel con __m128i, _mm_*, 4 cargas de 16 bytes
| |
| |
#else
| |
#error "Debes definir TSN_TARGET_AVX512, TSN_TARGET_AVX2 o TSN_TARGET_SSE42"
| |
#endif
| |
| |
#include <cstdarg>
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
using ulong = uint64_t;
| |
using uchar = uint8_t;
| |
using ushort = uint16_t;
| |
| |
//--- mascaras
| |
#define TSNTABLES_MASK_IMPARES_F (0xAAAAAAAAAAAAAAAA)
| |
#define TSNTABLES_MASK_PARES_F (0x5555555555555555)
| |
| |
//+------------------------------------------------------------------+
| |
//| Macros |
| |
//+------------------------------------------------------------------+
| |
//---
| |
#define TSN_JSON_AUMENT m_stak_num[m_stak_curr]++;
| |
| |
//--- Al terminar el parseo qeu hacer
| |
#define TSN_JSON_ON_FINISH \
| |
*m_cinta_pos = cinta_pos; \
| |
*m_pos = pos;
| |
| |
//--- clave
| |
#define TSN_JSON_PARSE_KEY \
| |
pos = m_index[sp++]; \
| |
m_cinta[cinta_pos++] = (int64_t)JSON_VTYPE_KEY \
| |
| int64_t(pos - start) << TSN_SBL_BIT_STR_LEN \
| |
| int64_t(start) << TSN_SBL_BIT_STR_START; \
| |
pos = m_index[sp++]; \
| |
if(m_raw[pos++] != ':') \
| |
{ \
| |
*m_last_err = TSN_JSON_ERR_MALFODERD_KEY_EXPECTED_DOS_PUNTOS; \
| |
TSN_JSON_ON_FINISH \
| |
return false; \
| |
}
| |
| |
//--- Se usa solo luego de un cor ini aqui peuden ir " [ { t\f\n (1-9\-) ]
| |
#define TSN_JSON_NEXT_COR_INI \
| |
while(true) \
| |
{ \
| |
const uchar _c = m_raw[pos]; \
| |
if(_c < 33) \
| |
{ \
| |
pos++; \
| |
continue; \
| |
} \
| |
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; \
| |
TSN_JSON_ON_FINISH \
| |
return false; \
| |
} \
| |
break; \
| |
}
| |
| |
//--- Luego de una coma en array
| |
// Luego de una , y KEY siempre siempre valor
| |
#define TSN_JSON_NEXT_VALUE_COMM_KEY \
| |
while(true) \
| |
{ \
| |
const uchar _c = m_raw[pos]; \
| |
if(_c < 33) \
| |
{ \
| |
pos++; \
| |
continue; \
| |
} \
| |
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; \
| |
TSN_JSON_ON_FINISH \
| |
return false; \
| |
} \
| |
break; \
| |
}
| |
| |
#define JSONPARSERBYLEO_FULL_NEXT \
| |
pos = m_index[sp++]; \
| |
m_next = g_table_json_tokens[m_raw[pos]]; \
| |
if(((1 << m_next) & m_stak_curr_state) == 0) \
| |
{ \
| |
*m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL; \
| |
TSN_JSON_ON_FINISH \
| |
return false; \
| |
}
| |
| |
//--- macro para parsear numeros
| |
#define JSONPARSERBYLEO_PARSE_NUMBER(SING) \
| |
int64_t v = 0; \
| |
uchar ch = m_raw[pos] ^ '0'; \
| |
while(true) \
| |
{ \
| |
v = (v << 3) + (v << 1) + ch; \
| |
pos++; \
| |
ch = m_raw[pos] ^ '0'; \
| |
if(ch < 10) \
| |
continue; \
| |
else \
| |
if(ch == 30 || (ch | 0x20) == 117) \
| |
{ \
| |
double val = double(v); \
| |
if(ch == 30) \
| |
{ \
| |
pos++; \
| |
int64_t frac_int = 0; \
| |
ushort fract_digits = 0; \
| |
while(true) \
| |
{ \
| |
ch = m_raw[pos] ^ '0'; \
| |
if(ch > 9) \
| |
break; \
| |
frac_int = (frac_int << 3) + (frac_int << 1) + ch; \
| |
fract_digits++; \
| |
pos++; \
| |
} \
| |
val += frac_int * g_Exp10[fract_digits]; \
| |
} \
| |
if((ch | 0x20) == 117) \
| |
{ \
| |
pos++; \
| |
bool exp_sign = true; \
| |
ch = m_raw[pos] ^ '0'; \
| |
if(ch > 9) \
| |
{ \
| |
if(ch == 29) \
| |
exp_sign = false; \
| |
pos++; \
| |
ch = m_raw[pos] ^ '0'; \
| |
} \
| |
ushort exp_val = 0; \
| |
while(true) \
| |
{ \
| |
exp_val = (exp_val << 3) + (exp_val << 1) + ch; \
| |
pos++; \
| |
ch = m_raw[pos] ^ '0'; \
| |
if(ch > 9) \
| |
break; \
| |
} \
| |
val *= (exp_sign) ? g_Pow10[exp_val] : g_Exp10[exp_val]; \
| |
} \
| |
TsnBitInterprete bit; \
| |
bit.double_value = val; \
| |
m_cinta[cinta_pos++] = JSON_VTYPE_REAL; \
| |
m_cinta[cinta_pos++] = SING(bit.long_value); \
| |
break; \
| |
} \
| |
else \
| |
{ \
| |
m_cinta[cinta_pos++] = JSON_VTYPE_INTEGER; \
| |
m_cinta[cinta_pos++] = SING(v); \
| |
break; \
| |
} \
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
extern "C" __declspec(dllexport)
| |
// array ya allocado tambein raw solo hace falta rellenar
| |
bool __stdcall JsonParserResolve(
| |
const uint8_t* m_raw, // datos de entrada
| |
int64_t* m_cinta, // cinta de datos
| |
int* m_index, // array de indices structurales
| |
const int len, // tamaño de raw
| |
const int m_offset, // offset de inicio para pos
| |
| |
//--- salida
| |
int* m_last_err, // ultimo err
| |
int* m_cinta_pos, // posicion actul en la cinta
| |
int* m_pos // ultima posicion en la lecutra de raw
| |
); // retorna true en caso de exito, false de lo contrario..
| |
//+------------------------------------------------------------------+
|