#include #include #include #include #include #include #include #include #include #include #include "UDPTCPNetwork-json.h" /*********************************************************************** *********************************************************************** * * JSONParse * *********************************************************************** *********************************************************************** */ // FIXME: need to test embedded arrays 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(std::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 < (int) 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(std::string varname, std::string *dest) { std::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(std::string varname, int *dest) { std::string s; int res = GetValue(varname, &s); if (res) { *dest = atoi (s.c_str()); return 1; } return 0; }; int JSONParse::GetValueInt64(std::string varname, int64_t *dest) { std::string s; int res = GetValue(varname, &s); if (res) { *dest = atol (s.c_str()); return 1; } return 0; }; int JSONParse::GetValueString(std::string varname, std::string *dest) { std::string s; int res = GetValue(varname, &s); if (res) { *dest = JSONElement::StringRemoveEscape(&s); return 1; } return 0; }; int JSONParse::GetObject(std::string varname, JSONParse *dest) { std::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 /// @brief Reads the source and returns the string of element requested. /// @param src source json array /// @param idx index to read /// @param dest destiantion of the string /// @return 0 not found else 1 int JSONParse::GetIdx(std::string src, int idx, std::string *dest) { char recursive[MAXRECURSIVE]; int i = 0, rcnt = 0, cnt = 0; // debug ("src:%s\n\n", src.c_str()); (*dest) = ""; for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0; for (i = 0; i < (int) src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) { /* if (src[i] == '[' || src[i] == ']' || src[i] == '"' || src[i] == ',' || src[i] == '}' || src[i] == '{') { int _i; debug ("src[i]:%c i:%d rcnt:%d cnt:%d idx:%d recursive:", src[i], i, rcnt, cnt, idx); for (int _i = 0; _i < rcnt; _i++) printf ("%c", recursive[_i]); printf ("\n"); } */ if (src[i] == '[') { recursive[rcnt++] = src[i]; continue; } else if (src[i] == '{' ) recursive[rcnt++] = src[i]; else if (src[i] == '}' && recursive[rcnt-1] == '{') rcnt--; else if (src[i] == '"' && recursive[rcnt-1] == '"') rcnt--; else if (src[i] == '"') recursive[rcnt++] = src[i]; else if (src[i] == ',' && rcnt == 1) { cnt++; continue; } else if (src[i] == ']' && rcnt > 0) { continue; } if (rcnt > 0 && cnt == idx) { (*dest) += src[i]; if (src[i] == '\\') (*dest) += src[i]; } else { if (src[i] == '\\')i++; } } // // 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(std::string varname, int idx, std::string *dest) { std::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(std::string varname, int idx, JSONParse *dest) { std::list::iterator iter; std::string deststr; int ret = 0; if (dest == NULL) return 0; for (iter = names.begin(); iter != names.end(); iter++) { // debug ("name:%s value:%s\n", iter->name.c_str(), iter->value.c_str()); if (varname.compare(iter->name) == 0) { ret = GetIdx(iter->value, idx, &deststr); if (ret == 1) dest->Set(deststr); // debug ("Return: %s\n", deststr.c_str()); return ret; } } return 0; }; std::list JSONParse::GetElements() { std::list l; std::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 (std::string name, JSONParse jp) { JSONElement je; je.SetObject(name, jp.ToString()); names.push_back(je); }; void JSONParse::AddObject (std::string name, int val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (std::string name, int64_t val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (std::string name, std::string val) { JSONElement je; je.Set(name, val); names.push_back(je); }; void JSONParse::AddObject (std::string name, double val) { JSONElement je; je.Set(name, val); names.push_back(je); }; std::string JSONParse::ToString() { std::list::iterator iter; std::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; }; int JSONParse::LoadFromFile(std::string filename) { int fd; struct stat fs; char *buffer; if (stat(filename.c_str(), &fs) != 0) return -1; buffer = (char *) malloc (fs.st_size+1); memset (buffer, 0x0, fs.st_size+1); fd = open(filename.c_str(), O_RDONLY); if (fd < 0) return -1; read (fd, buffer, fs.st_size); close (fd); Set(buffer); free (buffer); return 0; }; int JSONParse::SaveToFile(std::string filename) { std::ofstream out(filename); if (!out) return -1; out << ToString(); out.close(); return 0; }; /*********************************************************************** *********************************************************************** * * JSONElement * *********************************************************************** *********************************************************************** */ std::string JSONElement::StringAddEscape (std::string *s) { std::string res = ""; if (s == NULL) return res; for (int i = 0; i < s->length(); i++) { if ((*s)[i] == '\"') { res += "\\\""; continue; } res += (*s)[i]; } return res; } std::string JSONElement::StringRemoveEscape (std::string *s) { std::string res = ""; if (s == NULL) return res; for (int i = 0; i < s->length(); i++) { if ((*s)[i] == '\\') { continue; } res += (*s)[i]; } return res; } void JSONElement::Set (std::string n, double v) { name = n; value = std::to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (std::string n, int v) { name = n; value = std::to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (std::string n, int64_t v) { name = n; value = std::to_string(v); type = JSON_T_NUMBER; }; void JSONElement::Set (std::string n, std::string v) { name = n; value = StringAddEscape(&v); type = JSON_T_STRING; }; void JSONElement::SetArray (std::string n, std::list *l) { std::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::SetAddArray (std::string n, std::string jpstring) { std::size_t ab; // start of array [ std::size_t ae; // end of array ] if (type != JSON_T_ARRAY || n.compare (name) != 0) { // reset array value = "[]"; name = n; } type = JSON_T_ARRAY; ab = value.find_first_of('['); ae = value.find_last_of(']'); value = value.substr(0, ae); if (value.length() > 2) value += ","; value += jpstring + "]"; } void JSONElement::SetObject (std::string n, std::string s) { name = n; value = s; type = JSON_T_OBJECT; }; std::string JSONElement::GetString () { std::string output = ""; std::string filename = __FILE__; switch (type) { case(JSON_T_NUMBER): output += "\"" + name + "\" : " + value; break; case(JSON_T_STRING): if (value.length()==0) { output += "\"" + name + "\" : \"\""; } 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 + "\" : []"; } else if (value[0] != '[') { output += "\"" + name + "\" : [" + value + "]"; } else output += "\"" + name + "\" : " + value; break; default: output += "\"error\" : \""+ filename + ":" + std::to_string(__LINE__) +" JSONElement unknown type error ("+std::to_string(type)+")\""; break; } return output; };