292 строки
8 КиБ
MQL5
292 строки
8 КиБ
MQL5
//+------------------------------------------------------------------+
| |||
//| 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
|