//+------------------------------------------------------------------ß //| JAson | //| This software is licensed under the MIT https://goo.gl/eyJgHe | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006-2017" #property version "1.12" #property strict //------------------------------------------------------------------ enum enJAType enum enJAType { jtUNDEF, jtNULL, jtBOOL, jtINT, jtDBL, jtSTR, jtARRAY, jtOBJ }; //------------------------------------------------------------------ class CJAVal class CJAVal { public: virtual void Clear(enJAType jt=jtUNDEF, bool savekey=false) { m_parent=NULL; if (!savekey) m_key=""; m_type=jt; m_bv=false; m_iv=0; m_dv=0; m_prec=8; m_sv=""; ArrayResize(m_e, 0, 100); } virtual bool Copy(const CJAVal &a) { if (m_key == "") 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_prec=a.m_prec; 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-100) m_prec=aprec; m_iv=(long)m_dv; m_sv=DoubleToString(m_dv, m_prec); 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: int Size() { return ArraySize(m_e); } virtual bool IsNumeric() { return m_type==jtDBL || m_type==jtINT; } virtual CJAVal* FindKey(string akey) { for (int i=Size()-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) { CJAVal* e=FindKey(akey); if (CheckPointer(e)!=POINTER_INVALID) { if (atype==jtUNDEF || atype==e.m_type) return GetPointer(e); } return NULL; } 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) { if (slen==0) return ""; 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[]) { if (m_type==jtUNDEF) m_type=jtARRAY; int n=ArrayResize(m_e, ArraySize(list), 100); for (int i=0; i=Size()) { CJAVal b(GetPointer(this), jtUNDEF); if (CheckPointer(Add(b)) == POINTER_INVALID) return NULL; } return GetPointer(m_e[i]); } //------------------------------------------------------------------ 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=Size(); 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, m_prec); 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) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif 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=="") { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } CJAVal val(GetPointer(this), jtUNDEF); CJAVal *oc=Add(val); // object type not yet defined oc.m_key=m_lkey; m_lkey=""; // set name of key i++; if (!oc.Deserialize(js, slen, i)) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } break; } case ',': // delimiter // the value type must already be defined i0=i+1; if (!m_parent && m_type!=jtOBJ) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } else if (m_parent) { if (m_parent.m_type!=jtARRAY && m_parent.m_type!=jtOBJ) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif 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 '{': // beginning of the object. Create an object and fetch it from js i0=i+1; if (m_type!=jtUNDEF) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } // type error m_type=jtOBJ; // set the value type i++; if (!Deserialize(js, slen, i)) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } // pull it out if (i>=slen) 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': // beginning of true case 'f': case 'F': // beginning of false if (m_type!=jtUNDEF) { #ifdef DEBUG Print(m_key+" "+string(__LINE__));#endif return false; } // type error m_type=jtBOOL; // set the value type if (i+3='0' && js[i]<='9') || (js[i]>='A' && js[i]<='F') || (js[i]>='a' && js[i]<='f'))) { Print(m_key+" "+CharToString(js[i])+" "+string(__LINE__)); return false; } // not hex } i--; break; } default: break; /*{ return false; } // not allowed 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='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; // not hex k+=h*(ushort)pow(16, (3-jj)); } i--; c=k; break; } } } s[j]=c; j++; i++; } a=ShortArrayToString(s, 0, j); return a; }