#include #include #include #include "debug.h" #include "json.h" /*********************************************************************** *********************************************************************** * * JSONParse * *********************************************************************** *********************************************************************** */ enum { STEP_NONE = 0, STEP_STARTNAME, STEP_NAME, STEP_STARTVALUE, STEP_VALUE, STEP_END }; ///////////////////////////////////////////////////////// // // clear out all data // void JSONParse::Clear() { jsondata = ""; names.clear(); } ///////////////////////////////////////////////////////// // // read every element and keep only this in memory. // int JSONParse::Set(string json) { int i; int step; int level; bool ignorenext; JSONElement jelement; Clear(); // find start and read until end for (step = STEP_NONE, i = 0, ignorenext = false; i < json.length(); i++) { // need to copy next character // debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str()); if (ignorenext) { ignorenext = false; if (step == STEP_NAME) jelement.name += json[i]; if (step == STEP_VALUE) jelement.value += json[i]; } // searching for startname else if (step == STEP_NONE) { if (json[i] == '{') { step = STEP_STARTNAME; continue; } } // searching for startname else if (step == STEP_STARTNAME) { if (json[i] == '"') { step = STEP_NAME; continue; } } // copy name else if (step == STEP_NAME) { if (json[i] == '"') { step = STEP_STARTVALUE; continue; } else { jelement.name += json[i]; continue; } } // searching for startvalue else if (step == STEP_STARTVALUE) { if (json[i] == '"') { step = STEP_VALUE; jelement.type = JSON_T_STRING; continue; } if (json[i] == '{') { step = STEP_VALUE; level = 0; jelement.type = JSON_T_OBJECT; jelement.value = "{"; continue; } if (json[i] == '[') { step = STEP_VALUE; level = 0; jelement.type = JSON_T_ARRAY; jelement.value = "["; continue; } if ((json[i] >= '0' && json[i] <= '9') || (json[i] == '+' || json[i] == '-')) { step = STEP_VALUE; level = 0; jelement.type = JSON_T_NUMBER; jelement.value = json[i]; continue; } } // copy value else if (step == STEP_VALUE) { if (jelement.type == JSON_T_STRING) { if (json[i] == '"') step = STEP_END; else jelement.value += json[i]; continue; } else if (jelement.type == JSON_T_OBJECT) { if (json[i] == '}' && level == 0) { jelement.value += json[i]; step = STEP_END; } else { if (json[i] == '{') level++; // increase level if (json[i] == '}') level--; // decrease level jelement.value += json[i]; } continue; } else if (jelement.type == JSON_T_ARRAY) { if (json[i] == ']' && level == 0) { jelement.value += json[i]; step = STEP_END; } else { if (json[i] == '[') level++; // increase level if (json[i] == ']') level--; // decrease level jelement.value += json[i]; } continue; } else if (jelement.type == JSON_T_NUMBER) { if ((json[i] < '0' || json[i] > '9') && json[i] != '.' && json[i] != '+' && json[i] != 'e' && json[i] != 'E') step = STEP_END; else { jelement.value += json[i]; continue; } } } // another element? if (step == STEP_END) { if (json[i] == ',') { // debug (0, "* JSON.Set Add name:%s", jelement.name.c_str()); if (jelement.type != JSON_T_NONE) { // debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type); names.push_back (jelement); } jelement.Clear(); step = STEP_STARTNAME; } continue; } } // debug (0, "* JSON.Set Add name:%s", jelement.name.c_str()); if (jelement.type != JSON_T_NONE) { // debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type); names.push_back (jelement); } return 0; }; int JSONParse::GetValue(string varname, string *dest) { list::iterator iter; if (dest == NULL) return 0; *dest = ""; for (iter = names.begin(); iter != names.end(); iter++) { if (varname.compare(iter->name) == 0) { *dest = iter->value; return 1; } } return 0; }; int JSONParse::GetValueInt(string varname, int *dest) { string s; int res = GetValue(varname, &s); if (res) { *dest = atoi (s.c_str()); return 1; } return 0; }; int JSONParse::GetValueInt64(string varname, int64_t *dest) { string s; int res = GetValue(varname, &s); if (res) { *dest = atol (s.c_str()); return 1; } return 0; }; int JSONParse::GetObject(string varname, JSONParse *dest) { list::iterator iter; if (dest == NULL) return 0; for (iter = names.begin(); iter != names.end(); iter++) { if (varname.compare(iter->name) == 0) { dest->Set(iter->value); return 1; } } return 0; }; #define MAXRECURSIVE 255 int JSONParse::GetIdx(string src, int idx, string *dest) { char recursive[MAXRECURSIVE]; int i = 0, rcnt = 0, cnt = 0; (*dest) = ""; // printf("\n***************************************idx:%d\n", idx); for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0; for (i = 0; i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) { // printf ("i:%d rcnt:%d['%c'] cnt:%d char:'%c' ous:'%s'\n", // i, rcnt, recursive[rcnt], cnt, src[i], dest->c_str()); if (src[i] == '[') { recursive[rcnt++] = src[i]; continue; } else if (src[i] == '{' && recursive[rcnt] != '"') recursive[++rcnt] = src[i]; else if (src[i] == '}' && recursive[rcnt] == '{') rcnt--; else if (src[i] == '"' && recursive[rcnt] == '"') rcnt--; else if (src[i] == '"') recursive[++rcnt] = src[i]; else if (src[i] == ',' && rcnt == 1) { cnt++; continue; } else if (src[i] == ']' && rcnt == 1) { continue; } if (rcnt > 0 && cnt == idx) { (*dest) += src[i]; if (src[i] == '\\') (*dest) += src[i]; } else { if (src[i] == '\\')i++; } } // printf("\n***************************************idx:%d cnt:%d\n", idx, cnt); // printf("in:'%s'\n***\nout:'%s'\n\n*****\n", src.c_str(), dest->c_str()); // // final checks if (cnt == 0 && idx == 0 && // empty source/array? dest->size() == 0) return 0; // if (cnt >= idx) return 1; // found the right element return 0; // element not found } #undef MAXRECURSIVE int JSONParse::GetValueIdx(string varname, int idx, string *dest) { list::iterator iter; if (dest == NULL) return 0; for (iter = names.begin(); iter != names.end(); iter++) { if (varname.compare(iter->name) == 0) { return GetIdx(iter->value, idx, dest); } } return 0; }; int JSONParse::GetObjectIdx(string varname, int idx, JSONParse *dest) { list::iterator iter; string deststr; int ret = 0; if (dest == NULL) return 0; for (iter = names.begin(); iter != names.end(); iter++) { if (varname.compare(iter->name) == 0) { ret = GetIdx(iter->value, idx, &deststr); if (ret == 1) dest->Set(deststr); return ret; } } return 0; }; list JSONParse::GetElements() { list l; list::iterator iter; l.clear(); for (iter = names.begin(); iter != names.end(); iter++) { l.push_back(*iter); } return l; }; void JSONParse::AddObject (JSONElement element) { names.push_back (element); }; void JSONParse::AddObject (string name, JSONParse jp) { JSONElement je; je.SetObject(name, jp.ToString()); names.push_back(je); }; void JSONParse::AddObject (string name, int val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (string name, int64_t val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (string name, string val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (string name, double val) { JSONElement je; je.Set(name, val); names.push_back(je); }; string JSONParse::ToString() { list::iterator iter; string output; int level, i; output = "{"; for (level = 1, iter = names.begin(); iter != names.end(); iter++) { if (iter != names.begin()) output += ","; output += "\n"; for (i = 0; i < 4*level; i++) output += " "; output += iter->GetString(); } output += "\n}\n"; return output; }; /*********************************************************************** *********************************************************************** * * JSONElement * *********************************************************************** *********************************************************************** */ void JSONElement::Set (string n, double v) { name = n; value = to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (string n, int v) { name = n; value = to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (string n, int64_t v) { name = n; value = to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (string n, string v) { name = n; value = v; type = JSON_T_STRING; }; void JSONElement::SetArray (string n, list *l) { list::iterator iter; name = n; value = "["; type = JSON_T_STRING; for (iter = l->begin(); iter != l->end(); iter++) { if (iter != l->begin()) value += ","; value += iter->GetString(); } value += "]"; }; void JSONElement::SetObject (string n, string s) { name = n; value = s; type = JSON_T_OBJECT; }; string JSONElement::GetString () { string output = ""; string filename = __FILE__; switch (type) { case(JSON_T_NUMBER): output += "\"" + name + "\" : " + value; break; case(JSON_T_STRING): if (value.length()==0) { output += "\"" + name + "\" : \"\""; } // FIXME: we have to define all strings are saved here without "" // will be set up in the future // WORKAROUND for empty strings else if (value[0] != '"') { output += "\"" + name + "\" : \"" + value + "\""; } else output += "\"" + name + "\" : " + value; break; case(JSON_T_OBJECT): output += "\"" + name + "\" : " + value; break; case(JSON_T_ARRAY): if (value.length()==0) { output += "\"" + name + "\" : []"; } // WORKAROUND for arrays without [] else if (value[0] != '[') { output += "\"" + name + "\" : [" + value + "]"; } else output += "\"" + name + "\" : " + value; break; default: output += "\"error\" : \""+ filename + ":" + to_string(__LINE__) + " JSONElement unknown type error\"("+to_string(type)+")"; break; } return output; };