#include "json.h" #include "cJSON.h" #include #include namespace special_char_trans { struct { const char* writedown_text; char readable_char; }transferred_chars[] = { { "\\\"", '\"' } , { "\\'", '\'' } , { "\\a", '\a' } , { "\\b", '\b' } , { "\\f", '\f' } , { "\\n", '\n' } , { "\\r", '\r' } , { "\\t", '\t' } , { "\\v", '\v' } // , { "\\?", '\?' } , { "\\\\", '\\' } , { "\\/", '/' } // , { "\\0", '\0' } }; void to_writedown(std::string& str) { std::string trans(str); const char* ptr = trans.c_str(); str.clear(); while (*ptr) { bool rep = false; if (*ptr == '\\') { if (ptr[1] == '\\') { str += "\\\\"; ptr++; rep = true; } else if( ptr[1] == '/' || ptr[1] == 'a' || ptr[1] == 'b' || ptr[1] == 'f' || ptr[1] == 'n' || ptr[1] == 'r' || ptr[1] == 't' || ptr[1] == 'u' || ptr[1] == 'v') { str += "\\"; ptr++; } else { str += "\\\\"; rep = true; } } else { for (size_t i = 0; i < sizeof(transferred_chars) / sizeof(transferred_chars[0]); ++i) { if (*ptr == transferred_chars[i].readable_char) { str += transferred_chars[i].writedown_text; rep = true; break; } } } if (!rep) str.append(1, *ptr); ptr++; } } } json::json(char* json_txt) : type_(VAL_TYPE_OBJECT), key_(""), strval_(""), cur_child_(-1) { simple_val_.dval = .0f; if(json_txt) attach_text(json_txt); } json::json(const char* key, bool val) : type_(VAL_TYPE_BOOL), key_(key ? key : ""), strval_(""), cur_child_(-1) { simple_val_.bval = val; } json::json(const char* key, int val) : type_(VAL_TYPE_INT), key_(key ? key : ""), strval_(""), cur_child_(-1) { simple_val_.nval = val; } json::json(const char* key, double val) : type_(VAL_TYPE_FLOAT), key_(key ? key : ""), strval_(""), cur_child_(-1) { simple_val_.dval = val; } json::json(const char* key, const char* val) : type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val ? val : ""), cur_child_(-1) {} json::~json() { clear(); } std::string json::object_key(json* jsn) { return "\"" + jsn->key() + "\":"; } std::string json::array_key(json* jsn) { return ""; } void json::from_cjson(cJSON* cj) { key_ = cj && cj->string ? cj->string : ""; while (cj) { json* child = nullptr; if (cj->type == cJSON_True) { child = new json(cj->string, true); } else if(cj->type == cJSON_False) { child = new json(cj->string, false); } else if (cj->type == cJSON_Number) { if (cj->valuedouble - (int)cj->valuedouble < .00001) { child = new json(cj->string, cj->valueint); } else { child = new json(cj->string, cj->valuedouble); } } else if (cj->type == cJSON_String) { child = new json(cj->string, cj->valuestring); } else if (cj->type == cJSON_Object || cj->type == cJSON_Array) { child = new json(); child->from_cjson(cj->child); child->key_ = cj->string ? cj->string : ""; } arr_val_.push_back(child); cj = cj->next; } if (arr_val_.size() == 1 && arr_val_[0]->arr_val_.size() == 0) { json* child = arr_val_[0]; if (!child->key_.empty()) // array { arr_val_.clear(); type_ = child->type_; key_ = child->key_; simple_val_.dval = child->simple_val_.dval; strval_ = child->strval_; for (auto& v : child->arr_val_) arr_val_.push_back(v); child->arr_val_.clear(); child->release(); } } if (arr_val_.size()) { type_ = arr_val_[0]->key().empty() ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; } } json* json::find_child(const char* key, bool remove) { json* ret = nullptr; if (type_ == VAL_TYPE_OBJECT) { for (size_t i = 0; i < arr_val_.size(); ++i) { if (arr_val_[i]->key() == key) { ret = arr_val_[i]; if (remove) arr_val_.erase(arr_val_.begin() + i); else ret->add_ref(); break; } } } return ret; } bool json::attach_text(char* json_txt) { clear(); cJSON* jsn = cJSON_Parse(json_txt); if (jsn) { char *text = cJSON_Print(jsn); if (text) free(text); from_cjson(jsn->child); cJSON_Delete(jsn); return true; } return false; } void json::clear(bool as_array) { if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { for (auto& v : arr_val_) v->release(); } type_ = as_array ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; simple_val_.dval = .0f; key_ = ""; strval_ = ""; arr_val_.clear(); cur_child_ = -1; } std::string json::to_string(void) { if (type_ == VAL_TYPE_NULL) return ""; if (type_ == VAL_TYPE_BOOL) return (simple_val_.bval ? "true" : "false"); if (type_ == VAL_TYPE_INT) return std::to_string(simple_val_.nval); if (type_ == VAL_TYPE_FLOAT) return std::to_string(simple_val_.dval); if (type_ == VAL_TYPE_STRING) { char* u = cJSON_utf8_2_unic(strval_.c_str()); std::string r(u); free(u); special_char_trans::to_writedown(r); return "\"" + r + "\""; } std::string(*k)(json*) = type_ == VAL_TYPE_OBJECT ? json::object_key : json::array_key; std::string str(type_ == VAL_TYPE_OBJECT ? "{" : "["); if (arr_val_.size()) { str += k(arr_val_[0]) + arr_val_[0]->to_string(); for(size_t i = 1; i < arr_val_.size(); ++i) str += "," + k(arr_val_[i]) + arr_val_[i]->to_string(); } str += type_ == VAL_TYPE_OBJECT ? "}" : "]"; return str; } std::string& json::key(void) { return key_; } bool json::is_array(void) { return type_ == VAL_TYPE_ARRAY; } bool json::is_leaf_node(void) { return type_ == VAL_TYPE_BOOL || type_ == VAL_TYPE_INT || type_ == VAL_TYPE_FLOAT || type_ == VAL_TYPE_STRING; } bool json::get_value(const char* key, bool& val) { bool ret = false; json* child = find_child(key); if (child) { if (child->type_ == VAL_TYPE_BOOL) { val = child->simple_val_.bval; ret = true; } child->release(); } else if (type_ == VAL_TYPE_BOOL && key_ == key) { val = simple_val_.bval; ret = true; } return ret; } bool json::get_value(const char* key, int& val) { bool ret = false; json* child = find_child(key); if (child) { if (child->type_ == VAL_TYPE_INT) { val = child->simple_val_.nval; ret = true; } child->release(); } else if (type_ == VAL_TYPE_INT && key_ == key) { val = simple_val_.nval; ret = true; } return ret; } bool json::get_value(const char* key, double& val) { bool ret = false; json* child = find_child(key); if (child) { if (child->type_ == VAL_TYPE_FLOAT) { val = child->simple_val_.dval; ret = true; } child->release(); } else if (type_ == VAL_TYPE_FLOAT && key_ == key) { val = simple_val_.dval; ret = true; } return ret; } bool json::get_value(const char* key, std::string& val) { bool ret = false; json* child = find_child(key); if (child) { if (child->type_ == VAL_TYPE_STRING) { val = child->strval_; ret = true; } child->release(); } else if (type_ == VAL_TYPE_STRING && key_ == key) { val = strval_; ret = true; } return ret; } bool json::get_value(const char* key, json*& val) { bool ret = false; json *child = find_child(key); if (child) { if (child->type_ == VAL_TYPE_OBJECT) { val = child; ret = true; } else { child->release(); } } return ret; } size_t json::children(void) { if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) return arr_val_.size(); else return -1; } json* json::child(size_t ind) { if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { if (ind >= 0 && ind < arr_val_.size()) { arr_val_[ind]->add_ref(); return arr_val_[ind]; } } return nullptr; } json* json::first_child(void) { if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) { cur_child_ = 0; if (arr_val_.size()) { arr_val_[0]->add_ref(); return arr_val_[0]; } } return nullptr; } json* json::next_child(void) { if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) { if (++cur_child_ < arr_val_.size()) { arr_val_[cur_child_]->add_ref(); return arr_val_[cur_child_]; } } return nullptr; } bool json::set_value(const char* key, bool val) { if (type_ != VAL_TYPE_OBJECT) return false; json* child = find_child(key); if (child) { child->clear(); child->type_ = VAL_TYPE_BOOL; child->key() = key ? key : ""; child->simple_val_.bval = val; child->release(); } else { child = new json(key, val); arr_val_.push_back(child); } return true; } bool json::set_value(const char* key, int val) { if (type_ != VAL_TYPE_OBJECT) return false; json* child = find_child(key); if (child) { child->clear(); child->type_ = VAL_TYPE_INT; child->key() = key ? key : ""; child->simple_val_.nval = val; child->release(); } else { child = new json(key, val); arr_val_.push_back(child); } return true; } bool json::set_value(const char* key, double val) { if (type_ != VAL_TYPE_OBJECT) return false; json* child = find_child(key); if (child) { child->clear(); child->type_ = VAL_TYPE_FLOAT; child->key() = key ? key : ""; child->simple_val_.dval = val; child->release(); } else { child = new json(key, val); arr_val_.push_back(child); } return true; } bool json::set_value(const char* key, const char* val) { if (type_ != VAL_TYPE_OBJECT) return false; json* child = find_child(key); if (child) { child->clear(); child->type_ = VAL_TYPE_STRING; child->key() = key ? key : ""; child->strval_ = val ? val : ""; child->release(); } else { child = new json(key, val); arr_val_.push_back(child); } return true; } bool json::set_value(const char* key, json* val) { if (type_ != VAL_TYPE_OBJECT) return false; for (size_t i = 0; i < arr_val_.size(); ++i) { if (arr_val_[i]->key() == key) { arr_val_[i]->release(); arr_val_[i] = val; val->add_ref(); return true; } } arr_val_.push_back(val); val->key() = key; val->add_ref(); return true; } json& json::operator+=(bool val) { if (type_ == VAL_TYPE_ARRAY) { json* child = new json(nullptr, val); arr_val_.push_back(child); } return *this; } json& json::operator+=(int val) { if (type_ == VAL_TYPE_ARRAY) { json* child = new json(nullptr, val); arr_val_.push_back(child); } return *this; } json& json::operator+=(double val) { if (type_ == VAL_TYPE_ARRAY) { json* child = new json(nullptr, val); arr_val_.push_back(child); } return *this; } json& json::operator+=(const char* val) { if (type_ == VAL_TYPE_ARRAY) { json* child = new json(nullptr, val); arr_val_.push_back(child); } return *this; } json& json::operator+=(json* val) { if (type_ == VAL_TYPE_ARRAY) { val->add_ref(); arr_val_.push_back(val); } return *this; } json& json::operator-=(int ind) { remove(ind); return *this; } bool json::remove(const char* key) { json* child = find_child(key, true); if (child) { child->release(); return true; } else { return false; } } bool json::remove(json* child) { if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { for (size_t i = 0; i < arr_val_.size(); ++i) { if (arr_val_[i] == child) { arr_val_[i]->release(); arr_val_.erase(arr_val_.begin() + i); return true; } } } return false; } bool json::remove(int ind) { bool ret = false; if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { if (ind >= 0 && ind < arr_val_.size()) { arr_val_[ind]->release(); arr_val_.erase(arr_val_.begin() + ind); ret = true; } } return ret; } int json::index(json* child) { if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) { for (int i = 0; i < arr_val_.size(); ++i) { if (arr_val_[i] == child) return i; } } return -1; } int json::index_move_to(json* child, int ind) { int i = index(child); if (i == -1) return -1; arr_val_.erase(arr_val_.begin() + i); if (ind < 0) ind = 0; if (ind > arr_val_.size()) ind = arr_val_.size(); arr_val_.insert(arr_val_.begin() + ind, child); return ind; } bool json::value(bool& val) { bool ret = false; if (is_leaf_node() && type_ == VAL_TYPE_BOOL) { val = simple_val_.bval; ret = true; } return ret; } bool json::value(int& val) { bool ret = false; if (is_leaf_node() && type_ == VAL_TYPE_INT) { val = simple_val_.nval; ret = true; } return ret; } bool json::value(double& val) { bool ret = false; if (is_leaf_node() && type_ == VAL_TYPE_FLOAT) { val = simple_val_.dval; ret = true; } return ret; } bool json::value(std::string& val) { bool ret = false; if (is_leaf_node() && type_ == VAL_TYPE_STRING) { val = strval_; ret = true; } return ret; } json& json::operator=(bool val) { if (is_leaf_node()) { simple_val_.bval = val; type_ = VAL_TYPE_BOOL; } return *this; } json& json::operator=(int val) { if (is_leaf_node()) { simple_val_.nval = val; type_ = VAL_TYPE_INT; } return *this; } json& json::operator=(double val) { if (is_leaf_node()) { simple_val_.dval = val; type_ = VAL_TYPE_FLOAT; } return *this; } json& json::operator=(const char* val) { if (is_leaf_node()) { strval_ = val ? val : ""; type_ = VAL_TYPE_STRING; } return *this; }