2026-08-24 13:05:37 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| RSP.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza"
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
| | | #ifndef CRYPTOBYLEO_RSPPARSER_RSP_MQH
|
| | | #define CRYPTOBYLEO_RSPPARSER_RSP_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "Def.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CRSPParser : public CBaseLanFormat
|
| | | {
|
2026-08-24 22:33:45 -05:00 | | | public:
|
| | | int m_root_values;
|
| | |
|
2026-08-24 13:05:37 -05:00 | | | private:
|
2026-08-24 21:32:18 -05:00 | | | //--- last err
|
2026-08-24 13:05:37 -05:00 | | | ENUM_RSPPARSER_LAST_ERR m_last_err;
|
2026-08-24 21:32:18 -05:00 | | |
|
| | | //--- parseo
|
2026-08-24 13:05:37 -05:00 | | | int m_prev_start_v;
|
| | |
|
| | | // el ultimo valor esta entre [] osea meta
|
| | | bool m_last_meta;
|
| | |
|
| | | // mascara de fin
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
| | | ulong m_last_val_mask;
|
| | | #else
|
| | | uchar m_last_val_char;
|
| | | #endif // RSPDATA_DESACTIVE_SWAR
|
2026-08-24 22:33:45 -05:00 | | |
|
2026-08-24 13:05:37 -05:00 | | | public:
|
2026-08-24 15:46:14 -05:00 | | | CRSPParser(void);
|
2026-08-24 13:05:37 -05:00 | | | ~CRSPParser(void) {}
|
| | |
|
2026-08-24 22:07:20 -05:00 | | | //---
|
| | | __forceinline void CorrectPadding() { CorrectPadingInternal('\n', 8); }
|
| | |
|
2026-08-24 13:05:37 -05:00 | | | //---
|
| | | bool AutoParseByFileExt(const int file_ext_type);
|
| | | int AssingFile(const string& file_name, const bool comon_flag);
|
| | |
|
2026-08-24 21:32:18 -05:00 | | | //--
|
| | | // verifica si una clave esta limpia
|
| | | // En caso no lo este ejeucta la limpiza ahi mismo
|
| | | void VerifyCleanKey(const int cur, const int start, int& len);
|
| | |
|
| | | //---
|
| | | bool KeysEqual(const string &str, const int curr);
|
| | | bool StrEquals(const string &str, const int curr) const;
|
| | |
|
2026-08-24 13:05:37 -05:00 | | | //---
|
2026-08-24 15:46:14 -05:00 | | | __forceinline ENUM_RSPPARSER_LAST_ERR LastErr() const { return m_last_err; }
|
2026-08-24 13:05:37 -05:00 | | |
|
| | | //---
|
| | | bool Parse();
|
| | |
|
| | | //---
|
| | | void ErrorInfo(bool with_avanze = false) const;
|
2026-08-24 22:07:20 -05:00 | | |
|
| | | //---
|
| | | bool SaveCompiled(const string & file_name_out, const bool out_common_flag) const;
|
| | | bool SaveCompiled(const string & file_name_out, const bool out_common_flag, const string & file_name_data, const bool data_common_flag) const;
|
2026-08-24 22:33:45 -05:00 | | |
|
| | |
|
| | | //---
|
| | | void PrintCintaTypes(const int start, const int num) const;
|
| | |
|
| | | //---
|
| | | CRSPNode GetRoot();
|
2026-08-24 13:05:37 -05:00 | | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-24 15:46:14 -05:00 | | | CRSPParser::CRSPParser()
|
| | | {
|
| | | }
|
| | |
|
2026-08-24 22:07:20 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CRSPParser::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 = RSPPARSER_LAST_ERR_INVALID_EXT_FILE;
|
| | | m_pos = 0;
|
| | | return false;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
2026-08-24 21:32:18 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CRSPParser::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;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CRSPParser::VerifyCleanKey(const int cur, const int start, int& len)
|
| | | {
|
| | | const int k = cur + 1; // kpos+1
|
| | | if(((m_cinta[k] >> RSPDATA_BITSTART_ISKEY_CLEAN) & RSPDATA_MASK_META_IS) == 0)
|
| | | {
|
| | | int j = (start + len) - 1;
|
| | | while(j >= start && m_raw[j] < 33)
|
| | | {
|
| | | j--;
|
| | | }
|
| | | len = (j - start) + 1;
|
2026-08-24 22:42:17 -05:00 | | | m_cinta[cur] = long(RSPDATA_TYPE_PLAIN_KEY)
|
| | | | long(len) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | |
|
2026-08-24 21:32:18 -05:00 | | | m_cinta[k] |= RSPDATA_BITSTART_ISKEY_CLEAN_F;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CRSPParser::KeysEqual(const string &str, const int curr)
|
| | | {
|
| | | //---
|
| | | const int start = int(m_cinta[curr] >> TSN_SBL_BIT_STR_START);
|
| | | int len = int((m_cinta[curr] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | | //---
|
| | | VerifyCleanKey(curr, start, 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;
|
| | | }
|
| | |
|
2026-08-24 15:46:14 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // luego de un valor buscar key
|
| | | // el |1 lo hacemos para acitvar el bit 1 cosa uqe aumenta en 1 el valor base del token
|
| | | // En el enum estan definidos de tal forma qeu si le aumentmos 1 para value=key (ahora es key)
|
| | | // y los demas tambien
|
| | | // coment aunenta en uno ahora es comentp
|
| | | // lo que tambien aumenta es cor que pasa a ser corp
|
| | | // e invalid pasa a (fuera) de rango (defualt en NEXTT)
|
| | | // maxima velocidad sin branches
|
| | | #define TSN_RSPPARSER_NEXTV \
|
| | | while(true) \
|
| | | { \
|
| | | if(m_pos >= m_len) \
|
| | | { \
|
| | | return true; \
|
| | | } \
|
| | | const uchar cfasd = m_raw[m_pos]; \
|
| | | if(cfasd < 33) \
|
| | | { \
|
| | | m_pos++; \
|
| | | continue; \
|
| | | } \
|
| | | m_next = g_tsn_rsp_t_to_tokesn[cfasd]|1; \
|
2026-08-24 22:33:45 -05:00 | | | break;\
|
2026-08-24 15:46:14 -05:00 | | | }
|
2026-08-24 13:05:37 -05:00 | | |
|
2026-08-25 08:22:06 -05:00 | | | //---
|
| | | #define RSPDATA_PARSE_FIND_CHAR_UNROLLED_8(CH) \
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break;\
|
| | | m_pos++;\
|
| | | if(m_raw[m_pos] == CH)\
|
| | | break; \
|
| | | m_pos++;
|
| | |
|
2026-08-24 13:05:37 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CRSPParser::Parse(void)
|
| | | {
|
| | | //---
|
2026-08-24 15:46:14 -05:00 | | | m_pos = m_offset;
|
2026-08-24 22:33:45 -05:00 | | | m_cinta_pos = 0;
|
2026-08-24 13:05:37 -05:00 | | | m_last_meta = false;
|
2026-08-24 15:46:14 -05:00 | | | m_last_err = RSPPARSER_LAST_ERR_NOT;
|
2026-08-24 22:33:45 -05:00 | | | m_root_values = 0;
|
2026-09-02 08:18:46 -05:00 | | | // base
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
| | | m_last_val_mask = TSNTABLES_SWAR_MASK_NEW_LINE;
|
| | | #else
|
| | | m_last_val_char = '\n';
|
| | | #endif
|
| | |
|
2026-08-24 13:05:37 -05:00 | | |
|
2026-08-24 15:46:14 -05:00 | | | //--- Initial
|
| | | while(true)
|
| | | {
|
| | | const uchar _c = m_raw[m_pos];
|
| | | if(_c < 33)
|
| | | {
|
| | | m_pos++;
|
| | | continue;
|
| | | }
|
| | | m_next = g_tsn_rsp_t_to_tokesn[_c] | 1;
|
2026-08-24 22:33:45 -05:00 | | | break;
|
2026-08-24 15:46:14 -05:00 | | | }
|
| | |
|
| | | //--- Iter
|
2026-08-24 13:05:37 -05:00 | | | while(true)
|
| | | {
|
| | | switch(m_next)
|
| | | {
|
2026-08-24 15:46:14 -05:00 | | | //---
|
| | | case RSPDATA_TOK_TYPE_VALUE:
|
| | | {
|
| | | // m_prev_start_v = start del key qeu este ultimo nos definio para este valor
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
| | | while(true)
|
| | | {
|
| | | 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 = chunk ^ m_last_val_mask;
|
| | | const ulong has_x = TSNTABLES_SWAR_HAS(x);
|
| | | if(has_x == 0)
|
| | | {
|
| | | m_pos += 8;
|
| | |
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_FIN_V;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | // Si hay \n
|
2026-08-27 14:02:47 -05:00 | | | const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_x);
|
2026-09-02 07:44:15 -05:00 | | |
|
2026-08-27 14:02:47 -05:00 | | | m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag); // Ahora mismo en \n
|
2026-08-24 15:46:14 -05:00 | | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_last_val_mask = TSNTABLES_SWAR_MASK_NEW_LINE;
|
2026-09-02 07:22:44 -05:00 | | |
|
| | |
|
2026-08-24 15:46:14 -05:00 | | | #else // RSPDATA_DESACTIVE_SWAR
|
2026-08-25 08:22:06 -05:00 | | | while(true)
|
2026-08-24 15:46:14 -05:00 | | | {
|
2026-08-25 08:22:06 -05:00 | | | RSPDATA_PARSE_FIND_CHAR_UNROLLED_8(m_last_val_char)
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_FIN_V;
|
| | | return false;
|
| | | }
|
2026-08-24 15:46:14 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | m_last_val_char = '\n';
|
| | | #endif // RSPDATA_DESACTIVE_SWAR
|
| | | // Ahora mismo en \n
|
2026-09-02 07:22:44 -05:00 | | |
|
| | |
|
2026-08-24 15:46:14 -05:00 | | | //---
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_VALUE) | long(m_pos - m_prev_start_v) << TSN_SBL_BIT_STR_LEN
|
| | | | long(m_prev_start_v) << TSN_SBL_BIT_STR_START;
|
| | |
|
| | |
|
| | | //---
|
| | | m_pos++; // Luiego del \n
|
2026-08-24 22:33:45 -05:00 | | | m_root_values++;
|
2026-08-24 15:46:14 -05:00 | | |
|
| | | //---
|
| | | TSN_RSPPARSER_NEXTV
|
| | | break;
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | | //---
|
2026-08-24 13:05:37 -05:00 | | | case RSPDATA_TOK_TYPE_KEY:
|
| | | {
|
| | | // ahora mismo justo en kstart
|
| | | const int start = m_pos++;
|
2026-08-25 08:22:06 -05:00 | | |
|
| | | //---
|
| | | // Por deqfecto desactivo en priomedio als key no superan los 8 chars ahi
|
| | | // asi que no hay mucho beneficio
|
| | | #ifdef RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
2026-08-24 13:05:37 -05:00 | | | while(true)
|
| | | {
|
| | | //Print(CharArrayToString(m_raw, m_pos, 7));
|
| | | 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 = chunk ^ TSNTABLES_SWAR_MASK_IGUAL;
|
| | | const ulong has_x = TSNTABLES_SWAR_HAS(x);
|
| | | if(has_x == 0)
|
| | | {
|
| | | m_pos += 8;
|
| | |
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_EQ;
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | // Si hay =
|
2026-08-27 14:02:47 -05:00 | | | const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_x);
|
| | | m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag);
|
2026-08-24 13:05:37 -05:00 | | | break;
|
| | | }
|
2026-08-25 08:22:06 -05:00 | | | #else // RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
| | | while(true)
|
2026-08-24 13:05:37 -05:00 | | | {
|
2026-08-25 08:22:06 -05:00 | | | RSPDATA_PARSE_FIND_CHAR_UNROLLED_8('=')
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_EQ;
|
| | | return false;
|
| | | }
|
2026-08-24 13:05:37 -05:00 | | | }
|
2026-08-25 08:22:06 -05:00 | | | #endif // RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
2026-09-02 07:44:15 -05:00 | | | // Nota que en un key "in plain no en cor" no peude haber valor = (nada)
|
| | | // siempre hay valor
|
| | | // eso solo sucede en el contexto de cor [] donde se permiten [valor = 20] como [value]
|
2026-08-24 13:05:37 -05:00 | | | // Ahora mismo justo en =
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_KEY)
|
| | | | long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | |
|
| | | // ahora toca meta
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_META) | long(m_last_meta) << TSN_SBL_BIT_START_ENDTYPE;
|
2026-08-24 15:46:14 -05:00 | | |
|
2026-08-24 13:05:37 -05:00 | | | //--- avanzamos
|
| | | m_pos++; // Ahora toca value
|
2026-08-25 08:22:06 -05:00 | | | m_last_meta = false;
|
2026-09-02 07:22:44 -05:00 | | | m_prev_start_v = m_pos;
|
2026-08-24 21:32:18 -05:00 | | |
|
2026-08-24 13:05:37 -05:00 | | | //--- Ahora buscamos el valor
|
| | | while(true)
|
| | | {
|
| | | const uchar f = m_raw[m_pos];
|
| | | if(f < 33)
|
| | | {
|
| | | m_pos++;
|
| | | if(m_pos >= m_len) // o en todo caso fin
|
| | | {
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_VALUE) | long(0) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | | return true;
|
| | | }
|
| | | //---
|
| | | m_prev_start_v++; // nada avanzamos..
|
| | | continue;
|
| | | }
|
| | |
|
| | | //--- Justo aqui nos detenemos. Vemos que sigue comentario o valor
|
2026-08-24 15:46:14 -05:00 | | | // Valor raw tal cual (sin 1 asi que el value es vlaue ya no se pasa a key)
|
2026-08-24 13:05:37 -05:00 | | | m_next = g_tsn_rsp_t_to_tokesn[f];
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | |
|
| | | //--- [ ]
|
| | | case RSPDATA_TOK_TYPE_COR:
|
2026-08-24 15:46:14 -05:00 | | | case RSPDATA_TOK_TYPE_COR_P:
|
2026-08-24 13:05:37 -05:00 | | | {
|
| | | m_pos++; // luego del cor
|
| | |
|
| | | //
|
| | | m_last_meta = true;
|
| | |
|
| | | // saltar ws
|
| | | while(true)
|
| | | {
|
| | | if(m_raw[m_pos] < 33)
|
2026-09-02 07:22:44 -05:00 | | | {
|
| | | m_pos++;
|
2026-08-24 13:05:37 -05:00 | | | continue;
|
2026-09-02 07:22:44 -05:00 | | | }
|
2026-08-24 22:33:45 -05:00 | | | break;
|
2026-08-24 13:05:37 -05:00 | | | }
|
| | |
|
| | | // camibamos las mcaras para que en vez de \n sea ] fin de valor
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
2026-08-24 15:46:14 -05:00 | | | m_last_val_mask = TSNTABLES_SWAR_MASK_COR_END;
|
2026-08-24 13:05:37 -05:00 | | | #else
|
| | | m_last_val_char = ']';
|
| | | #endif
|
| | |
|
| | | // ahora mismo ene l primer char de key
|
2026-09-02 07:22:44 -05:00 | | | m_next = RSPDATA_TOK_TYPE_KEY_COR;
|
2026-08-24 13:05:37 -05:00 | | | break;
|
| | | }
|
| | |
|
| | |
|
| | | //---
|
| | | case RSPDATA_TOK_TYPE_COMMENT:
|
2026-08-24 15:46:14 -05:00 | | | case RSPDATA_TOK_TYPE_COMMENT_P:
|
2026-08-24 13:05:37 -05:00 | | | {
|
| | | m_pos++; // Siguiente..
|
| | |
|
| | | //---
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
| | | while(true)
|
| | | {
|
| | | //Print(CharArrayToString(m_raw, m_pos, 7));
|
| | | 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 = chunk ^ TSNTABLES_SWAR_MASK_NEW_LINE;
|
| | | const ulong has_x = TSNTABLES_SWAR_HAS(x);
|
| | | if(has_x == 0)
|
| | | {
|
| | | m_pos += 8;
|
| | |
|
| | | //--- Check
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_FIN_DE_LINEA;
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | // Si hay \n
|
2026-08-27 14:02:47 -05:00 | | | const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_x);
|
| | | m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag); // Ahora mismo en \n+1 \n[aqui]
|
2026-08-24 13:05:37 -05:00 | | | break;
|
| | | }
|
| | | #else // RSPDATA_DESACTIVE_SWAR
|
2026-08-25 08:22:06 -05:00 | | | while(true)
|
2026-08-24 13:05:37 -05:00 | | | {
|
2026-08-25 08:22:06 -05:00 | | | RSPDATA_PARSE_FIND_CHAR_UNROLLED_8('\n')
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_FIN_DE_LINEA;
|
| | | return false;
|
| | | }
|
2026-08-24 13:05:37 -05:00 | | | }
|
| | | #endif // RSPDATA_DESACTIVE_SWAR
|
| | | //---
|
| | | m_pos++;
|
| | | // Si o si sigue key
|
| | | TSN_RSPPARSER_NEXTV
|
| | | break;
|
| | | }
|
2026-08-24 15:46:14 -05:00 | | |
|
| | | //---
|
| | | case RSPDATA_TOK_INVALID:
|
2026-09-02 07:22:44 -05:00 | | | case RSPDATA_TOK_INVALID_P:
|
2026-08-24 15:46:14 -05:00 | | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_INVALID_TOKEN;
|
| | | return false;
|
| | | }
|
| | |
|
2026-09-02 07:22:44 -05:00 | | |
|
| | | //---
|
| | | case RSPDATA_TOK_TYPE_KEY_COR:
|
| | | {
|
| | | // ahora mismo justo en kstart
|
| | | const int start = m_pos++;
|
| | |
|
| | | //---
|
| | | // Por deqfecto desactivo en priomedio als key no superan los 8 chars ahi
|
| | | // asi que no hay mucho beneficio
|
| | | #ifdef RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
| | | while(true)
|
| | | {
|
| | | //Print(CharArrayToString(m_raw, m_pos, 7));
|
| | | 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 = chunk ^ TSNTABLES_SWAR_MASK_IGUAL;
|
| | | const ulong has_x = TSNTABLES_SWAR_HAS(x);
|
| | | if(has_x == 0)
|
| | | {
|
| | | m_pos += 8;
|
| | |
|
| | | //---
|
| | | if((m_pos + 7) >= m_len)
|
| | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_EQ;
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | // Si hay =
|
| | | const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(has_x);
|
| | | m_pos += TSNTABLES_CTZ_64_GET_BYTE(flag);
|
| | | break;
|
| | | }
|
| | | #else // RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
2026-09-02 07:44:15 -05:00 | | | uchar fs = m_raw[m_pos];
|
2026-09-02 07:22:44 -05:00 | | | while(true)
|
| | | {
|
| | | //---
|
2026-09-02 07:44:15 -05:00 | | | if(fs == '=' || fs == ']')
|
| | | break;
|
| | |
|
| | | //---
|
| | | if(++m_pos >= m_len)
|
2026-09-02 07:22:44 -05:00 | | | {
|
| | | m_last_err = RSPPARSER_LAST_ERR_SE_BUSCABA_EQ;
|
| | | return false;
|
| | | }
|
2026-09-02 07:44:15 -05:00 | | |
|
| | | //---
|
| | | fs = m_raw[m_pos];
|
2026-09-02 07:22:44 -05:00 | | | }
|
| | | #endif // RSPDATA_PARSER_KEY_ACTIVE_SWAR
|
| | | // Ahora mismo justo en =
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_KEY)
|
| | | | long(m_pos - start) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | |
|
| | | // ahora toca meta
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_META) | long(m_last_meta) << TSN_SBL_BIT_START_ENDTYPE;
|
| | |
|
| | | //--- avanzamos
|
2026-09-02 07:44:15 -05:00 | | | m_pos++; // Ahora toca value (luego del ] o =)
|
2026-09-02 07:22:44 -05:00 | | | m_last_meta = false;
|
2026-09-02 07:44:15 -05:00 | | |
|
| | |
|
| | | //--- termino motivo de un cierre [hola] no hay ni = .. asi que valor 0 directo
|
| | | if(fs == ']')
|
| | | {
|
| | | // No habai nada estamos en\n entonces 0
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_VALUE) | long(0) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | |
|
2026-09-02 08:18:46 -05:00 | | | //--- reiniciosmo (esto lo que haria value)
|
| | | #ifndef RSPDATA_DESACTIVE_SWAR
|
| | | m_last_val_mask = TSNTABLES_SWAR_MASK_NEW_LINE;
|
| | | #else
|
| | | m_last_val_char = '\n';
|
| | | #endif
|
| | |
|
| | |
|
2026-09-02 07:44:15 -05:00 | | | //---
|
| | | // Siguiente valor
|
| | | TSN_RSPPARSER_NEXTV
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
2026-09-02 07:22:44 -05:00 | | | m_prev_start_v = m_pos;
|
| | |
|
| | | //--- Ahora buscamos el valor
|
| | | while(true)
|
| | | {
|
| | | const uchar f = m_raw[m_pos];
|
| | | if(f < 33)
|
| | | {
|
| | | m_pos++;
|
| | | if(m_pos >= m_len) // o en todo caso fin
|
| | | {
|
| | | m_cinta[m_cinta_pos++] = long(RSPDATA_TYPE_PLAIN_VALUE) | long(0) << TSN_SBL_BIT_STR_LEN
|
| | | | long(start) << TSN_SBL_BIT_STR_START;
|
| | | return true;
|
| | | }
|
| | | //---
|
| | | m_prev_start_v++; // nada avanzamos..
|
| | | continue;
|
| | | }
|
| | |
|
| | | //--- Justo aqui nos detenemos. Vemos que sigue comentario o valor
|
| | | // Valor raw tal cual (sin 1 asi que el value es vlaue ya no se pasa a key)
|
| | | m_next = g_tsn_rsp_t_to_tokesn[f];
|
| | | break;
|
| | | }
|
| | |
|
| | | //---
|
| | | break;
|
| | | }
|
| | |
|
| | |
|
2026-08-24 13:05:37 -05:00 | | | //---
|
| | | default:
|
2026-08-24 15:46:14 -05:00 | | | m_last_err = RSPPARSER_LAST_ERR_INVALID_NEXTT;
|
2026-08-24 13:05:37 -05:00 | | | return false;
|
| | | }
|
| | | }
|
2026-08-24 15:46:14 -05:00 | | | }
|
2026-08-24 13:05:37 -05:00 | | |
|
2026-08-24 22:07:20 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | int CRSPParser::AssingFile(const string &file_name, const bool comon_flag)
|
| | | {
|
| | | //---
|
2026-09-26 21:47:11 -05:00 | | | if(CPathUtils::FileGetExtension(file_name) == RSPPARSER_TAPECACHE_EXT) // jsontp tape cache
|
2026-08-24 22:07:20 -05:00 | | | {
|
| | | ::ResetLastError();
|
| | | const int fh = FileOpen(file_name, FILE_BIN | FILE_ANSI | (comon_flag ? FILE_COMMON : 0) | FILE_READ);
|
| | | if(fh == INVALID_HANDLE)
|
| | | {
|
| | | return -1;
|
| | | }
|
| | | // Metadata (cinta\yaml)
|
| | | m_cinta_pos = FileReadInteger(fh); // Nota que cuadno se guarda se hace con el tamaño exacto
|
| | | m_cinta_reserve = m_cinta_pos; // Mismo tamaño
|
| | | const int type = FileReadInteger(fh); // Tipo ()
|
| | |
|
| | | //---
|
| | | if(type == TSN_SLF_RAW_EMBEBED)
|
| | | {
|
| | | m_len = FileReadInteger(fh);
|
| | | m_offset = FileReadInteger(fh);
|
| | | FileReadArray(fh, m_cinta, 0, m_cinta_pos); // Total
|
| | | // Yaml embebido (aqui no hace falta hacer nada ya todo esta hecho.. osea lo de encoding etc..)
|
| | | FileReadArray(fh, m_raw, 0, m_len);
|
| | | }
|
| | | else // Dir
|
| | | {
|
| | | const bool common = bool(FileReadInteger(fh, CHAR_VALUE));
|
| | | const int file_name_len = FileReadInteger(fh);
|
| | | if(AssingFile(FileReadString(fh, file_name_len), common) == TSN_SLF_EXT_TYPE_CACHE_FILE)
|
| | | {
|
| | | FileClose(fh);
|
| | | return -1; // fallo
|
| | | }
|
| | | FileReadArray(fh, m_cinta, 0, m_cinta_pos);
|
| | | }
|
| | |
|
| | | //---
|
| | | FileClose(fh);
|
| | | return TSN_SLF_EXT_TYPE_CACHE_FILE;
|
| | | }
|
| | | else // Ninguno de los dos... json normal O jsonasm
|
| | | {
|
| | | const int l = (int)FileLoad(file_name, m_raw, (comon_flag ? FILE_COMMON : 0));
|
| | | if(l == -1)
|
| | | return -1;
|
| | |
|
| | | //---
|
| | | m_len = l;
|
| | |
|
| | | //---
|
| | | NormalizeUft();
|
| | |
|
| | | //---
|
| | | return TSN_SLF_EXT_TYPE_FILE;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | //--- Ambos
|
| | | // 4 bytes: m_cinta_pos
|
| | | // 4 bytes: type
|
| | |
|
| | |
|
| | | //---
|
| | | bool CRSPParser::SaveCompiled(const string & file_name_out, const bool out_common_flag) const
|
| | | {
|
| | | ::ResetLastError();
|
| | | const int fh = FileOpen(file_name_out, FILE_BIN | (out_common_flag ? FILE_COMMON : 0) | FILE_WRITE | FILE_ANSI);
|
| | | if(fh == INVALID_HANDLE)
|
| | | {
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- Comun
|
| | | FileWriteInteger(fh, m_cinta_pos);
|
| | | FileWriteInteger(fh, TSN_SLF_RAW_EMBEBED);
|
| | |
|
| | | //---
|
| | | // 4 bytes: len
|
| | | // 4 bytes: offset
|
| | | // array: cinta
|
| | | // array yaml
|
| | |
|
| | | //---
|
| | | FileWriteInteger(fh, m_len);
|
| | | FileWriteInteger(fh, m_offset);
|
| | | FileWriteArray(fh, m_cinta, 0, m_cinta_pos);
|
| | | FileWriteArray(fh, m_raw, 0, m_len);
|
| | |
|
| | |
|
| | | //---
|
| | | FileClose(fh);
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CRSPParser::SaveCompiled(const string & file_name_out, const bool out_common_flag,
|
| | | const string & file_name_data, const bool data_common_flag) const
|
| | | {
|
| | | //---
|
| | | ::ResetLastError();
|
| | | const int fh = FileOpen(file_name_out, FILE_BIN | (out_common_flag ? FILE_COMMON : 0) | FILE_WRITE | FILE_ANSI);
|
| | | if(fh == INVALID_HANDLE)
|
| | | {
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- Comun
|
| | | FileWriteInteger(fh, m_cinta_pos);
|
| | | FileWriteInteger(fh, TSN_SLF_RAW_FILE);
|
| | |
|
| | | //---
|
| | | // 1 bytes: comon
|
| | | // 4 bytes: len
|
| | | // string: name_file
|
| | | // array: cinta
|
| | |
|
| | |
|
| | | //---
|
| | | FileWriteInteger(fh, data_common_flag, CHAR_VALUE);
|
| | | const int len = StringLen(file_name_data);
|
| | | FileWriteInteger(fh, len);
|
| | | FileWriteString(fh, file_name_data, len);
|
| | | FileWriteArray(fh, m_cinta, 0, m_cinta_pos);
|
| | |
|
| | | //---
|
| | | FileClose(fh);
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
2026-08-24 22:33:45 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CRSPParser::ErrorInfo(bool with_avanze = false) const
|
| | | {
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CRSPParser::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);
|
| | |
|
| | | //---
|
| | | while(p < end)
|
| | | {
|
| | | const ENUM_RSPDATA_TYPE tipo = ENUM_RSPDATA_TYPE(m_cinta[p] & TSN_SBL_BIT_MASK_TYPE);
|
| | | string text = "[" + (string)p + "] " + EnumToString(tipo) + " | ";
|
| | |
|
| | | //---
|
| | | switch(tipo)
|
| | | {
|
| | | case RSPDATA_TYPE_PLAIN_KEY:
|
| | | {
|
| | | const int s = int(m_cinta[p] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_cinta[p] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | |
|
| | | //---
|
| | | text += "start=" + (string)s + " len=" + (string)slen + " key=\"" + CharArrayToString(m_raw, s, slen) + "\"";
|
| | | break;
|
| | | }
|
| | | case RSPDATA_TYPE_PLAIN_VALUE:
|
| | | {
|
| | | const int s = int(m_cinta[p] >> TSN_SBL_BIT_STR_START);
|
| | | const int slen = int((m_cinta[p] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
| | |
|
| | | //---
|
| | | text += "start=" + (string)s + " len=" + (string)slen + " val=\"" + CharArrayToString(m_raw, s, slen) + "\"";
|
| | | break;
|
| | | }
|
| | | case RSPDATA_TYPE_META:
|
| | | {
|
2026-08-31 20:37:20 -05:00 | | | TsnBitInterprete un;
|
2026-08-24 22:33:45 -05:00 | | | un.long_value = m_cinta[p + 1];
|
| | | text += StringFormat("is_cor=%s is_val_cleaned=%s is_key_cleaned=%s",
|
| | | (((m_cinta[p] >> TSN_SBL_BIT_START_ENDTYPE) & RSPDATA_MASK_META_IS) != 0 ? "true" : "false"),
|
| | | (((m_cinta[p] >> RSPDATA_BITSTART_ISVAL_CLEAN) & RSPDATA_MASK_META_IS) != 0 ? "true" : "false"),
|
| | | (((m_cinta[p] >> RSPDATA_BITSTART_ISKEY_CLEAN) & RSPDATA_MASK_META_IS) != 0 ? "true" : "false")
|
| | | );
|
| | | break;
|
| | | }
|
| | | default:
|
| | | break;
|
| | | }
|
| | |
|
| | | Print(text);
|
| | | p++;
|
| | | }
|
| | |
|
| | | }
|
2026-08-24 13:05:37 -05:00 | | |
|
| | | //---
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | #endif // CRYPTOBYLEO_RSPPARSER_RSP_MQH
|