2026-08-04 08:01:43 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| JsonSaxImp.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_JSONSAXIMP_MQH
|
| | | #define JSONPARSERBYLEO_SRC_JSONSAXIMP_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "JsonParser.mqh"
|
| | | #include "JsonSax.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define JSONPARSERBYLEO_SAX_STR_START (0)
|
2026-08-04 09:07:11 -05:00 | | | /* Notas de mi parte
|
| | | Siempre cuando vuevea a llamar aseungramtne de agregar datos amenos un solo dato es lo minimo..
|
| | | */
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CJsonParserStream : public CJsonParser
|
| | | {
|
| | | private:
|
| | | ITsnJsonParserStream* m_in;
|
2026-08-04 09:02:31 -05:00 | | | bool m_del_caller;
|
| | |
|
| | | //---
|
2026-08-04 08:01:43 -05:00 | | | uchar m_prev_c;
|
| | | uint8_t m_in_n;
|
| | | long m_mask;
|
| | | long m_last_number;
|
| | | double m_last_number_dbl;
|
| | |
|
| | | //----
|
| | | long m_sax_frac_int;
|
2026-09-18 14:11:09 -05:00 | | | ushort m_sax_frac_digits;
|
| | | uchar m_ch;
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | public:
|
2026-08-04 09:02:31 -05:00 | | | CJsonParserStream(void) : m_del_caller(false) {}
|
| | | ~CJsonParserStream(void);
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
2026-08-04 09:02:31 -05:00 | | | __forceinline int CurrentStack() const { return m_stak_curr + 1; }
|
| | | __forceinline int CurrentStackState() const { return m_stak_curr_state; }
|
2026-08-04 08:01:43 -05:00 | | | void KillParse();
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | void SetCaller(ITsnJsonParserStream* caller, bool del);
|
| | | void CheckLimpieza();
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | bool ParseSreamSax();
|
| | | };
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | CJsonParserStream::~CJsonParserStream(void)
|
| | | {
|
| | | if(m_del_caller && CheckPointer(m_in) == POINTER_DYNAMIC)
|
| | | delete m_in;
|
| | | }
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // Al terminar solo lo poneres en tok invalid..
|
| | | #define JSONPARSERBYLEO_SAX_ON_FINISH m_next=TSN_JSON_TOK_INVALID;
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CJsonParserStream::KillParse(void)
|
| | | {
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | }
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CJsonParserStream::SetCaller(ITsnJsonParserStream *caller, bool del)
|
| | | {
|
| | | m_del_caller = del;
|
| | | m_in = caller;
|
| | | m_in.MainPointer(&this);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CJsonParserStream::CheckLimpieza(void)
|
| | | {
|
| | | // Revisamos el estado previo
|
| | | // La idea ees ver si estamos en string SI no lo estabamos entonces es seguro retrazar el pos
|
| | | if(((1 << m_next) & (TSN_JSON_F_KEY | TSN_JSON_F_STRING)) == 0)
|
| | | {
|
| | | m_pos = 0; // Reiniciamos el pos
|
| | | // Entonces la idea es que la siguiente llama el que llame a esta clase
|
| | | // Llente el array auqneusea conreserva pero hasta m_len
|
| | | // Lo deal seria ejeuctar esto antes de cada relleneado
|
| | | }
|
| | | // No se puede..
|
| | | }
|
| | |
|
| | |
|
2026-08-26 19:48:01 -05:00 | | |
|
2026-08-04 08:01:43 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CJsonParserStream::ParseSreamSax(void)
|
| | | {
|
| | | //--- Inicial
|
| | | if(m_next == TSN_JSON_TOK_INVALID)
|
| | | {
|
2026-08-26 19:48:01 -05:00 | | | // general
|
2026-08-04 08:01:43 -05:00 | | | m_stak_curr = -1;
|
| | | m_last_err = TSN_JSON_NOT_ERR;
|
| | | m_pos = m_offset;
|
2026-08-26 19:48:01 -05:00 | | | // numeros
|
| | | m_last_number = 0;
|
| | | m_mask = 0;
|
| | | //dbl
|
| | | m_in_n = 0;
|
| | | // extra
|
2026-08-04 08:01:43 -05:00 | | | m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = -1; // string y keys
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | m_in.OnStartDocument();
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //--- Inicial
|
| | | const uchar _f_c = m_raw[m_pos];
|
| | | if(_f_c == '{')
|
| | | {
|
| | | m_next = TSN_JSON_TOK_LLAVE_INI;
|
| | | }
|
| | | else
|
| | | if(_f_c == '[')
|
| | | {
|
| | | m_next = TSN_JSON_TOK_COR_INI;
|
| | | }
|
| | | 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)
|
| | | {
|
2026-08-26 19:48:01 -05:00 | | | case TSN_JSON_TOK_NUMBER_NEG:
|
2026-08-04 08:01:43 -05:00 | | | {
|
| | | //---
|
2026-08-26 19:48:01 -05:00 | | | // m_last_number=0 ya viene a 0
|
| | | m_mask = -1; // solo cambiamos la mascara
|
| | | m_next = TSN_JSON_TOK_NUMBER;
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
2026-08-26 19:48:01 -05:00 | | | if(++m_pos >= m_len) // Ahora en numero de lo contraio a la siguiente..
|
| | | return true;
|
| | | break;
|
| | | }
|
2026-08-04 08:01:43 -05:00 | | |
|
2026-08-26 19:48:01 -05:00 | | | //---
|
| | | case TSN_JSON_TOK_NUMBER:
|
| | | {
|
2026-08-04 08:01:43 -05:00 | | | //---
|
2026-09-18 14:11:09 -05:00 | | | m_ch = m_raw[m_pos] ^ '0';
|
2026-08-04 08:01:43 -05:00 | | |
|
2026-08-26 19:48:01 -05:00 | | | //--- bucle principal
|
2026-08-04 08:01:43 -05:00 | | | while(true)
|
| | | {
|
2026-09-18 14:11:09 -05:00 | | | m_last_number = (m_last_number << 3) + (m_last_number << 1) + m_ch;
|
2026-08-04 08:01:43 -05:00 | | | m_pos++;
|
| | | if(m_pos >= m_len)
|
2026-08-26 19:48:01 -05:00 | | | return true;
|
2026-09-18 14:11:09 -05:00 | | | m_ch = m_raw[m_pos] ^ '0';
|
| | | if(m_ch < 10)
|
2026-08-04 08:01:43 -05:00 | | | continue;
|
| | | else
|
2026-09-18 14:11:09 -05:00 | | | if(m_ch == 30 || (m_ch | 0x20) == 117)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-09-18 14:11:09 -05:00 | | | m_prev_c = m_ch;
|
2026-08-04 08:01:43 -05:00 | | | m_last_number_dbl = double(m_last_number);
|
| | | m_next = TSN_JSON_TOK_SAX_DBL;
|
2026-08-26 19:48:01 -05:00 | | | // dbl ya reincia ..
|
2026-08-04 08:01:43 -05:00 | | | break;
|
| | | }
|
| | | else
|
| | | {
|
| | | m_in.OnInteger((m_last_number ^ m_mask) - m_mask);
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
2026-08-26 19:48:01 -05:00 | | | // reiniciamos
|
| | | m_last_number = 0;
|
| | | m_mask = 0;
|
| | | break;
|
2026-08-04 08:01:43 -05:00 | | | }
|
| | | }
|
| | |
|
| | | //--- no hago el m_pos++ dado que ahora mismo estamo en el seg char
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TSN_JSON_TOK_STRING:
|
| | | {
|
| | | //---
|
| | | //TSN_JSON_RESERVAR(2)
|
| | |
|
| | | //---
|
| | | if(m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] == -1)
|
| | | {
|
| | | m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = ++m_pos;
|
| | | }
|
| | |
|
| | | //--- Char por char
|
2026-08-04 09:02:31 -05:00 | | | while(true)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | if(m_pos >= m_len)
|
| | | {
|
| | | return true;
|
| | | }
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | const uchar c = m_raw[m_pos];
|
| | |
|
| | | //---
|
| | | if(c == '\\')
|
| | | {
|
| | | m_pos += 2;
|
| | | continue;
|
| | | }
|
| | | if(c == '"')
|
| | | {
|
| | | //---
|
| | | const int start = m_stak_pos[JSONPARSERBYLEO_SAX_STR_START];
|
| | | m_in.OnString(start, m_pos - start);
|
| | |
|
| | | //---
|
| | | m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = -1;
|
| | |
|
| | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_pos++;
|
| | | }
|
| | |
|
| | |
|
| | | //---
|
| | | // No enconto nada.. entonces.. sale noma vovemos luego
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_BOOL_TRUE:
|
| | | {
|
| | | //TSN_JSON_RESERVAR(1)
|
| | | // t r u e W
|
| | | // [-4] [-3] [-2] [-1] [0]
|
| | |
|
| | | //---
|
| | | if(m_pos + 5 < m_len)
|
| | | {
|
| | | m_pos += 4; // Aumentamos y continuamos
|
2026-08-04 09:29:06 -05:00 | | | m_in.OnBool(true);
|
2026-08-04 08:01:43 -05:00 | | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | | }
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_BOOL_FALSE:
|
| | | {
|
| | | //TSN_JSON_RESERVAR(1)
|
| | | // f a l s e W
|
| | | // [] [-4] [-3] [-2 ] [-1] [0]
|
| | |
|
| | | //---
|
| | | if(m_pos + 6 < m_len)
|
| | | {
|
| | | m_pos += 5; // Aumentamos y continuamos
|
2026-08-04 09:29:06 -05:00 | | | m_in.OnBool(false);
|
2026-08-04 08:01:43 -05:00 | | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | | }
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_NULL:
|
| | | {
|
| | | //TSN_JSON_RESERVAR(1)
|
| | | // n u l l W
|
| | | // [-4][-3][-2][-1][]
|
| | |
|
| | |
|
| | | //---
|
| | | // Solo si hay 5 chars mas si no no hacemo snada
|
| | | if(m_pos + 5 < m_len)
|
| | | {
|
| | | m_pos += 4; // Aumentamos y continuamos
|
| | | m_in.OnNull();
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | | }
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_COMMA:
|
| | | {
|
| | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | if(m_stak_curr_state == TSN_JSON_CTX_IN_OBJ)
|
| | | m_next = TSN_JSON_TOK_SAX_FIND_KEY;
|
| | | else
|
| | | m_next = TSN_JSON_TOK_SAX_COM_KEY;
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_LLAVE_INI:
|
| | | {
|
| | | //_--
|
| | | m_in.OnStartObj();
|
| | |
|
| | | //---
|
| | | m_stak_curr++;
|
2026-08-04 09:02:31 -05:00 | | | m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_OBJ;
|
| | | m_stak_curr_state = TSN_JSON_CTX_IN_OBJ;
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_LLAVE_INI;
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_COR_INI:
|
| | | {
|
| | | //_--
|
| | | m_in.OnStartArr();
|
| | |
|
| | | //---
|
| | | m_stak_curr++;
|
2026-08-04 09:02:31 -05:00 | | | m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_ARR;
|
| | | m_stak_curr_state = TSN_JSON_CTX_IN_ARR;
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_COR_INI;
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_LLAVE_END:
|
| | | {
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | m_stak_curr--;
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | m_in.OnEndObJ();
|
| | |
|
| | | //---
|
2026-08-04 09:02:31 -05:00 | | | if(m_stak_curr < 0) // termino
|
2026-08-04 08:01:43 -05:00 | | | {
|
| | | m_in.OnEndDocument();
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | return true;
|
| | | }
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | m_stak_curr_state = m_stak_state[m_stak_curr];
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_COR_END:
|
| | | {
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | m_stak_curr--;
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | m_in.OnEndArr();
|
| | |
|
| | | //---
|
2026-08-04 09:02:31 -05:00 | | | if(m_stak_curr < 0) // termino
|
2026-08-04 08:01:43 -05:00 | | | {
|
| | | m_in.OnEndDocument();
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | return true;
|
| | | }
|
| | |
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | m_stak_curr_state = m_stak_state[m_stak_curr];
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | | case TSN_JSON_TOK_KEY:
|
| | | {
|
| | | //---
|
| | | if(m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] == -1)
|
| | | {
|
| | | m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = ++m_pos;
|
| | | }
|
| | |
|
| | | //--- Char por char
|
2026-08-04 09:02:31 -05:00 | | | while(true)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-04 09:02:31 -05:00 | | | //---
|
| | | if(m_pos >= m_len)
|
| | | {
|
| | | return true;
|
| | | }
|
| | |
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | const uchar c = m_raw[m_pos];
|
| | |
|
| | | //---
|
| | | if(c == '\\')
|
| | | {
|
| | | m_pos += 2;
|
| | | continue;
|
| | | }
|
| | | if(c == '"')
|
| | | {
|
| | | //---
|
| | | const int start = m_stak_pos[JSONPARSERBYLEO_SAX_STR_START];
|
| | | m_in.OnKey(start, m_pos - start);
|
| | |
|
| | | //---
|
| | | m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = -1;
|
| | |
|
| | | //---
|
| | | m_pos++;
|
| | |
|
| | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_DOS_PUNTOS;
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_pos++;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | case TSN_JSON_TOK_INVALID:
|
| | | {
|
| | | m_last_err = TSN_JSON_ERR_INVALID_CHAR;
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | return false;
|
| | | }
|
| | |
|
| | | case TSN_JSON_TOK_SAX_NO_NEXT_KEY:
|
| | | {
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // esperando mas ...
|
| | |
|
| | | //---
|
| | | const uchar _c = m_raw[m_pos];
|
| | | if(_c < 33)
|
| | | {
|
| | | m_pos++;
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_next = g_table_json_tokens[_c];
|
| | | if(((1 << m_next) & m_stak_curr_state) == 0)
|
| | | {
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
2026-09-18 14:11:09 -05:00 | | | m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL;
|
2026-08-04 08:01:43 -05:00 | | | return false;
|
| | | }
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TSN_JSON_TOK_SAX_LLAVE_INI:
|
| | | {
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // esperando mas ...
|
| | |
|
| | | //---
|
| | | 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++;
|
| | | }
|
2026-08-04 09:02:31 -05:00 | | |
|
| | | //---
|
| | | break;
|
2026-08-04 08:01:43 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | case TSN_JSON_TOK_SAX_COR_INI:
|
| | | {
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // esperando mas ...
|
| | |
|
| | | //---
|
| | | const uchar _c = m_raw[m_pos];
|
| | | if(_c < 33)
|
| | | {
|
| | | m_pos++;
|
| | | continue;
|
| | | }
|
| | | m_next = g_table_json_tokens[_c];
|
| | | if(((1 << m_next) & TSN_JSON_F_VAL_COR) == 0)
|
| | | {
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
2026-09-18 14:11:09 -05:00 | | | m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI;
|
2026-08-04 08:01:43 -05:00 | | | return false;
|
| | | }
|
| | | break;
|
| | | }
|
| | | break;
|
| | | }
|
| | |
|
| | | case TSN_JSON_TOK_SAX_FIND_KEY:
|
| | | {
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // esperando mas ...
|
| | | //---
|
| | | if(m_raw[m_pos] == '"')
|
| | | {
|
| | | m_next = TSN_JSON_TOK_KEY;
|
| | | break;
|
| | | }
|
| | | m_pos++;
|
| | | }
|
| | | break;
|
| | | }
|
| | |
|
| | | case TSN_JSON_TOK_SAX_COM_KEY:
|
| | | {
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // esperando mas ...
|
| | |
|
| | | //---
|
| | | const uchar _c = m_raw[m_pos];
|
| | | if(_c < 33)
|
| | | {
|
| | | m_pos++;
|
| | | continue;
|
| | | }
|
| | | m_next = g_table_json_tokens[_c];
|
| | | if(((1 << m_next) & TSN_JSON_F_ALL_I_VAL) == 0)
|
| | | {
|
2026-09-18 14:11:09 -05:00 | | | m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL;
|
2026-08-04 08:01:43 -05:00 | | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | return false;
|
| | | }
|
| | | break;
|
| | | }
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | case TSN_JSON_TOK_SAX_DBL:
|
| | | {
|
| | | // Comentarios para que no te pierdas
|
| | | // En si la tenica a usar es como ir lockeradno o teneinedo estaods con reuso de varialbes
|
| | | // m_prev_c continee el ultimo char.. lo uso priemro para poder evitar una lectura de array mas
|
| | | // y luego lo utilizo mas adalante para no vover a ver si m_pos e E\e
|
| | | // Dado que podria no entrar si eso pasa
|
| | | // Ahora otras vairalevbs presents son m_in_n esta es como mi avarialbe de estado
|
| | | // La uso para ver en que fase estoy
|
| | | // Luego tmabien se reusa m_last_number en el E\e para ver si tenia signo o no
|
| | | // Aqui si neceisto persistencia.. por eso reutilizo esa varialbe..
|
| | | if(m_prev_c == 30)
|
| | | {
|
2026-08-26 19:48:01 -05:00 | | | if(m_in_n == 0) // etapa inicial 0
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_in_n++; // 1
|
2026-08-04 08:01:43 -05:00 | | | m_pos++;
|
| | | m_sax_frac_int = 0;
|
| | | m_sax_frac_digits = 0;
|
| | | }
|
| | |
|
| | | //---
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true;
|
| | |
|
| | | //---
|
2026-09-18 14:11:09 -05:00 | | | m_ch = m_raw[m_pos] ^ '0';
|
| | | if(m_ch > 9)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_in_n = 0; // Vuelta en 0 (ahora para procesar lod giitos)
|
2026-08-04 08:01:43 -05:00 | | | m_prev_c = 0; // Ahora ya no podra ingresar a este if
|
| | | m_last_number_dbl += m_sax_frac_int * g_Exp10[m_sax_frac_digits];
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
2026-09-18 14:11:09 -05:00 | | | m_sax_frac_int = (m_sax_frac_int << 3) + (m_sax_frac_int << 1) + m_ch;
|
2026-08-04 08:01:43 -05:00 | | | m_sax_frac_digits++;
|
| | | m_pos++;
|
| | | }
|
| | |
|
| | | //---
|
| | | // Pasamos con un char extra..
|
| | | }
|
| | |
|
| | | //--- Ahora procesamos E
|
2026-09-18 14:11:09 -05:00 | | | if(m_prev_c == 15 || (m_ch | 0x20) == 117) // e or E
|
2026-08-04 08:01:43 -05:00 | | | {
|
| | | //---
|
| | | switch(m_in_n)
|
| | | {
|
2026-08-26 19:48:01 -05:00 | | | case 0:
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_in_n++; // 1
|
2026-08-04 08:01:43 -05:00 | | | m_prev_c = 15;
|
2026-09-18 14:11:09 -05:00 | | |
|
| | | //---
|
| | | if(++m_pos >= m_len)
|
2026-08-04 08:01:43 -05:00 | | | return true; // Salimos
|
| | | // Cae al siguiente
|
| | | }
|
| | |
|
2026-08-26 19:48:01 -05:00 | | | case 1:
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_in_n++; // 2
|
2026-08-04 08:01:43 -05:00 | | | m_last_number = 1; // bool exp_sign = true;
|
| | |
|
| | | //---
|
2026-09-18 14:11:09 -05:00 | | | m_ch = m_raw[m_pos] ^ '0';
|
| | | if(m_ch > 9)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-09-18 14:11:09 -05:00 | | | if(m_ch == ('-' ^ '0'))
|
| | | m_last_number = 0;
|
| | |
|
| | | //---
|
| | | m_ch = UCHAR_MAX;
|
| | |
|
| | | //---
|
| | | if(++m_pos >= m_len)
|
| | | return true;
|
2026-08-04 08:01:43 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | // Cae al siguiente
|
| | | }
|
| | |
|
2026-08-26 19:48:01 -05:00 | | | case 2:
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_in_n++; // 3
|
2026-08-04 08:01:43 -05:00 | | | m_sax_frac_int = 0;
|
2026-09-18 14:11:09 -05:00 | | | //---
|
2026-08-04 08:01:43 -05:00 | | | // Cae al siguiente
|
| | | }
|
| | |
|
2026-08-26 19:48:01 -05:00 | | | case 3:
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-09-18 14:11:09 -05:00 | | | //--- en caso sea uchar max (tema de signo entonces volvemos..)
|
| | | if(m_ch == UCHAR_MAX)
|
| | | m_ch = m_raw[m_pos] ^ '0';
|
| | |
|
| | | //---
|
2026-08-04 08:01:43 -05:00 | | | while(true)
|
| | | {
|
2026-09-18 14:11:09 -05:00 | | | if(m_ch > 9)
|
2026-08-04 08:01:43 -05:00 | | | {
|
2026-08-26 19:48:01 -05:00 | | | m_last_number_dbl *= m_last_number ? g_Pow10[m_sax_frac_int] : g_Exp10[m_sax_frac_int];
|
2026-08-04 08:01:43 -05:00 | | | break;
|
| | | }
|
| | |
|
| | | //---
|
2026-09-18 14:11:09 -05:00 | | | m_sax_frac_int = (m_sax_frac_int << 3) + (m_sax_frac_int << 1) + m_ch;
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
| | | m_pos++;
|
| | | if(m_pos >= m_len)
|
2026-09-18 14:11:09 -05:00 | | | {
|
| | | m_ch = UCHAR_MAX; // valido aun sigamos.
|
2026-08-04 08:01:43 -05:00 | | | return true;
|
2026-09-18 14:11:09 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | m_ch = m_raw[m_pos] ^ '0';
|
2026-08-04 08:01:43 -05:00 | | | }
|
| | | break; // Sale esta vez si..
|
| | | }
|
| | |
|
| | | //---
|
| | | default:
|
| | | {
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | m_last_err = TSN_JSON_ERR_INVALID_STATE_IN_PARSE_DOUBLE_E;
|
| | | return false;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
2026-08-26 19:48:01 -05:00 | | | //--- Reinicio base
|
2026-08-04 08:01:43 -05:00 | | | m_in_n = 0;
|
| | |
|
| | | //---
|
2026-08-28 08:28:32 -05:00 | | | TsnBitInterprete bit;
|
2026-08-04 08:01:43 -05:00 | | | bit.double_value = m_last_number_dbl;
|
| | | bit.long_value ^= (m_mask & (1LL << 63));
|
| | | m_in.OnReal(bit.double_value);
|
| | |
|
2026-08-26 19:48:01 -05:00 | | | //---
|
| | | m_last_number = 0; // reiniciamos (pude haber sido 1)
|
| | | m_mask = 0; // tambien a 0
|
2026-08-04 08:01:43 -05:00 | | | //---
|
| | | m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| | | break;
|
| | | }
|
| | |
|
| | | case TSN_JSON_TOK_SAX_DOS_PUNTOS:
|
| | | {
|
| | | //--- Find :
|
| | | while(true)
|
| | | {
|
| | | //---
|
| | | if(m_pos >= m_len)
|
| | | return true; // luego
|
| | |
|
| | | //---
|
| | | if(m_raw[m_pos] == ':')
|
2026-08-04 09:02:31 -05:00 | | | {
|
| | | //---
|
| | | m_pos++; // Luego del
|
| | |
|
| | | //--- Buscamos valor
|
| | | m_next = TSN_JSON_TOK_SAX_COM_KEY;
|
2026-08-04 08:01:43 -05:00 | | | break;
|
2026-08-04 09:02:31 -05:00 | | | }
|
2026-08-04 08:01:43 -05:00 | | |
|
| | | //---
|
| | | m_pos++;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | default:
|
| | | {
|
| | | m_last_err = TSN_JSON_ERR_INVALID_CHAR;
|
| | | JSONPARSERBYLEO_SAX_ON_FINISH
|
| | | return false;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | }
|
| | | #endif // JSONPARSERBYLEO_SRC_JSONSAXIMP_MQH
|
| | | //+------------------------------------------------------------------+
|