SNAP Library 2.1, User Reference  2013-09-25 10:47:25
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
json.cpp
Go to the documentation of this file.
00001 
00002 // Json-Value
00003 TJsonVal::TJsonVal(TSIn& SIn):
00004   JsonValType((TJsonValType)(TInt(SIn).Val)), Bool(SIn), 
00005   Num(SIn), Str(SIn), ValV(SIn), KeyValH(SIn) { }
00006 
00007 void TJsonVal::Save(TSOut& SOut) const {
00008   TInt((int)JsonValType).Save(SOut);
00009   Bool.Save(SOut); Num.Save(SOut);
00010   Str.Save(SOut); ValV.Save(SOut);
00011   KeyValH.Save(SOut);
00012 }
00013 
00014 TStr TJsonVal::SaveStr() { 
00015   return GetStrFromVal(this); 
00016 }
00017 
00018 bool TJsonVal::operator==(const TJsonVal& JsonVal) const {
00019   return JsonValType == JsonVal.JsonValType &&
00020     Bool == JsonVal.Bool &&
00021     Num == JsonVal.Num &&
00022     Str == JsonVal.Str &&
00023     ValV == JsonVal.ValV && 
00024     KeyValH == JsonVal.KeyValH;    
00025 }
00026 
00027 bool TJsonVal::operator!=(const TJsonVal& JsonVal) const {
00028   return !(*this == JsonVal);
00029 }
00030 
00031 void TJsonVal::AddToObj(const PJsonVal& Val) {
00032         EAssert(Val->IsObj());
00033         int KeyId = Val->KeyValH.FFirstKeyId();
00034         while (Val->KeyValH.FNextKeyId(KeyId)) {
00035                 AddToObj(Val->KeyValH.GetKey(KeyId), Val->KeyValH[KeyId]);
00036         }
00037 }
00038 
00039 PJsonVal TJsonVal::NewArr(const TJsonValV& ValV) {
00040         PJsonVal Val = TJsonVal::NewArr();
00041         for (int ValN = 0; ValN < ValV.Len(); ValN++) {
00042                 Val->AddToArr(ValV[ValN]);
00043         }
00044         return Val;
00045 }
00046 
00047 PJsonVal TJsonVal::NewArr(const TIntV& IntV) {
00048         PJsonVal Val = TJsonVal::NewArr();
00049         for (int IntN = 0; IntN < IntV.Len(); IntN++) {
00050                 Val->AddToArr(TJsonVal::NewNum((double)IntV[IntN]));
00051         }
00052         return Val;
00053 }
00054 
00055 PJsonVal TJsonVal::NewArr(const TFltV& FltV) {
00056         PJsonVal Val = TJsonVal::NewArr();
00057         for (int FltN = 0; FltN < FltV.Len(); FltN++) {
00058                 Val->AddToArr(TJsonVal::NewNum(FltV[FltN]));
00059         }
00060         return Val;
00061 }
00062 
00063 PJsonVal TJsonVal::NewArr(const TStrV& StrV) {
00064         PJsonVal Val = TJsonVal::NewArr();
00065         for (int StrN = 0; StrN < StrV.Len(); StrN++) {
00066                 Val->AddToArr(TJsonVal::NewStr(StrV[StrN]));
00067         }
00068         return Val;
00069 }
00070 
00071 PJsonVal TJsonVal::NewArr(const TFltPr& FltPr) {
00072   PJsonVal Val = TJsonVal::NewArr();
00073   Val->AddToArr(TJsonVal::NewNum(FltPr.Val1));
00074   Val->AddToArr(TJsonVal::NewNum(FltPr.Val2));
00075   return Val;
00076 }
00077 
00078 PJsonVal TJsonVal::GetObjKey(const TStr& Key) const {
00079   EAssert(IsObj());
00080   EAssert(IsObjKey(Key)); 
00081   return KeyValH.GetDat(Key);
00082 }
00083 
00084 PJsonVal TJsonVal::GetObjKey(const char *Key) const {
00085   EAssert(IsObj());
00086   EAssert(IsObjKey(Key));
00087   return KeyValH.GetDat(Key);
00088 }
00089 
00090 bool TJsonVal::GetObjBool(const TStr& Key, const bool& DefBool) const { 
00091   EAssert(IsObj());
00092   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetBool() : DefBool;
00093 }
00094 
00095 bool TJsonVal::GetObjBool(const char *Key, const bool& DefBool) const { 
00096   EAssert(IsObj());
00097   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetBool() : DefBool;
00098 }
00099 
00100 double TJsonVal::GetObjNum(const TStr& Key, const double& DefNum) const { 
00101   EAssert(IsObj());
00102   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetNum() : DefNum;
00103 } 
00104 
00105 double TJsonVal::GetObjNum(const char *Key, const double& DefNum) const { 
00106   EAssert(IsObj());
00107   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetNum() : DefNum;
00108 }
00109 
00110 TStr TJsonVal::GetObjStr(const TStr& Key, const TStr& DefStr) const { 
00111   EAssert(IsObj());
00112   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetStr() : DefStr;
00113 }
00114 
00115 TStr TJsonVal::GetObjStr(const char *Key, const TStr& DefStr) const { 
00116   EAssert(IsObj());
00117   return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetStr() : DefStr;
00118 }
00119   
00120 PJsonVal TJsonVal::GetValFromLx(TILx& Lx){
00121   static TFSet ValExpect=TFSet()|syIdStr|syFlt|syQStr|syLBracket|syLBrace|syRBracket;
00122   PJsonVal Val=TJsonVal::New();
00123   if ((Lx.Sym==syIdStr)&&(Lx.Str=="null")){
00124     Val->PutNull(); Lx.GetSym();
00125   } else if ((Lx.Sym==syIdStr)&&(Lx.Str=="true")){
00126     Val->PutBool(true); Lx.GetSym();
00127   } else if ((Lx.Sym==syIdStr)&&(Lx.Str=="false")){
00128     Val->PutBool(false); Lx.GetSym();
00129   } else if (Lx.Sym==syFlt){
00130     Val->PutNum(Lx.Flt); Lx.GetSym();
00131   } else if (Lx.Sym==syQStr){
00132     Val->PutStr(Lx.Str); Lx.GetSym();
00133   } else if (Lx.Sym==syLBracket){
00134     Val->PutArr(); Lx.GetSym(ValExpect); // added ValExpect to correctyl parse arrays of floats
00135     if (Lx.Sym!=syRBracket){
00136       forever{
00137         PJsonVal SubVal=TJsonVal::GetValFromLx(Lx);
00138         Val->AddToArr(SubVal);
00139         if (Lx.Sym==syComma){Lx.GetSym(ValExpect);} 
00140         else if (Lx.Sym==syRBracket){break;} 
00141         else {TExcept::Throw("JSON Array not properly formed.");}
00142       }
00143     }
00144     Lx.GetSym();
00145   } else if (Lx.Sym==syLBrace){
00146     Val->PutObj(); Lx.GetSym(TFSet()|syRBrace|syQStr);
00147     if (Lx.Sym!=syRBrace){
00148       forever{
00149         TStr SubKey=Lx.Str; 
00150         Lx.GetSym(syColon); 
00151         Lx.GetSym(ValExpect);
00152         PJsonVal SubVal=TJsonVal::GetValFromLx(Lx);
00153         Val->AddToObj(SubKey, SubVal);
00154         if (Lx.Sym==syComma){Lx.GetSym(TFSet()|syQStr);} 
00155         else if (Lx.Sym==syRBrace){break;} 
00156         else {TExcept::Throw("JSON Object not properly formed.");}
00157       }
00158     }
00159     Lx.GetSym();
00160   } else {
00161     TExcept::Throw("Unexpected JSON symbol.");
00162   }
00163   return Val;
00164 }
00165 
00166 PJsonVal TJsonVal::GetValFromSIn(const PSIn& SIn){
00167   TILx Lx(SIn, TFSet()|iloCmtAlw|iloCsSens|iloExcept|iloSigNum);
00168   PJsonVal Val;
00169   //bool Ok=true;
00170   TStr MsgStr="Ok";
00171   try {
00172     Lx.GetSym(TFSet()|syLBracket|syLBrace);
00173     Val=GetValFromLx(Lx);
00174   }
00175   catch (PExcept Except){
00176     //Ok=false;
00177     MsgStr=Except->GetMsgStr();
00178     Val=TJsonVal::New();
00179   }
00180   return Val;
00181 }
00182 
00183 PJsonVal TJsonVal::GetValFromStr(const TStr& JsonStr){
00184   PSIn SIn=TStrIn::New(JsonStr);
00185   return GetValFromSIn(SIn);
00186 }
00187 
00188 void TJsonVal::AddEscapeChAFromStr(const TStr& Str, TChA& ChA){
00189         if (TUnicodeDef::IsDef()) {
00190                 // parse the UTF8 string
00191                 TIntV UStr; TUnicodeDef::GetDef()->DecodeUtf8(Str, UStr);
00192                 // escape the string
00193                 for (int ChN = 0; ChN < UStr.Len(); ChN++) {
00194                         const int UCh = UStr[ChN];
00195                         if (UCh < 0x80) {
00196                                 // 7-bit ascii
00197                                 const char Ch = (char)UCh;
00198                                 switch (Ch) {
00199                                         case '"' : ChA.AddCh('\\'); ChA.AddCh('"'); break;
00200                                         case '\\' : ChA.AddCh('\\'); ChA.AddCh('\\'); break;
00201                                         case '/' : ChA.AddCh('\\'); ChA.AddCh('/'); break;
00202                                         case '\b' : ChA.AddCh('\\'); ChA.AddCh('b'); break;
00203                                         case '\f' : ChA.AddCh('\\'); ChA.AddCh('f'); break;
00204                                         case '\n' : ChA.AddCh('\\'); ChA.AddCh('n'); break;
00205                                         case '\r' : ChA.AddCh('\\'); ChA.AddCh('r'); break;
00206                                         case '\t' : ChA.AddCh('\\'); ChA.AddCh('t'); break;
00207                                         default :
00208                                                 ChA.AddCh(Ch);
00209                                 }
00210                         } else {
00211                                 // escape
00212                                 ChA += "\\u";
00213                                 ChA += TStr::Fmt("%04x", UCh);
00214                         }
00215                 }
00216         } else {
00217                 // escape the string
00218                 for (int ChN = 0; ChN < Str.Len(); ChN++) {
00219                         const char Ch = Str[ChN];
00220                         if ((Ch & 0x80) == 0) {
00221                                 // 7-bit ascii
00222                                 switch (Ch) {
00223                                         case '"' : ChA.AddCh('\\'); ChA.AddCh('"'); break;
00224                                         case '\\' : ChA.AddCh('\\'); ChA.AddCh('\\'); break;
00225                                         case '/' : ChA.AddCh('\\'); ChA.AddCh('/'); break;
00226                                         case '\b' : ChA.AddCh('\\'); ChA.AddCh('b'); break;
00227                                         case '\f' : ChA.AddCh('\\'); ChA.AddCh('f'); break;
00228                                         case '\n' : ChA.AddCh('\\'); ChA.AddCh('n'); break;
00229                                         case '\r' : ChA.AddCh('\\'); ChA.AddCh('r'); break;
00230                                         case '\t' : ChA.AddCh('\\'); ChA.AddCh('t'); break;
00231                                         default : ChA.AddCh(Ch);
00232                                 }
00233                         } else {
00234                                 // escape
00235                                 ChA += "\\u";
00236                                 ChA += TStr::Fmt("%02x", (int)Ch);
00237                         }
00238                 }
00239         }
00240 }
00241 
00242 void TJsonVal::AddQChAFromStr(const TStr& Str, TChA& ChA){
00243   ChA+="\"";
00244   AddEscapeChAFromStr(Str, ChA);
00245   ChA+="\"";
00246 }
00247 
00248 void TJsonVal::GetChAFromVal(const PJsonVal& Val, TChA& ChA){
00249   switch (Val->GetJsonValType()){
00250     case jvtNull: 
00251       ChA+="null"; break;
00252     case jvtBool:
00253       if (Val->GetBool()){ChA+="true";} else {ChA+="false";} break;
00254     case jvtNum: 
00255       ChA+=TStr::Fmt("%f", Val->GetNum()); break;
00256     case jvtStr:
00257       AddQChAFromStr(Val->GetStr(), ChA); break;
00258     case jvtArr:
00259       ChA+="[";
00260       for (int ArrValN=0; ArrValN<Val->GetArrVals(); ArrValN++){
00261         if (ArrValN>0){ChA+=", ";}
00262         GetChAFromVal(Val->GetArrVal(ArrValN), ChA);
00263       }
00264       ChA+="]"; 
00265       break;
00266     case jvtObj:
00267       ChA+="{";
00268       for (int ObjKeyN=0; ObjKeyN<Val->GetObjKeys(); ObjKeyN++){
00269         if (ObjKeyN>0){ChA+=", ";}
00270         TStr ObjKey; PJsonVal ObjVal; Val->GetObjKeyVal(ObjKeyN, ObjKey, ObjVal);
00271         AddQChAFromStr(ObjKey, ChA);
00272         ChA+=":";
00273         GetChAFromVal(ObjVal, ChA);
00274       }
00275       ChA+="}"; 
00276       break;
00277         default: TExcept::Throw("Error parsing json");
00278   }
00279 }
00280 
00281 TStr TJsonVal::GetStrFromVal(const PJsonVal& Val){
00282   TChA ChA;
00283   GetChAFromVal(Val, ChA);
00284   return ChA;
00285 }