SNAP Library 2.0, User Reference  2013-05-13 16:33:57
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; bool Ok=true; TStr MsgStr="Ok";
00169   try {
00170     Lx.GetSym(TFSet()|syLBracket|syLBrace);
00171     Val=GetValFromLx(Lx);
00172   }
00173   catch (PExcept Except){
00174     Ok=false; MsgStr=Except->GetMsgStr();
00175     Val=TJsonVal::New();
00176   }
00177   return Val;
00178 }
00179 
00180 PJsonVal TJsonVal::GetValFromStr(const TStr& JsonStr){
00181   PSIn SIn=TStrIn::New(JsonStr);
00182   return GetValFromSIn(SIn);
00183 }
00184 
00185 void TJsonVal::AddEscapeChAFromStr(const TStr& Str, TChA& ChA){
00186         if (TUnicodeDef::IsDef()) {
00187                 // parse the UTF8 string
00188                 TIntV UStr; TUnicodeDef::GetDef()->DecodeUtf8(Str, UStr);
00189                 // escape the string
00190                 for (int ChN = 0; ChN < UStr.Len(); ChN++) {
00191                         const int UCh = UStr[ChN];
00192                         if (UCh < 0x80) {
00193                                 // 7-bit ascii
00194                                 const char Ch = (char)UCh;
00195                                 switch (Ch) {
00196                                         case '"' : ChA.AddCh('\\'); ChA.AddCh('"'); break;
00197                                         case '\\' : ChA.AddCh('\\'); ChA.AddCh('\\'); break;
00198                                         case '/' : ChA.AddCh('\\'); ChA.AddCh('/'); break;
00199                                         case '\b' : ChA.AddCh('\\'); ChA.AddCh('b'); break;
00200                                         case '\f' : ChA.AddCh('\\'); ChA.AddCh('f'); break;
00201                                         case '\n' : ChA.AddCh('\\'); ChA.AddCh('n'); break;
00202                                         case '\r' : ChA.AddCh('\\'); ChA.AddCh('r'); break;
00203                                         case '\t' : ChA.AddCh('\\'); ChA.AddCh('t'); break;
00204                                         default :
00205                                                 ChA.AddCh(Ch);
00206                                 }
00207                         } else {
00208                                 // escape
00209                                 ChA += "\\u";
00210                                 ChA += TStr::Fmt("%04x", UCh);
00211                         }
00212                 }
00213         } else {
00214                 // escape the string
00215                 for (int ChN = 0; ChN < Str.Len(); ChN++) {
00216                         const char Ch = Str[ChN];
00217                         if ((Ch & 0x80) == 0) {
00218                                 // 7-bit ascii
00219                                 switch (Ch) {
00220                                         case '"' : ChA.AddCh('\\'); ChA.AddCh('"'); break;
00221                                         case '\\' : ChA.AddCh('\\'); ChA.AddCh('\\'); break;
00222                                         case '/' : ChA.AddCh('\\'); ChA.AddCh('/'); break;
00223                                         case '\b' : ChA.AddCh('\\'); ChA.AddCh('b'); break;
00224                                         case '\f' : ChA.AddCh('\\'); ChA.AddCh('f'); break;
00225                                         case '\n' : ChA.AddCh('\\'); ChA.AddCh('n'); break;
00226                                         case '\r' : ChA.AddCh('\\'); ChA.AddCh('r'); break;
00227                                         case '\t' : ChA.AddCh('\\'); ChA.AddCh('t'); break;
00228                                         default : ChA.AddCh(Ch);
00229                                 }
00230                         } else {
00231                                 // escape
00232                                 ChA += "\\u";
00233                                 ChA += TStr::Fmt("%02x", (int)Ch);
00234                         }
00235                 }
00236         }
00237 }
00238 
00239 void TJsonVal::AddQChAFromStr(const TStr& Str, TChA& ChA){
00240   ChA+="\"";
00241   AddEscapeChAFromStr(Str, ChA);
00242   ChA+="\"";
00243 }
00244 
00245 void TJsonVal::GetChAFromVal(const PJsonVal& Val, TChA& ChA){
00246   switch (Val->GetJsonValType()){
00247     case jvtNull: 
00248       ChA+="null"; break;
00249     case jvtBool:
00250       if (Val->GetBool()){ChA+="true";} else {ChA+="false";} break;
00251     case jvtNum: 
00252       ChA+=TStr::Fmt("%f", Val->GetNum()); break;
00253     case jvtStr:
00254       AddQChAFromStr(Val->GetStr(), ChA); break;
00255     case jvtArr:
00256       ChA+="[";
00257       for (int ArrValN=0; ArrValN<Val->GetArrVals(); ArrValN++){
00258         if (ArrValN>0){ChA+=", ";}
00259         GetChAFromVal(Val->GetArrVal(ArrValN), ChA);
00260       }
00261       ChA+="]"; 
00262       break;
00263     case jvtObj:
00264       ChA+="{";
00265       for (int ObjKeyN=0; ObjKeyN<Val->GetObjKeys(); ObjKeyN++){
00266         if (ObjKeyN>0){ChA+=", ";}
00267         TStr ObjKey; PJsonVal ObjVal; Val->GetObjKeyVal(ObjKeyN, ObjKey, ObjVal);
00268         AddQChAFromStr(ObjKey, ChA);
00269         ChA+=":";
00270         GetChAFromVal(ObjVal, ChA);
00271       }
00272       ChA+="}"; 
00273       break;
00274         default: TExcept::Throw("Error parsing json");
00275   }
00276 }
00277 
00278 TStr TJsonVal::GetStrFromVal(const PJsonVal& Val){
00279   TChA ChA;
00280   GetChAFromVal(Val, ChA);
00281   return ChA;
00282 }