code_scanner/common/json/json.cpp

787 lines
13 KiB
C++
Raw Permalink Normal View History

2022-12-31 03:38:27 +00:00
#include "json.h"
#include "cJSON.h"
#include <stdlib.h>
#include <string.h>
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;
}
2022-12-31 03:50:15 +00:00
bool json::set_value(const char* key, const char* val)
2022-12-31 03:38:27 +00:00
{
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 : "";
2022-12-31 03:50:15 +00:00
child->strval_ = val ? val : "";
2022-12-31 03:38:27 +00:00
child->release();
}
else
{
2022-12-31 03:50:15 +00:00
child = new json(key, val);
2022-12-31 03:38:27 +00:00
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;
}