| //+------------------------------------------------------------------+
|
| //| 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)
|
| /* Notas de mi parte
|
| Siempre cuando vuevea a llamar aseungramtne de agregar datos amenos un solo dato es lo minimo..
|
| */
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| class CJsonParserStream : public CJsonParser
|
| {
|
| private:
|
| ITsnJsonParserStream* m_in;
|
| bool m_del_caller;
|
|
|
| //---
|
| 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;
|
| ushort m_sax_frac_digits;
|
| uchar m_ch;
|
|
|
| public:
|
| CJsonParserStream(void) : m_del_caller(false) {}
|
| ~CJsonParserStream(void);
|
|
|
| //---
|
| __forceinline int CurrentStack() const { return m_stak_curr + 1; }
|
| __forceinline int CurrentStackState() const { return m_stak_curr_state; }
|
| void KillParse();
|
|
|
| //---
|
| void SetCaller(ITsnJsonParserStream* caller, bool del);
|
| void CheckLimpieza();
|
|
|
| //---
|
| bool ParseSreamSax();
|
| };
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CJsonParserStream::~CJsonParserStream(void)
|
| {
|
| if(m_del_caller && CheckPointer(m_in) == POINTER_DYNAMIC)
|
| delete m_in;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| // 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
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| 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..
|
| }
|
|
|
|
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| bool CJsonParserStream::ParseSreamSax(void)
|
| {
|
| //--- Inicial
|
| if(m_next == TSN_JSON_TOK_INVALID)
|
| {
|
| // general
|
| m_stak_curr = -1;
|
| m_last_err = TSN_JSON_NOT_ERR;
|
| m_pos = m_offset;
|
| // numeros
|
| m_last_number = 0;
|
| m_mask = 0;
|
| //dbl
|
| m_in_n = 0;
|
| // extra
|
| m_stak_pos[JSONPARSERBYLEO_SAX_STR_START] = -1; // string y keys
|
|
|
| //---
|
| m_in.OnStartDocument();
|
|
|
| //--- 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:
|
| {
|
| //---
|
| // m_last_number=0 ya viene a 0
|
| m_mask = -1; // solo cambiamos la mascara
|
| m_next = TSN_JSON_TOK_NUMBER;
|
|
|
| //---
|
| if(++m_pos >= m_len) // Ahora en numero de lo contraio a la siguiente..
|
| return true;
|
| break;
|
| }
|
|
|
| //---
|
| case TSN_JSON_TOK_NUMBER:
|
| {
|
| //---
|
| m_ch = m_raw[m_pos] ^ '0';
|
|
|
| //--- bucle principal
|
| while(true)
|
| {
|
| m_last_number = (m_last_number << 3) + (m_last_number << 1) + m_ch;
|
| m_pos++;
|
| if(m_pos >= m_len)
|
| return true;
|
| m_ch = m_raw[m_pos] ^ '0';
|
| if(m_ch < 10)
|
| continue;
|
| else
|
| if(m_ch == 30 || (m_ch | 0x20) == 117)
|
| {
|
| m_prev_c = m_ch;
|
| m_last_number_dbl = double(m_last_number);
|
| m_next = TSN_JSON_TOK_SAX_DBL;
|
| // dbl ya reincia ..
|
| break;
|
| }
|
| else
|
| {
|
| m_in.OnInteger((m_last_number ^ m_mask) - m_mask);
|
| m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
| // reiniciamos
|
| m_last_number = 0;
|
| m_mask = 0;
|
| break;
|
| }
|
| }
|
|
|
| //--- 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
|
| while(true)
|
| {
|
| //---
|
| if(m_pos >= m_len)
|
| {
|
| return true;
|
| }
|
|
|
| //---
|
| 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
|
| m_in.OnBool(true);
|
| 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
|
| m_in.OnBool(false);
|
| 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++;
|
| m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_OBJ;
|
| m_stak_curr_state = TSN_JSON_CTX_IN_OBJ;
|
|
|
| //---
|
| m_pos++;
|
|
|
| //---
|
| m_next = TSN_JSON_TOK_SAX_LLAVE_INI;
|
|
|
| //---
|
| break;
|
| }
|
| case TSN_JSON_TOK_COR_INI:
|
| {
|
| //_--
|
| m_in.OnStartArr();
|
|
|
| //---
|
| m_stak_curr++;
|
| m_stak_state[m_stak_curr] = TSN_JSON_CTX_IN_ARR;
|
| m_stak_curr_state = TSN_JSON_CTX_IN_ARR;
|
|
|
| //---
|
| m_pos++;
|
|
|
| //---
|
| m_next = TSN_JSON_TOK_SAX_COR_INI;
|
|
|
| //---
|
| break;
|
| }
|
| case TSN_JSON_TOK_LLAVE_END:
|
| {
|
| //---
|
| m_stak_curr--;
|
|
|
| //---
|
| m_in.OnEndObJ();
|
|
|
| //---
|
| if(m_stak_curr < 0) // termino
|
| {
|
| m_in.OnEndDocument();
|
| JSONPARSERBYLEO_SAX_ON_FINISH
|
| return true;
|
| }
|
|
|
| //---
|
| m_stak_curr_state = m_stak_state[m_stak_curr];
|
|
|
| //---
|
| m_pos++;
|
|
|
| //---
|
| m_next = TSN_JSON_TOK_SAX_NO_NEXT_KEY;
|
|
|
| //---
|
| break;
|
| }
|
| case TSN_JSON_TOK_COR_END:
|
| {
|
| //---
|
| m_stak_curr--;
|
|
|
| //---
|
| m_in.OnEndArr();
|
|
|
| //---
|
| if(m_stak_curr < 0) // termino
|
| {
|
| m_in.OnEndDocument();
|
| JSONPARSERBYLEO_SAX_ON_FINISH
|
| return true;
|
| }
|
|
|
| //---
|
| m_stak_curr_state = m_stak_state[m_stak_curr];
|
|
|
| //---
|
| 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
|
| while(true)
|
| {
|
| //---
|
| if(m_pos >= m_len)
|
| {
|
| return true;
|
| }
|
|
|
| //---
|
| 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
|
| m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_VAL;
|
| 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++;
|
| }
|
|
|
| //---
|
| break;
|
| }
|
|
|
| //---
|
| 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
|
| m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_AFTER_COR_INI;
|
| 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)
|
| {
|
| m_last_err = TSN_JSON_ERR_MALFORDMED_JSON_FIND_VAL;
|
| 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)
|
| {
|
| if(m_in_n == 0) // etapa inicial 0
|
| {
|
| m_in_n++; // 1
|
| m_pos++;
|
| m_sax_frac_int = 0;
|
| m_sax_frac_digits = 0;
|
| }
|
|
|
| //---
|
| while(true)
|
| {
|
| //---
|
| if(m_pos >= m_len)
|
| return true;
|
|
|
| //---
|
| m_ch = m_raw[m_pos] ^ '0';
|
| if(m_ch > 9)
|
| {
|
| m_in_n = 0; // Vuelta en 0 (ahora para procesar lod giitos)
|
| 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;
|
| }
|
|
|
| //---
|
| m_sax_frac_int = (m_sax_frac_int << 3) + (m_sax_frac_int << 1) + m_ch;
|
| m_sax_frac_digits++;
|
| m_pos++;
|
| }
|
|
|
| //---
|
| // Pasamos con un char extra..
|
| }
|
|
|
| //--- Ahora procesamos E
|
| if(m_prev_c == 15 || (m_ch | 0x20) == 117) // e or E
|
| {
|
| //---
|
| switch(m_in_n)
|
| {
|
| case 0:
|
| {
|
| m_in_n++; // 1
|
| m_prev_c = 15;
|
|
|
| //---
|
| if(++m_pos >= m_len)
|
| return true; // Salimos
|
| // Cae al siguiente
|
| }
|
|
|
| case 1:
|
| {
|
| m_in_n++; // 2
|
| m_last_number = 1; // bool exp_sign = true;
|
|
|
| //---
|
| m_ch = m_raw[m_pos] ^ '0';
|
| if(m_ch > 9)
|
| {
|
| if(m_ch == ('-' ^ '0'))
|
| m_last_number = 0;
|
|
|
| //---
|
| m_ch = UCHAR_MAX;
|
|
|
| //---
|
| if(++m_pos >= m_len)
|
| return true;
|
| }
|
|
|
| //---
|
| // Cae al siguiente
|
| }
|
|
|
| case 2:
|
| {
|
| m_in_n++; // 3
|
| m_sax_frac_int = 0;
|
| //---
|
| // Cae al siguiente
|
| }
|
|
|
| case 3:
|
| {
|
| //--- en caso sea uchar max (tema de signo entonces volvemos..)
|
| if(m_ch == UCHAR_MAX)
|
| m_ch = m_raw[m_pos] ^ '0';
|
|
|
| //---
|
| while(true)
|
| {
|
| if(m_ch > 9)
|
| {
|
| m_last_number_dbl *= m_last_number ? g_Pow10[m_sax_frac_int] : g_Exp10[m_sax_frac_int];
|
| break;
|
| }
|
|
|
| //---
|
| m_sax_frac_int = (m_sax_frac_int << 3) + (m_sax_frac_int << 1) + m_ch;
|
|
|
| //---
|
| m_pos++;
|
| if(m_pos >= m_len)
|
| {
|
| m_ch = UCHAR_MAX; // valido aun sigamos.
|
| return true;
|
| }
|
|
|
| //---
|
| m_ch = m_raw[m_pos] ^ '0';
|
| }
|
| break; // Sale esta vez si..
|
| }
|
|
|
| //---
|
| default:
|
| {
|
| JSONPARSERBYLEO_SAX_ON_FINISH
|
| m_last_err = TSN_JSON_ERR_INVALID_STATE_IN_PARSE_DOUBLE_E;
|
| return false;
|
| }
|
| }
|
| }
|
|
|
| //--- Reinicio base
|
| m_in_n = 0;
|
|
|
| //---
|
| TsnBitInterprete bit;
|
| bit.double_value = m_last_number_dbl;
|
| bit.long_value ^= (m_mask & (1LL << 63));
|
| m_in.OnReal(bit.double_value);
|
|
|
| //---
|
| m_last_number = 0; // reiniciamos (pude haber sido 1)
|
| m_mask = 0; // tambien a 0
|
| //---
|
| 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] == ':')
|
| {
|
| //---
|
| m_pos++; // Luego del
|
|
|
| //--- Buscamos valor
|
| m_next = TSN_JSON_TOK_SAX_COM_KEY;
|
| break;
|
| }
|
|
|
| //---
|
| 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
|
| //+------------------------------------------------------------------+
|