868 lines
43 KiB
MQL5
868 lines
43 KiB
MQL5
//+------------------------------------------------------------------ß
|
|
//| JAson |
|
|
//| This software is licensed under the MIT https://goo.gl/eyJgHe |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright © 2006-2017"
|
|
#property version "1.08"
|
|
#property strict
|
|
#define DEBUG_PRINT false
|
|
//------------------------------------------------------------------ enum enJAType
|
|
enum enJAType { jtUNDEF,jtNULL,jtBOOL,jtINT,jtDBL,jtSTR,jtARRAY,jtOBJ };
|
|
//------------------------------------------------------------------ class CJAVal
|
|
class CJAVal
|
|
{
|
|
public:
|
|
virtual void Clear()
|
|
{
|
|
m_parent=NULL;
|
|
m_key="";
|
|
m_type=jtUNDEF;
|
|
m_bv=false;
|
|
m_iv=0;
|
|
m_dv=0;
|
|
m_sv="";
|
|
ArrayResize(m_e,0);
|
|
}
|
|
virtual bool Copy(const CJAVal &a)
|
|
{
|
|
m_key=a.m_key;
|
|
CopyData(a);
|
|
return true;
|
|
}
|
|
virtual void CopyData(const CJAVal &a)
|
|
{
|
|
m_type=a.m_type;
|
|
m_bv=a.m_bv;
|
|
m_iv=a.m_iv;
|
|
m_dv=a.m_dv;
|
|
m_sv=a.m_sv;
|
|
CopyArr(a);
|
|
}
|
|
virtual void CopyArr(const CJAVal &a)
|
|
{
|
|
int n=ArrayResize(m_e,ArraySize(a.m_e));
|
|
for(int i=0; i<n; i++)
|
|
{
|
|
m_e[i]=a.m_e[i];
|
|
m_e[i].m_parent=GetPointer(this);
|
|
}
|
|
}
|
|
|
|
public:
|
|
CJAVal m_e[];
|
|
string m_key;
|
|
string m_lkey;
|
|
CJAVal *m_parent;
|
|
enJAType m_type;
|
|
bool m_bv;
|
|
long m_iv;
|
|
double m_dv;
|
|
string m_sv;
|
|
static int code_page;
|
|
|
|
public:
|
|
CJAVal()
|
|
{
|
|
Clear();
|
|
}
|
|
CJAVal(CJAVal *aparent,enJAType atype)
|
|
{
|
|
Clear();
|
|
m_type=atype;
|
|
m_parent=aparent;
|
|
}
|
|
CJAVal(enJAType t,string a)
|
|
{
|
|
Clear();
|
|
FromStr(t,a);
|
|
}
|
|
CJAVal(const int a)
|
|
{
|
|
Clear();
|
|
m_type=jtINT;
|
|
m_iv=a;
|
|
m_dv=(double)m_iv;
|
|
m_sv=IntegerToString(m_iv);
|
|
m_bv=m_iv!=0;
|
|
}
|
|
CJAVal(const long a)
|
|
{
|
|
Clear();
|
|
m_type=jtINT;
|
|
m_iv=a;
|
|
m_dv=(double)m_iv;
|
|
m_sv=IntegerToString(m_iv);
|
|
m_bv=m_iv!=0;
|
|
}
|
|
CJAVal(const double a)
|
|
{
|
|
Clear();
|
|
m_type=jtDBL;
|
|
m_dv=a;
|
|
m_iv=(long)m_dv;
|
|
m_sv=DoubleToString(m_dv);
|
|
m_bv=m_iv!=0;
|
|
}
|
|
CJAVal(const bool a)
|
|
{
|
|
Clear();
|
|
m_type=jtBOOL;
|
|
m_bv=a;
|
|
m_iv=m_bv;
|
|
m_dv=m_bv;
|
|
m_sv=IntegerToString(m_iv);
|
|
}
|
|
CJAVal(const CJAVal &a)
|
|
{
|
|
Clear();
|
|
Copy(a);
|
|
}
|
|
~CJAVal()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
public:
|
|
virtual bool IsNumeric()
|
|
{
|
|
return m_type==jtDBL || m_type==jtINT;
|
|
}
|
|
virtual CJAVal *FindKey(string akey)
|
|
{
|
|
for(int i=ArraySize(m_e)-1; i>=0; --i) if(m_e[i].m_key==akey) return GetPointer(m_e[i]);
|
|
return NULL;
|
|
}
|
|
virtual CJAVal *HasKey(string akey,enJAType atype=jtUNDEF);
|
|
virtual CJAVal *operator[](string akey);
|
|
virtual CJAVal *operator[](int i);
|
|
void operator=(const CJAVal &a)
|
|
{
|
|
Copy(a);
|
|
}
|
|
void operator=(const int a)
|
|
{
|
|
m_type=jtINT;
|
|
m_iv=a;
|
|
m_dv=(double)m_iv;
|
|
m_bv=m_iv!=0;
|
|
}
|
|
void operator=(const long a)
|
|
{
|
|
m_type=jtINT;
|
|
m_iv=a;
|
|
m_dv=(double)m_iv;
|
|
m_bv=m_iv!=0;
|
|
}
|
|
void operator=(const double a)
|
|
{
|
|
m_type=jtDBL;
|
|
m_dv=a;
|
|
m_iv=(long)m_dv;
|
|
m_bv=m_iv!=0;
|
|
}
|
|
void operator=(const bool a)
|
|
{
|
|
m_type=jtBOOL;
|
|
m_bv=a;
|
|
m_iv=(long)m_bv;
|
|
m_dv=(double)m_bv;
|
|
}
|
|
void operator=(string a)
|
|
{
|
|
m_type=(a!=NULL)?jtSTR:jtNULL;
|
|
m_sv=a;
|
|
m_iv=StringToInteger(m_sv);
|
|
m_dv=StringToDouble(m_sv);
|
|
m_bv=a!=NULL;
|
|
}
|
|
|
|
bool operator==(const int a)
|
|
{
|
|
return m_iv==a;
|
|
}
|
|
bool operator==(const long a)
|
|
{
|
|
return m_iv==a;
|
|
}
|
|
bool operator==(const double a)
|
|
{
|
|
return m_dv==a;
|
|
}
|
|
bool operator==(const bool a)
|
|
{
|
|
return m_bv==a;
|
|
}
|
|
bool operator==(string a)
|
|
{
|
|
return m_sv==a;
|
|
}
|
|
|
|
bool operator!=(const int a)
|
|
{
|
|
return m_iv!=a;
|
|
}
|
|
bool operator!=(const long a)
|
|
{
|
|
return m_iv!=a;
|
|
}
|
|
bool operator!=(const double a)
|
|
{
|
|
return m_dv!=a;
|
|
}
|
|
bool operator!=(const bool a)
|
|
{
|
|
return m_bv!=a;
|
|
}
|
|
bool operator!=(string a)
|
|
{
|
|
return m_sv!=a;
|
|
}
|
|
|
|
long ToInt() const
|
|
{
|
|
return m_iv;
|
|
}
|
|
double ToDbl() const
|
|
{
|
|
return m_dv;
|
|
}
|
|
bool ToBool() const
|
|
{
|
|
return m_bv;
|
|
}
|
|
string ToStr()
|
|
{
|
|
return m_sv;
|
|
}
|
|
|
|
virtual void FromStr(enJAType t,string a)
|
|
{
|
|
m_type=t;
|
|
switch(m_type)
|
|
{
|
|
case jtBOOL:
|
|
m_bv=(StringToInteger(a)!=0);
|
|
m_iv=(long)m_bv;
|
|
m_dv=(double)m_bv;
|
|
m_sv=a;
|
|
break;
|
|
case jtINT:
|
|
m_iv=StringToInteger(a);
|
|
m_dv=(double)m_iv;
|
|
m_sv=a;
|
|
m_bv=m_iv!=0;
|
|
break;
|
|
case jtDBL:
|
|
m_dv=StringToDouble(a);
|
|
m_iv=(long)m_dv;
|
|
m_sv=a;
|
|
m_bv=m_iv!=0;
|
|
break;
|
|
case jtSTR:
|
|
m_sv=Unescape(a);
|
|
m_type=(m_sv!=NULL)?jtSTR:jtNULL;
|
|
m_iv=StringToInteger(m_sv);
|
|
m_dv=StringToDouble(m_sv);
|
|
m_bv=m_sv!=NULL;
|
|
break;
|
|
}
|
|
}
|
|
virtual string GetStr(char &js[],int i,int slen)
|
|
{
|
|
#ifdef __MQL4__
|
|
if(slen<=0) return "";
|
|
#endif
|
|
char cc[];
|
|
ArrayCopy(cc,js,0,i,slen);
|
|
return CharArrayToString(cc, 0, WHOLE_ARRAY, CJAVal::code_page);
|
|
}
|
|
|
|
virtual void Set(const CJAVal &a)
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtOBJ;
|
|
CopyData(a);
|
|
}
|
|
virtual void Set(const CJAVal &list[]);
|
|
virtual CJAVal *Add(const CJAVal &item)
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtARRAY; /*ASSERT(m_type==jtOBJ || m_type==jtARRAY);*/ return AddBase(item);
|
|
}
|
|
virtual CJAVal *Add(const int a)
|
|
{
|
|
CJAVal item(a);
|
|
return Add(item);
|
|
}
|
|
virtual CJAVal *Add(const long a)
|
|
{
|
|
CJAVal item(a);
|
|
return Add(item);
|
|
}
|
|
virtual CJAVal *Add(const double a)
|
|
{
|
|
CJAVal item(a);
|
|
return Add(item);
|
|
}
|
|
virtual CJAVal *Add(const bool a)
|
|
{
|
|
CJAVal item(a);
|
|
return Add(item);
|
|
}
|
|
virtual CJAVal *Add(string a)
|
|
{
|
|
CJAVal item(jtSTR,a);
|
|
return Add(item);
|
|
}
|
|
virtual CJAVal *AddBase(const CJAVal &item)
|
|
{
|
|
int c=ArraySize(m_e);
|
|
ArrayResize(m_e,c+1);
|
|
m_e[c]=item;
|
|
m_e[c].m_parent=GetPointer(this);
|
|
return GetPointer(m_e[c]);
|
|
}
|
|
virtual CJAVal *New()
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtARRAY; /*ASSERT(m_type==jtOBJ || m_type==jtARRAY);*/ return NewBase();
|
|
}
|
|
virtual CJAVal *NewBase()
|
|
{
|
|
int c=ArraySize(m_e);
|
|
ArrayResize(m_e,c+1);
|
|
return GetPointer(m_e[c]);
|
|
}
|
|
|
|
virtual string Escape(string a);
|
|
virtual string Unescape(string a);
|
|
public:
|
|
virtual void Serialize(string &js,bool bf=false,bool bcoma=false);
|
|
virtual string Serialize()
|
|
{
|
|
string js;
|
|
Serialize(js);
|
|
return js;
|
|
}
|
|
virtual bool Deserialize(char &js[],int slen,int &i);
|
|
virtual bool ExtrStr(char &js[],int slen,int &i);
|
|
virtual bool Deserialize(string js,int acp=CP_ACP)
|
|
{
|
|
int i=0;
|
|
Clear();
|
|
CJAVal::code_page=acp;
|
|
char arr[];
|
|
int slen=StringToCharArray(js,arr,0,WHOLE_ARRAY,CJAVal::code_page);
|
|
return Deserialize(arr,slen,i);
|
|
}
|
|
virtual bool Deserialize(char &js[],int acp=CP_ACP)
|
|
{
|
|
int i=0;
|
|
Clear();
|
|
CJAVal::code_page=acp;
|
|
return Deserialize(js,ArraySize(js),i);
|
|
}
|
|
};
|
|
|
|
int CJAVal::code_page=CP_ACP;
|
|
|
|
//------------------------------------------------------------------ HasKey
|
|
CJAVal *CJAVal::HasKey(string akey,enJAType atype/*=jtUNDEF*/)
|
|
{
|
|
for(int i=0; i<ArraySize(m_e); i++) if(m_e[i].m_key==akey)
|
|
{
|
|
if(atype==jtUNDEF || atype==m_e[i].m_type) return GetPointer(m_e[i]);
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
//------------------------------------------------------------------ operator[]
|
|
CJAVal *CJAVal::operator[](string akey)
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtOBJ;
|
|
CJAVal *v=FindKey(akey);
|
|
if(v) return v;
|
|
CJAVal b(GetPointer(this),jtUNDEF);
|
|
b.m_key=akey;
|
|
v=Add(b);
|
|
return v;
|
|
}
|
|
//------------------------------------------------------------------ operator[]
|
|
CJAVal *CJAVal::operator[](int i)
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtARRAY;
|
|
while(i>=ArraySize(m_e))
|
|
{
|
|
CJAVal b(GetPointer(this),jtUNDEF);
|
|
if(CheckPointer(Add(b))==POINTER_INVALID) return NULL;
|
|
}
|
|
return GetPointer(m_e[i]);
|
|
}
|
|
//------------------------------------------------------------------ Set
|
|
void CJAVal::Set(const CJAVal &list[])
|
|
{
|
|
if(m_type==jtUNDEF) m_type=jtARRAY;
|
|
int n=ArrayResize(m_e,ArraySize(list));
|
|
for(int i=0; i<n; ++i)
|
|
{
|
|
m_e[i]=list[i];
|
|
m_e[i].m_parent=GetPointer(this);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------ Serialize
|
|
void CJAVal::Serialize(string &js,bool bkey/*=false*/,bool coma/*=false*/)
|
|
{
|
|
if(m_type==jtUNDEF) return;
|
|
if(coma) js+=",";
|
|
if(bkey) js+=StringFormat("\"%s\":", m_key);
|
|
int _n=ArraySize(m_e);
|
|
switch(m_type)
|
|
{
|
|
case jtNULL:
|
|
js+="null";
|
|
break;
|
|
case jtBOOL:
|
|
js+=(m_bv?"true":"false");
|
|
break;
|
|
case jtINT:
|
|
js+=IntegerToString(m_iv);
|
|
break;
|
|
case jtDBL:
|
|
js+=DoubleToString(m_dv);
|
|
break;
|
|
case jtSTR:
|
|
{
|
|
string ss=Escape(m_sv);
|
|
if(StringLen(ss)>0) js+=StringFormat("\"%s\"",ss);
|
|
else js+="null";
|
|
}
|
|
break;
|
|
case jtARRAY:
|
|
js+="[";
|
|
for(int i=0; i<_n; i++) m_e[i].Serialize(js,false,i>0);
|
|
js+="]";
|
|
break;
|
|
case jtOBJ:
|
|
js+="{";
|
|
for(int i=0; i<_n; i++) m_e[i].Serialize(js,true,i>0);
|
|
js+="}";
|
|
break;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------ Deserialize
|
|
bool CJAVal::Deserialize(char &js[],int slen,int &i)
|
|
{
|
|
string num="0123456789+-.eE";
|
|
int i0=i;
|
|
for(; i<slen; i++)
|
|
{
|
|
char c=js[i];
|
|
if(c==0) break;
|
|
switch(c)
|
|
{
|
|
case '\t':
|
|
case '\r':
|
|
case '\n':
|
|
case ' ': // skip
|
|
i0=i+1;
|
|
break;
|
|
|
|
case '[': // the beginning of the object. create an object and take it from js
|
|
{
|
|
i0=i+1;
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // if the value already has a type, then this is an error
|
|
return false;
|
|
}
|
|
m_type=jtARRAY; // set the type
|
|
i++;
|
|
CJAVal val(GetPointer(this),jtUNDEF);
|
|
while(val.Deserialize(js,slen,i))
|
|
{
|
|
if(val.m_type!=jtUNDEF) Add(val);
|
|
if(val.m_type==jtINT || val.m_type==jtDBL || val.m_type==jtARRAY) i++;
|
|
val.Clear();
|
|
val.m_parent=GetPointer(this);
|
|
if(js[i]==']') break;
|
|
i++;
|
|
if(i>=slen)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
}
|
|
return js[i]==']' || js[i]==0;
|
|
}
|
|
break;
|
|
case ']':
|
|
if(!m_parent) return false;
|
|
return m_parent.m_type==jtARRAY; // end of array, current value must be an array
|
|
|
|
case ':':
|
|
{
|
|
if(m_lkey=="")
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
CJAVal val(GetPointer(this),jtUNDEF);
|
|
CJAVal *oc=Add(val); // object type is not defined yet
|
|
oc.m_key=m_lkey;
|
|
m_lkey=""; // set the key name
|
|
i++;
|
|
if(!oc.Deserialize(js,slen,i))
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case ',': // value separator // value type must already be defined
|
|
i0=i+1;
|
|
if(!m_parent && m_type!=jtOBJ)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
else if(m_parent)
|
|
{
|
|
if(m_parent.m_type!=jtARRAY && m_parent.m_type!=jtOBJ)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
if(m_parent.m_type==jtARRAY && m_type==jtUNDEF) return true;
|
|
}
|
|
break;
|
|
|
|
// primitives can ONLY be in an array / or on their own
|
|
case '{': // the beginning of the object. create an object and take it from js
|
|
i0=i+1;
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // type error
|
|
return false;
|
|
}
|
|
m_type=jtOBJ; // set type of value
|
|
i++;
|
|
if(!Deserialize(js,slen,i))
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // pull it out
|
|
return false;
|
|
}
|
|
return js[i]=='}' || js[i]==0;
|
|
break;
|
|
case '}':
|
|
return m_type==jtOBJ; // end of object, current value must be object
|
|
|
|
case 't':
|
|
case 'T': // start true
|
|
case 'f':
|
|
case 'F': // start false
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // type error
|
|
return false;
|
|
}
|
|
m_type=jtBOOL; // set type
|
|
if(i+3<slen)
|
|
{
|
|
if(StringCompare(GetStr(js, i, 4), "true", false)==0)
|
|
{
|
|
m_bv=true;
|
|
i+=3;
|
|
return true;
|
|
}
|
|
}
|
|
if(i+4<slen)
|
|
{
|
|
if(StringCompare(GetStr(js, i, 5), "false", false)==0)
|
|
{
|
|
m_bv=false;
|
|
i+=4;
|
|
return true;
|
|
}
|
|
}
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false; //wrong type or end of line
|
|
break;
|
|
case 'n':
|
|
case 'N': // start null
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // type error
|
|
return false;
|
|
}
|
|
m_type=jtNULL; // set type of value
|
|
if(i+3<slen) if(StringCompare(GetStr(js,i,4),"null",false)==0)
|
|
{
|
|
i+=3;
|
|
return true;
|
|
}
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false; // not NULL or end of line
|
|
break;
|
|
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case '-':
|
|
case '+':
|
|
case '.': // start of number
|
|
{
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // type error
|
|
return false;
|
|
}
|
|
bool dbl=false;// set typo of value
|
|
int is=i;
|
|
while(js[i]!=0 && i<slen)
|
|
{
|
|
i++;
|
|
if(StringFind(num,GetStr(js,i,1))<0) break;
|
|
if(!dbl) dbl=(js[i]=='.' || js[i]=='e' || js[i]=='E');
|
|
}
|
|
m_sv=GetStr(js,is,i-is);
|
|
if(dbl)
|
|
{
|
|
m_type=jtDBL;
|
|
m_dv=StringToDouble(m_sv);
|
|
m_iv=(long)m_dv;
|
|
m_bv=m_iv!=0;
|
|
}
|
|
else
|
|
{
|
|
m_type=jtINT; // clarified the value type
|
|
m_iv=StringToInteger(m_sv);
|
|
m_dv=(double)m_iv;
|
|
m_bv=m_iv!=0;
|
|
}
|
|
i--;
|
|
return true; // moved back a character and exited
|
|
break;
|
|
}
|
|
case '\"': // start or end of line
|
|
if(m_type==jtOBJ) // if the type is still undefined and the key is not set
|
|
{
|
|
i++;
|
|
int is=i;
|
|
if(!ExtrStr(js,slen,i))
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // this is the key, go to the end of line
|
|
return false;
|
|
}
|
|
m_lkey=GetStr(js,is,i-is);
|
|
}
|
|
else
|
|
{
|
|
if(m_type!=jtUNDEF)
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__)); // type error
|
|
return false;
|
|
}
|
|
m_type=jtSTR; // set type of value
|
|
i++;
|
|
int is=i;
|
|
if(!ExtrStr(js,slen,i))
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+string(__LINE__));
|
|
return false;
|
|
}
|
|
FromStr(jtSTR,GetStr(js,is,i-is));
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------ ExtrStr
|
|
bool CJAVal::ExtrStr(char &js[],int slen,int &i)
|
|
{
|
|
for(; js[i]!=0 && i<slen; i++)
|
|
{
|
|
char c=js[i];
|
|
if(c=='\"') break; // end if line
|
|
if(c=='\\' && i+1<slen)
|
|
{
|
|
i++;
|
|
c=js[i];
|
|
switch(c)
|
|
{
|
|
case '/':
|
|
case '\\':
|
|
case '\"':
|
|
case 'b':
|
|
case 'f':
|
|
case 'r':
|
|
case 'n':
|
|
case 't':
|
|
break; // allowed
|
|
case 'u': // \uXXXX
|
|
{
|
|
i++;
|
|
for(int j=0; j<4 && i<slen && js[i]!=0; j++,i++)
|
|
{
|
|
if(!((js[i]>='0' && js[i]<='9') || (js[i]>='A' && js[i]<='F') || (js[i]>='a' && js[i]<='f')))
|
|
{
|
|
if(DEBUG_PRINT)Print(m_key+" "+CharToString(js[i])+" "+string(__LINE__)); // not hex
|
|
return false;
|
|
}
|
|
}
|
|
i--;
|
|
break;
|
|
}
|
|
default:
|
|
break; /*{ return false; } // unresolved escaped character */
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------ Escape
|
|
string CJAVal::Escape(string a)
|
|
{
|
|
ushort as[], s[];
|
|
int n=StringToShortArray(a, as);
|
|
if(ArrayResize(s, 2*n)!=2*n) return NULL;
|
|
int j=0;
|
|
for(int i=0; i<n; i++)
|
|
{
|
|
switch(as[i])
|
|
{
|
|
case '\\':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='\\';
|
|
j++;
|
|
break;
|
|
case '"':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='"';
|
|
j++;
|
|
break;
|
|
case '/':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='/';
|
|
j++;
|
|
break;
|
|
case 8:
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='b';
|
|
j++;
|
|
break;
|
|
case 12:
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='f';
|
|
j++;
|
|
break;
|
|
case '\n':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='n';
|
|
j++;
|
|
break;
|
|
case '\r':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='r';
|
|
j++;
|
|
break;
|
|
case '\t':
|
|
s[j]='\\';
|
|
j++;
|
|
s[j]='t';
|
|
j++;
|
|
break;
|
|
default:
|
|
s[j]=as[i];
|
|
j++;
|
|
break;
|
|
}
|
|
}
|
|
a=ShortArrayToString(s,0,j);
|
|
return a;
|
|
}
|
|
//------------------------------------------------------------------ Unescape
|
|
string CJAVal::Unescape(string a)
|
|
{
|
|
ushort as[], s[];
|
|
int n=StringToShortArray(a, as);
|
|
if(ArrayResize(s, n)!=n) return NULL;
|
|
int j=0,i=0;
|
|
while(i<n)
|
|
{
|
|
ushort c=as[i];
|
|
if(c=='\\' && i<n-1)
|
|
{
|
|
switch(as[i+1])
|
|
{
|
|
case '\\':
|
|
c='\\';
|
|
i++;
|
|
break;
|
|
case '"':
|
|
c='"';
|
|
i++;
|
|
break;
|
|
case '/':
|
|
c='/';
|
|
i++;
|
|
break;
|
|
case 'b':
|
|
c=8; /*08='\b'*/;
|
|
i++;
|
|
break;
|
|
case 'f':
|
|
c=12;/*0c=\f*/ i++;
|
|
break;
|
|
case 'n':
|
|
c='\n';
|
|
i++;
|
|
break;
|
|
case 'r':
|
|
c='\r';
|
|
i++;
|
|
break;
|
|
case 't':
|
|
c='\t';
|
|
i++;
|
|
break;
|
|
/*
|
|
case 'u': // \uXXXX
|
|
{
|
|
i+=2; ushort k=0;
|
|
for(int jj=0; jj<4 && i<n; jj++,i++)
|
|
{
|
|
c=as[i]; ushort h=0;
|
|
if(c>='0' && c<='9') h=c-'0';
|
|
else if(c>='A' && c<='F') h=c-'A'+10;
|
|
else if(c>='a' && c<='f') h=c-'a'+10;
|
|
else break; // не hex
|
|
k+=h*(ushort)pow(16,(3-jj));
|
|
}
|
|
i--;
|
|
c=k;
|
|
break;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
s[j]=c;
|
|
j++;
|
|
i++;
|
|
}
|
|
a=ShortArrayToString(s,0,j);
|
|
return a;
|
|
}
|
|
//+------------------------------------------------------------------+
|