| //+------------------------------------------------------------------+
|
| //| JsonUnescape.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_JSONUNESCAPE_MQH
|
| #define JSONPARSERBYLEO_SRC_JSONUNESCAPE_MQH
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| //--- incluyte al parser y defines.mqh
|
| #include "JsonParser.mqh"
|
| #include <TSN\\BSFL\\Utils.mqh>
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| namespace TSN
|
| {
|
| //+------------------------------------------------------------------+
|
| //| Version que retorna string |
|
| //+------------------------------------------------------------------+
|
| static bool CJsonParser::MakeString(const uchar &in[], int i, int len, string& res)
|
| {
|
| //---
|
| StringInit(res, len, ' ');
|
| int pos = 0;
|
|
|
| //---
|
| len += i;
|
| for(; i < len; i++)
|
| {
|
| //---
|
| const uchar ch = in[i];
|
| if(ch == '\\')
|
| {
|
| const uchar next = g_tsn_table_json_unescape_table[in[++i]];
|
| switch(next)
|
| {
|
| case TSN_TABLE_UNESCAPE_UNICODE:
|
| {
|
| if(i + 4 >= len)
|
| return false;
|
|
|
| //---
|
| DOMBASEULTIS_MAKESTRING_CODE(code, i)
|
|
|
| //--- Vefificamos low\high surrogate
|
| if(code >= 0xD800 && code <= 0xDBFF)
|
| {
|
| if(i + 6 < len && in[i + 1] == '\\' && in[i + 2] == 'u')
|
| {
|
| int j = i + 2;
|
| DOMBASEULTIS_MAKESTRING_CODE(low, j)
|
| //---
|
| if(low >= 0xDC00 && low <= 0xDFFF)
|
| {
|
| res.SetChar(pos++, code);
|
| res.SetChar(pos++, low);
|
| i = j;
|
| break;
|
| }
|
| }
|
| //---
|
| // if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| // return def;
|
| res.SetChar(pos++, 0xFFFD);
|
| }
|
| else
|
| if(code >= 0xDC00 && code <= 0xDFFF)
|
| {
|
| //if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| //return def;
|
| res.SetChar(pos++, 0xFFFD);
|
| }
|
| else
|
| res.SetChar(pos++, code);
|
| break;
|
| }
|
| case TSN_TABLE_UNESCAPE_INVALID:
|
| return false;
|
| default:
|
| res.SetChar(pos++, next);
|
| break;
|
| }
|
| continue;
|
| }
|
| //---
|
| res.SetChar(pos++, ch);
|
| }
|
| //---
|
| res.Truncate(pos);
|
| return true;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| static int CJsonParser::MakeUArray(const uchar &in[], int i, int len, uchar &res[], int pos = 0)
|
| {
|
| //---
|
| ArrayResize(res, len);
|
| //---
|
| len += i;
|
| for(; i < len; i++)
|
| {
|
| //---
|
| const uchar ch = in[i];
|
| if(ch == '\\')
|
| {
|
| const uchar next = g_tsn_table_json_unescape_table[in[++i]];
|
| switch(next)
|
| {
|
| case TSN_TABLE_UNESCAPE_UNICODE:
|
| {
|
| if(i + 4 >= len)
|
| return -1; // error
|
|
|
| //---
|
| DOMBASEULTIS_MAKESTRING_CODE(code, i)
|
|
|
| //---
|
| if(code < 0x80)
|
| {
|
| res[pos++] = uchar(code);
|
| continue;
|
| }
|
| else
|
| if(code < 0x800)
|
| {
|
| res[pos++] = uchar(0xC0 | (code >> 6));
|
| res[pos++] = uchar(0x80 | (code & 0x3F));
|
| continue;
|
| }
|
|
|
| //---
|
| uint cp = code;
|
| if(code >= 0xD800 && code <= 0xDBFF) // Esta en rango buscamos otro mas.
|
| {
|
| if(i + 6 < len && in[i + 1] == '\\' && in[i + 2] == 'u')
|
| {
|
| int j = i + 2;
|
| DOMBASEULTIS_MAKESTRING_CODE(low, j)
|
| if(low >= 0xDC00 && low <= 0xDFFF)
|
| {
|
| cp = 0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
|
| i = j;
|
|
|
| //--- emoji
|
| res[pos++] = uchar(0xF0 | (cp >> 18));
|
| res[pos++] = uchar(0x80 | ((cp >> 12) & 0x3F));
|
| res[pos++] = uchar(0x80 | ((cp >> 6) & 0x3F));
|
| res[pos++] = uchar(0x80 | (cp & 0x3F));
|
| continue;
|
| }
|
| }
|
|
|
| //---
|
| // if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| // return -1;
|
| code = 0xFFFD; // huerfano, no hay low surrogate despues
|
| }
|
| else
|
| if(code >= 0xDC00 && code <= 0xDFFF)
|
| {
|
| // if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| // return -1;
|
| code = 0xFFFD;
|
| }
|
|
|
| //---
|
| res[pos++] = uchar(0xE0 | (code >> 12));
|
| res[pos++] = uchar(0x80 | ((code >> 6) & 0x3F));
|
| res[pos++] = uchar(0x80 | (code & 0x3F));
|
| continue;
|
| }
|
| case TSN_TABLE_UNESCAPE_INVALID:
|
| return -1; // error
|
| default:
|
| res[pos++] = next;
|
| continue;
|
| }
|
| }
|
| //---
|
| res[pos++] = ch;
|
| }
|
|
|
| //---
|
| return ArrayResize(res, pos);
|
| }
|
|
|
|
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| static bool CJsonParser::EscapePointer(const string &in, int &i, int len, ulong &hash)
|
| {
|
| //---
|
| hash = 14695981039346656037ULL;
|
| for(; i < len; i++) // nota aqui el " se nos garantiza pero igual en uncidoe hay que vertiicar el len
|
| {
|
| //---
|
| const ushort ch = in[i];
|
| if(ch == '\\')
|
| {
|
| const uchar next = g_tsn_table_json_unescape_table[in[++i]];
|
| switch(next)
|
| {
|
| case TSN_TABLE_UNESCAPE_UNICODE:
|
| {
|
| if(i + 4 >= len)
|
| return false;
|
|
|
| //---
|
| DOMBASEULTIS_MAKESTRING_CODE(code, i)
|
|
|
| //--- Vefificamos low\high surrogate
|
| if(code >= 0xD800 && code <= 0xDBFF)
|
| {
|
| if(i + 6 < len && in[i + 1] == '\\' && in[i + 2] == 'u')
|
| {
|
| int j = i + 2;
|
| DOMBASEULTIS_MAKESTRING_CODE(low, j)
|
| //---
|
| if(low >= 0xDC00 && low <= 0xDFFF)
|
| {
|
| DOMBASEULTIS_MKH_ITER(code)
|
| DOMBASEULTIS_MKH_ITER(low)
|
| i = j;
|
| break;
|
| }
|
| }
|
| //---
|
| // if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| // return def;
|
| DOMBASEULTIS_MKH_ITER(0xFFFD)
|
| }
|
| else
|
| if(code >= 0xDC00 && code <= 0xDFFF)
|
| {
|
| //if(sizeof(TStrict) == JSONUNESCAPE_STRICT)
|
| //return def;
|
| DOMBASEULTIS_MKH_ITER(0xFFFD)
|
| }
|
| else
|
| {
|
| DOMBASEULTIS_MKH_ITER(code)
|
| }
|
| break;
|
| }
|
| case TSN_TABLE_UNESCAPE_INVALID:
|
| return false;
|
| default:
|
| DOMBASEULTIS_MKH_ITER(next)
|
| break;
|
| }
|
| continue;
|
| }
|
| if(ch == '/')
|
| return true;
|
| if(ch == '~')
|
| {
|
| const ushort n = in[++i];
|
| if(n == '1')
|
| {
|
| DOMBASEULTIS_MKH_ITER('/')
|
| continue;
|
| }
|
| else
|
| if(n == '0')
|
| {
|
| DOMBASEULTIS_MKH_ITER('~')
|
| continue;
|
| }
|
| return false; // escape invalido
|
| }
|
|
|
| //---
|
| DOMBASEULTIS_MKH_ITER(ch)
|
| }
|
| return true;
|
| }
|
|
|
| //--- end namespace
|
| }
|
| #endif // JSONPARSERBYLEO_SRC_JSONUNESCAPE_MQH
|