1 Star 4 Fork 2

linuxmail / lib-zjson

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
zcc_json.cpp 38.29 KB
一键复制 编辑 原始数据 按行查看 历史
linuxmail 提交于 2024-01-17 22:09 . 增加 int
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592
/*
* ================================
* eli960@qq.com
* http://linuxmail.cn/
* 2017-08-11
* ================================
*/
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#include "zcc_json.h"
#include <stdarg.h>
#include <string.h>
namespace zcc
{
typedef std::string ___std_string;
struct _json_walker_node {
json *new_json;
json *current_json;
std::map<std::string, json *>::const_iterator map_it;
int idx;
int status; /* 0: begin, 1: middle, 2: end */
};
class _json_walker {
public:
zinline _json_walker() { }
zinline ~_json_walker() { }
/* 本 json 库的 "序列化", "反序列化", "深度复制" 等操作,没有使用递归的方法 */
std::vector<json *> new_json_vec;
std::vector<json *> json_vec;
std::vector<std::map<std::string, json *>::const_iterator> object_vec;
std::vector<int> array_vec;
std::vector<int> status_vec;
public:
bool pop(_json_walker_node &node);
void push(_json_walker_node &node);
};
bool _json_walker::pop(_json_walker_node &node)
{
if (json_vec.empty()) {
return false;
}
node.new_json = new_json_vec.back();
node.current_json = json_vec.back();
node.idx = array_vec.back();
node.map_it = object_vec.back();
node.status = status_vec.back();
new_json_vec.pop_back();
json_vec.pop_back();
array_vec.pop_back();
object_vec.pop_back();
status_vec.pop_back();
return true;
}
void _json_walker::push(_json_walker_node &node)
{
new_json_vec.push_back(node.new_json);
json_vec.push_back(node.current_json);
array_vec.push_back(node.idx);
object_vec.push_back(node.map_it);
status_vec.push_back(node.status);
}
static zinline int _empty(const void *ptr) { return ((!ptr)||(!(*(const char *)(ptr)))); }
static std::string &_sprintf_1024(std::string &str, const char *format, ...)
{
va_list ap;
char buf[1024+1];
va_start(ap, format);
::vsnprintf(buf, 1024, format, ap);
va_end(ap);
str.append(buf);
return str;
}
static unsigned const char _char_xdigitval_vector[256] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
json::json()
{
parent_ = 0;
type_ = json_type_null;
}
json::json(const std::string &val)
{
parent_ = 0;
type_ = json_type_string;
new (val_.s) std::string(val);
}
json::json(const char *val, int len)
{
parent_ = 0;
type_ = json_type_string;
if (len < 0) {
len = strlen(val);
}
if (len == 0) {
new (val_.s) std::string();
} else {
new (val_.s) std::string(val, len);
}
}
json::json(ssize_t val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
json::json(size_t val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
#ifdef _WIN32
json::json(long val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
json::json(unsigned long val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
#endif // _WIN32
json::json(int val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
json::json(unsigned int val)
{
parent_ = 0;
type_ = json_type_long;
val_.l = val;
}
json::json(double val)
{
parent_ = 0;
type_ = json_type_double;
val_.d = val;
}
json::json(bool val)
{
parent_ = 0;
type_ = json_type_bool;
val_.b = val;
}
json::json(const unsigned char type)
{
parent_ = 0;
type_ = type;
if (type == json_type_null) {
} else if (type == json_type_bool) {
val_.b = false;
} else if (type == json_type_double) {
val_.d = 0;
} else if (type == json_type_long) {
val_.l = 0;
} else if (type == json_type_string) {
new (val_.s) std::string();
} else if (type == json_type_array) {
val_.v = new std::vector<json *>();
} else if (type == json_type_object) {
val_.m = new std::map<std::string, json *>();
}
}
json::~json()
{
reset();
}
json *json::reset()
{
json *js;
std::vector<json *> *vec_for_delete = 0;
switch(type_) {
case json_type_string:
((___std_string *)(val_.s))->~___std_string();
case json_type_null:
case json_type_bool:
case json_type_double:
case json_type_long:
type_ = json_type_null;
return this;
}
vec_for_delete = new std::vector<json *>();
auto &for_delete = *vec_for_delete;
for_delete.push_back(this);
while (!for_delete.empty()) {
js = for_delete.back();
for_delete.pop_back();
if (js == 0) {
continue;
}
if (js->type_ == json_type_array) {
if (js->val_.v->empty()) {
delete js->val_.v;
js->type_ = json_type_null;
if (js != this) {
delete js;
}
} else {
for_delete.push_back(js);
for_delete.push_back(js->val_.v->back());
js->val_.v->pop_back();
}
} else if (js->type_ == json_type_object) {
if (js->val_.m->empty()) {
delete js->val_.m;
js->type_ = json_type_null;
if (js != this) {
delete js;
}
} else {
for_delete.push_back(js);
for_delete.push_back(js->val_.m->begin()->second);
js->val_.m->erase(js->val_.m->begin());
}
} else {
if (js != this) {
delete js;
}
}
}
type_ = json_type_null;
delete vec_for_delete;
return this;
}
std::string &json::get_string_value(const char *def)
{
const char *v = def;
if (v == 0) {
v = "";
}
char buf[128 + 1];
if (type_ != json_type_string) {
if (type_ == json_type_bool)
{
buf[0] = (val_.b?'1':'0');
buf[1] = 0;
v = buf;
}
else if (type_ == json_type_long)
{
sprintf(buf, "%zd", val_.l);
v = buf;
}
else if (type_ == json_type_double)
{
sprintf(buf, "%lf", val_.d);
v = buf;
}
reset();
}
if (type_ == json_type_null) {
new (val_.s) std::string();
type_ = json_type_string;
*((std::string *)(val_.s)) = v;
}
return *((std::string *)(val_.s));
}
ssize_t &json::get_long_value(ssize_t def)
{
ssize_t v = def;
if (type_ != json_type_long) {
if (type_ == json_type_string)
{
v = atoll(((std::string *)(val_.s))->c_str());
}
else if (type_ == json_type_bool)
{
v = (val_.b?1:0);
}
else if (type_ == json_type_double)
{
v = (long)val_.d;
}
reset();
}
if (type_ == json_type_null) {
val_.l = v;
type_ = json_type_long;
}
return val_.l;
}
double &json::get_double_value(double def)
{
double v = def;
if (type_ != json_type_double) {
if (type_ == json_type_string)
{
v = atof(((std::string *)(val_.s))->c_str());
}
else if (type_ == json_type_bool)
{
v = (val_.b?1.0:0.0);
}
else if (type_ == json_type_long)
{
v = 1.0 * val_.d;
}
reset();
}
if (type_ == json_type_null) {
val_.d = v;
type_ = json_type_double;
}
return val_.d;
}
bool &json::get_bool_value(bool def)
{
bool v = def;
if (type_ != json_type_bool) {
if (type_ == json_type_string)
{
const char *p = ((std::string *)(val_.s))->c_str();
switch(p[0]) {
case 't':
case 'T':
case 'y':
case 'Y':
case '1':
v = true;
break;
case 'f':
case 'F':
case 'n':
case 'N':
case '0':
v = false;
break;
}
}
else if (type_ == json_type_long)
{
v = (val_.l);
}
else if (type_ == json_type_double)
{
v = (val_.d);
}
reset();
}
if (type_ == json_type_null) {
val_.b = v;
type_ = json_type_bool;
}
return val_.b;
}
const std::vector<json *> &json::get_array_value()
{
if (type_ != json_type_array) {
reset();
}
if (type_ == json_type_null) {
val_.v = new std::vector<json *>();
type_ = json_type_array;
}
return *(val_.v);
}
const std::map<std::string, json *> &json::get_object_value()
{
if (type_ != json_type_object) {
reset();
}
if (type_ == json_type_null) {
val_.m = new std::map<std::string, json *>();
type_ = json_type_object;
}
return *(val_.m);
}
json *json::set_string_value(const char *val, int len)
{
std::string &s = get_string_value();
s.clear();
if (len < 0) {
s.append(val);
} else if (len > 0) {
s.append(val, len);
}
return this;
}
json *json::used_for_bool()
{
get_bool_value();
return this;
}
json *json::used_for_long()
{
get_long_value();
return this;
}
json *json::used_for_double()
{
get_double_value();
return this;
}
json *json::used_for_string()
{
get_string_value();
return this;
}
json *json::used_for_array()
{
get_array_value();
return this;
}
json *json::used_for_object()
{
get_object_value();
return this;
}
json *json::array_get(int idx)
{
if (type_ != json_type_array) {
used_for_array();
}
int size = int(val_.v->size());
if (size < 1) {
return 0;
}
if (idx < 0) {
idx = size - 1;
}
if (size <= idx) {
return 0;
}
return (*val_.v)[idx];
}
json &json::array_get_or_create(int idx)
{
json *r = array_get(idx);
if (!r) {
r = array_update(idx, new json(), 0, true);
}
return *r;
}
json *json::object_get(const char *key)
{
if (type_ != json_type_object) {
used_for_object();
}
auto it = val_.m->find(key);
if (it == val_.m->end()) {
return 0;
}
return it->second;
}
json *json::object_get(const std::string &key)
{
if (type_ != json_type_object) {
used_for_object();
}
auto it = val_.m->find(key);
if (it == val_.m->end()) {
return 0;
}
return it->second;
}
json &json::object_get_or_create(const char *key)
{
json *r = object_get(key);
if (!r) {
r = object_update(key, new json(), 0, true);
}
return *r;
}
json &json::object_get_or_create(const std::string &key)
{
json *r = object_get(key);
if (!r) {
r = object_update(key, new json(), 0, true);
}
return *r;
}
int json::array_size()
{
if (type_ != json_type_array) {
used_for_array();
}
return (int)(val_.v->size());
}
int json::object_size()
{
if (type_ != json_type_object) {
used_for_object();
}
return (int)(val_.m->size());
}
json *json::array_insert(int idx, json *j, bool return_child)
{
j->parent_ = this;
used_for_array();
std::vector<json *> &v = *(val_.v);
int size = int(v.size());
if (idx < 0) {
idx = size;
}
if (idx < 0) {
idx = 0;
}
if (idx < size) {
v.insert(v.begin()+idx, j);
} else {
v.resize(idx+1, 0);
v[idx] = j;
}
return return_child?j:this;
}
json *json::array_update(int idx, json *j, json **old, bool return_child)
{
j->parent_ = this;
json *tmpj = 0;
used_for_array();
std::vector<json *> &v = *(val_.v);
int size = int(v.size());
if (idx < 0) {
idx = size - 1;
}
if (idx < 0) {
idx = 0;
}
if (idx < size) {
tmpj = v[idx];
} else {
v.resize(idx+1, 0);
}
v[idx] = j;
if (old) {
if (tmpj) {
tmpj->parent_ = 0;
}
*old = tmpj;
} else if (tmpj) {
delete tmpj;
}
return return_child?j:this;
}
bool json::array_delete(int idx, json **old)
{
json *tmpj = 0;
used_for_array();
std::vector<json *> &v = *(val_.v);
int size = int(v.size());
if (size < 1) {
return false;
}
if (idx < 0) {
idx = size - 1;
}
if (old) {
*old = 0;
}
if (idx >= size) {
return false;
}
tmpj = v[idx];
if (tmpj) {
tmpj->parent_ = 0;
}
if (old) {
*old = tmpj;
} else if (tmpj) {
delete tmpj;
}
v.erase(v.begin()+idx);
return true;
}
json *json::object_update(const std::string &key, json *j, json **old, bool return_child)
{
j->parent_ = this;
json *tmpj = 0;
used_for_object();
std::map<std::string, json *> &m = *(val_.m);
auto it = m.find(key);
if (it == m.end()) {
m[key] = j;
} else {
tmpj = it->second;
it->second = j;
if (tmpj) {
tmpj->parent_ = 0;
}
}
if (old) {
*old = tmpj;
} else if (tmpj) {
delete tmpj;
}
return return_child?j:this;
}
bool json::object_delete(const char *key, json **old)
{
json *tmpj = 0;
used_for_object();
std::map<std::string, json *> &m = *(val_.m);
if (old) {
*old = 0;
}
auto it = m.find(key);
if (it == m.end()) {
return false;
}
tmpj = it->second;
if (tmpj) {
tmpj->parent_ = 0;
}
if (old) {
*old = tmpj;
} else if (tmpj) {
delete tmpj;
}
m.erase(it);
return true;
}
static bool _get_path_idx(const char *ps, int &idx)
{
idx = 0;
if (!ps[0]) {
return true;
}
if (ps[0] == '-') {
ps++;
idx = -1;
}
for (; *ps; ps++) {
if (!isdigit(*ps)) {
return false;
}
idx = idx * 10 + (*ps - '0');
}
return true;
}
json *json::get_by_path(const char *path)
{
json *j = this;
if (_empty(path)) {
return j;
}
std::string tmpkey;
const char *ps = path, *p;
int idx;
while (j) {
tmpkey.clear();
p = strchr(ps, '/');
if (p) {
if (ps < p) {
tmpkey.append(ps, p - ps);
}
} else {
tmpkey.append(ps);
}
if (j->type_== json_type_array) {
if (!_get_path_idx(tmpkey.c_str(), idx)) {
j = 0;
break;
}
j = j->array_get(idx);
} else if (j->type_== json_type_object) {
j = j->object_get(tmpkey.c_str());
} else {
j = 0;
}
tmpkey.clear();
if (!p) {
break;
}
ps = p + 1;
}
return j;
}
json *json::get_by_path_vec(const char *path0, ...)
{
if (_empty(path0)) {
return 0;
}
json *j = this;
int first = 1, idx;
const char *ps;
va_list ap;
va_start(ap, path0);
while(j) {
if (first) {
first = 0;
ps = path0;
} else {
ps = va_arg(ap, const char *);
}
if (ps == 0) {
break;
}
if (j->type_== json_type_array) {
if (!_get_path_idx(ps, idx)) {
j = 0;
break;
}
j = j->array_get(idx);
} else if (j->type_== json_type_object) {
j = j->object_get(ps);
} else {
j = 0;
}
}
va_end(ap);
return j;
}
bool json::get_value_by_path(const char *name, std::string &value)
{
json *j = get_by_path(name);
if (!j) {
return false;
}
if (j->type_ == json_type_long) {
_sprintf_1024(value, "%l", j->val_.l);
} else if (j->type_ == json_type_string) {
value.append(j->val_.s);
} else if (j->type_ == json_type_double) {
_sprintf_1024(value, "%f", j->val_.d);
} else if (j->type_ == json_type_bool) {
value.append(j->val_.b?"1":"0");
} else if (j->type_ == json_type_null) {
value.append("0");
} else {
return false;
}
return true;
}
bool json::get_value_by_path(const char *name, ssize_t *value)
{
json *j = get_by_path(name);
if (!j) {
return false;
}
if (j->type_ == json_type_long) {
*value = j->val_.l;
} else if (j->type_ == json_type_string) {
*value = atol(j->get_string_value().c_str());
} else if (j->type_ == json_type_double) {
*value = (long)j->val_.l;
} else if (j->type_ == json_type_bool) {
*value = j->val_.b?1:0;
} else if (j->type_ == json_type_null) {
*value = 0;
} else {
return false;
}
return true;
}
json *json::get_top()
{
json *j = this;
while (j->parent_) {
j = j->parent_;
}
return j;
}
bool json::load_from_pathname(const char *pathname)
{
std::string con;
int ch;
#ifdef ZCC_JSON_FOPEN_FUNCTION
FILE *fp = ZCC_JSON_FOPEN_FUNCTION(pathname, "rb");
#else // ZCC_JSON_FOPEN_FUNCTION
FILE *fp = fopen(pathname, "rb");
#endif // ZCC_JSON_FOPEN_FUNCTION
while ((ch = fgetc(fp)) != EOF) {
con.push_back(ch);
}
if (ferror(fp)) {
fclose(fp);
return false;
}
fclose(fp);
if (!unserialize(con.c_str(), (int)con.size())) {
return false;
}
return true;
}
static zinline const char *___ignore_blank(const char *ps, const char *str_end)
{
while(ps < str_end){
if ((*ps != ' ') && (*ps != '\t') && (*ps != '\r') && (*ps != '\n')) {
break;
}
ps++;
}
return ps;
}
static zinline int ___ncr_decode(int ins, char *wchar)
{
if (ins < 128) {
*wchar = ins;
return 1;
}
if (ins < 2048) {
*wchar++ = (ins >> 6) + 192;
*wchar++ = (ins & 63) + 128;
return 2;
}
if (ins < 65536) {
*wchar++ = (ins >> 12) + 224;
*wchar++ = ((ins >> 6) & 63) + 128;
*wchar++ = (ins & 63) + 128;
return 3;
}
if (ins < 2097152) {
*wchar++ = (ins >> 18) + 240;
*wchar++ = ((ins >> 12) & 63) + 128;
*wchar++ = ((ins >> 6) & 63) + 128;
*wchar++ = (ins & 63) + 128;
return 4;
}
return 0;
}
static const char *___fetch_string(const char *ps, const char *str_end, std::string &str)
{
char begin = *ps ++, ch, ch2, ch3;
while (ps < str_end) {
ch = *ps ++;
if (ch =='"') {
if (begin == '"') {
return ps; /* true */
}
str.push_back(ch);
continue;
}
if (ch =='\'') {
if (begin == '\'') {
return ps; /* true */
}
str.push_back(ch);
continue;
}
if (ps == str_end) {
return ps; /* false */
}
if (ch == '\\') {
ch2 = *ps ++;
ch3 = 0;
if (ch2 == 'u') {
ch3 = 'u';
if (ps + 4 > str_end) {
return ps; /* false */
}
int uval = 0;
for (int count = 4; count ;count --) {
int ch4 = _char_xdigitval_vector[(unsigned char)(*ps++)];
if (ch4 == -1) {
return ps; /* false */
}
uval = (uval << 4) + ch4;
}
char buf[8];
int len = ___ncr_decode(uval, buf);
str.append(buf, len);
continue;
} else {
switch (ch2) {
case '\\':
ch3 = '\\';
break;
case '/':
ch3 = '/';
break;
case '"':
ch3 = '"';
break;
case '\'':
ch3 = '\'';
break;
case 'b':
ch3 = '\b';
break;
case 'f':
ch3 = '\f';
break;
case 'r':
ch3 = '\r';
break;
case 'n':
ch3 = '\n';
break;
case 't':
ch3 = '\t';
break;
}
}
if (ch3) {
str.push_back(ch3);
} else {
str.push_back('\\');
str.push_back(ch2);
}
continue;
} else {
str.push_back(ch);
}
}
return ps; /* false */
}
static const char *___fetch_string2(const char *ps, const char *str_end, std::string &str)
{
char ch;
while (ps < str_end) {
ch = *ps;
if ((ch == '\r') || (ch=='\n') || (ch==' ') || (ch == '\t') || (ch == ':')) {
break;
}
str.push_back(ch);
ps++;
}
if (ps == str_end) {
return ps; /* false */
}
return ps; /* false */
}
bool json::unserialize(const char *jstr, int jlen)
{
if (jlen < 0) {
jlen = strlen(jstr);
}
reset();
std::string tmpkey;
const char *ps = jstr, *str_end = ps + jlen;
std::vector<json *> json_vec;
json_vec.push_back(this);
json *current_json, *new_json, *old_json;
bool ret = false;
while(ps < str_end) {
ps = ___ignore_blank(ps, str_end);
if (ps == str_end) {
break;
}
if (json_vec.empty()) {
break;
}
current_json = json_vec.back();
json_vec.pop_back();
if (current_json->type_ == json_type_object) {
int comma_count = 0;
while(ps < str_end) {
ps = ___ignore_blank(ps, str_end);
if (ps == str_end) {
goto err;
}
if (*ps != ',') {
break;
}
comma_count ++;
ps ++;
}
if (ps == str_end) {
goto err;
}
if (*ps == '}') {
ps ++;
continue;
}
if ((current_json->object_size() > 0) && (comma_count == 0)) {
goto err;
}
tmpkey.clear();
if ((*ps == '"') || (*ps == '\'')) {
ps = ___fetch_string(ps, str_end, tmpkey);
} else {
ps = ___fetch_string2(ps, str_end, tmpkey);
}
new_json = new json();
current_json->object_update(tmpkey.c_str(), new_json, &old_json);
if (old_json) {
delete old_json;
goto err;
}
json_vec.push_back(current_json);
json_vec.push_back(new_json);
ps = ___ignore_blank(ps, str_end);
if (ps == str_end) {
goto err;
}
if (*ps != ':') {
goto err;
}
ps++;
continue;
}
if (current_json->type_ == json_type_array) {
int comma_count = 0;
while(ps < str_end) {
ps = ___ignore_blank(ps, str_end);
if (ps == str_end) {
goto err;
}
if (*ps != ',') {
break;
}
comma_count++;
ps ++;
}
if (ps == str_end) {
goto err;
}
if (*ps == ']') {
for (int i = 0; i < comma_count; i++) {
current_json->array_push(new json());
}
ps ++;
continue;
}
for (int i = 0; i < comma_count -1; i++) {
current_json->array_push(new json());
}
if ((current_json->array_size() > 0) && (comma_count < 1)){
goto err;
}
json_vec.push_back(current_json);
json_vec.push_back(current_json->array_push(new json(), true));
continue;
}
if (*ps == '{') {
json_vec.push_back(current_json);
current_json->used_for_object();
ps++;
continue;
}
if (*ps == '[') {
json_vec.push_back(current_json);
current_json->used_for_array();
ps++;
continue;
}
if ((*ps == '"') || (*ps == '\'')) {
tmpkey.clear();
ps = ___fetch_string(ps, str_end, tmpkey);
if((current_json->type_ != json_type_string) && (current_json->type_ != json_type_null)) {
goto err;
}
current_json->get_string_value() = tmpkey;
tmpkey.clear();
continue;
}
if ((*ps == '-') || ((*ps >= '0') && (*ps <= '9'))) {
tmpkey.clear();
bool is_double = false;
while(ps < str_end) {
int ch = *ps;
if ((ch!='-') && (ch!='+') && (ch!='.') && (ch!= 'E') &&(ch!='e') &&(!isdigit(ch))){
break;
}
if (ch == '.' || ch=='e' || ch == 'E'){
is_double = true;
}
tmpkey.push_back(ch);
ps++;
}
if (is_double) {
current_json->get_double_value() = atof(tmpkey.c_str());
} else {
current_json->get_long_value() = atol(tmpkey.c_str());
}
continue;
}
tmpkey.clear();
while(ps < str_end) {
int ch = *ps;
if (!isalpha(ch)){
break;
}
tmpkey.push_back(tolower(ch));
ps++;
if (tmpkey.size() > 10) {
goto err;
}
}
if ((!strcmp(tmpkey.c_str(), "null")) || (!strcmp(tmpkey.c_str(), "undefined"))) {
current_json->reset();
continue;
}
if (!strcmp(tmpkey.c_str(), "true")) {
current_json->get_bool_value() = true;
continue;
}
if (!strcmp(tmpkey.c_str(), "false")) {
current_json->get_bool_value() = false;
continue;
}
goto err;
}
ret = true;
err:
if (ret == false) {
reset();
}
return ret;
}
static void ___serialize_string(std::string &result, const char *data, int size)
{
const char *json_hex_chars = "0123456789abcdef";
result.push_back('"');
unsigned char *ps = (unsigned char *)data;
for (int i = 0; i < size; i++) {
int ch = ps[i];
switch(ch) {
case '\\':
result.push_back('\\');
result.push_back('\\');
break;
case '/':
result.push_back('\\');
result.push_back('/');
break;
case '\"':
result.push_back('\\');
result.push_back('"');
break;
case '\b':
result.push_back('\\');
result.push_back('b');
break;
case '\f':
result.push_back('\\');
result.push_back('f');
break;
case '\n':
result.push_back('\\');
result.push_back('n');
break;
case '\r':
result.push_back('\\');
result.push_back('r');
break;
case '\t':
result.push_back('\\');
result.push_back('t');
break;
default:
if (ch < ' ') {
result.append("\\u00");
result.push_back(json_hex_chars[ch>>4]);
result.push_back(json_hex_chars[ch&0X0F]);
} else {
result.push_back(ch);
}
break;
}
}
result.push_back('"');
}
static zinline void ___serialize_string2(std::string &result, const std::string &str)
{
___serialize_string(result, str.c_str(), (int)str.size());
}
static void _pretty_blank(std::string &result, int depth)
{
result.push_back('\n');
for (int i = 0; i < depth; i++) {
result.push_back(' ');
result.push_back(' ');
}
}
json *json::serialize(std::string &result, int flags)
{
_json_walker walker;
_json_walker_node wnode;
bool pretty_mode = (flags & json_serialize_pretty);
int depth = 0;
wnode.current_json = this;
wnode.status = 0;
walker.push(wnode);
while(walker.pop(wnode)) {
json *current_json = wnode.current_json;
unsigned char type = (current_json?current_json->type_:json_type_null);
if (type == json_type_null) {
result.append("null");
} else if (type == json_type_string) {
___serialize_string2(result, current_json->get_string_value());
} else if (type == json_type_bool) {
result.append((current_json->val_.b)?"true":"false");
} else if (type == json_type_long) {
_sprintf_1024(result, "%zd", current_json->get_long_value());
} else if (type == json_type_double) {
double d = current_json->get_double_value();
ssize_t l = (long)d;
if ((l > 1000LL * 1000 * 1000 * 1000) || (l < -1000LL * 1000 * 1000 * 1000)){
_sprintf_1024(result, "%e", d);
} else {
_sprintf_1024(result, "%lf", d);
}
} else if (type == json_type_array) {
int length = (int)current_json->array_size();
if (length == 0) {
result.append("[]");
continue;
}
if (wnode.status == 0) {
result.push_back('[');
wnode.idx = 0;
wnode.status = 1;
walker.push(wnode);
if (pretty_mode) {
depth ++;
_pretty_blank(result, depth);
}
continue;
}
if (wnode.status == 2) {
if (pretty_mode)
{
depth--;
_pretty_blank(result, depth);
}
result.push_back(']');
continue;
}
if ((wnode.idx > 0) && (wnode.idx < length)) {
result.push_back(',');
if (pretty_mode) {
_pretty_blank(result, depth);
}
}
wnode.idx++;
if (wnode.idx == length) {
wnode.status = 2;
}
walker.push(wnode);
wnode.current_json = current_json->array_get(wnode.idx - 1);
wnode.status = 0;
walker.push(wnode);
} else if (type == json_type_object) {
auto &m = current_json->get_object_value();
if (current_json->object_size() == 0) {
result.append("{}");
continue;
}
if (wnode.status == 0) {
result.push_back('{');
wnode.status = 1;
wnode.map_it = m.begin();
walker.push(wnode);
if (pretty_mode)
{
depth++;
_pretty_blank(result, depth);
}
continue;
}
if (wnode.status == 2) {
if (pretty_mode) {
depth --;
_pretty_blank(result, depth);
}
result.push_back('}');
continue;
}
if (wnode.map_it != m.begin()) {
result.push_back(',');
if (pretty_mode) {
_pretty_blank(result, depth);
}
}
___serialize_string2(result, wnode.map_it->first);
result.push_back(':');
if (pretty_mode) {
result.push_back(' ');
}
wnode.map_it ++;
if (wnode.map_it == m.end()) {
wnode.status = 2;
}
walker.push(wnode);
wnode.map_it --;
wnode.current_json = wnode.map_it->second;
wnode.status = 0;
walker.push(wnode);
continue;
}
}
return this;
}
static json *_deep_copy_simple(json *js, bool &is_simple)
{
json *njs = new json();
int type = (js?js->get_type():json_type_null);
if ((type == json_type_object) || (type == json_type_array)) {
is_simple = false;
return njs;
}
if (type == json_type_string) {
njs->set_string_value(js->get_string_value());
} else if (type == json_type_bool) {
njs->set_bool_value(js->get_bool_value());
} else if (type == json_type_long) {
njs->set_long_value(js->get_long_value());
} else if (type == json_type_double) {
njs->set_double_value(js->get_double_value());
}
is_simple = true;
return njs;
}
static json *_deep_copy_complex(json *r, json *current_json)
{
bool is_simple;
json *js, *new_json, *njs;
_json_walker walker;
_json_walker_node wnode;
wnode.new_json = r;
wnode.current_json = current_json;
wnode.status = 0;
walker.push(wnode);
while(walker.pop(wnode)) {
new_json = wnode.new_json;
current_json = wnode.current_json;
unsigned char type = current_json->get_type();
if (type == json_type_array) {
int length = current_json->array_size();
if (length == 0) {
new_json->used_for_array();
continue;
}
if (wnode.status == 0) {
wnode.status = 1;
wnode.idx = 0;
walker.push(wnode);
continue;
}
if (wnode.status == 2) {
continue;
}
js = current_json->array_get(wnode.idx);
njs = _deep_copy_simple(js, is_simple);
new_json->array_push(njs);
wnode.idx ++;
if (wnode.idx == length) {
wnode.status = 2;
}
walker.push(wnode);
if (is_simple) {
continue;
}
wnode.new_json = njs;
wnode.current_json = js;
wnode.status = 0;
walker.push(wnode);
continue;
} else /* if (type == json_type_object) */ {
auto &m = current_json->get_object_value();
if (current_json->object_size() == 0) {
new_json->used_for_object();
continue;
}
if (wnode.status == 0) {
wnode.status = 1;
wnode.map_it = m.begin();
walker.push(wnode);
continue;
}
if (wnode.status == 2) {
continue;
}
js = wnode.map_it->second;
njs = _deep_copy_simple(js, is_simple);
new_json->object_update(wnode.map_it->first.c_str(), njs);
wnode.map_it ++;
if (wnode.map_it == m.end()) {
wnode.status = 2;
}
walker.push(wnode);
if (is_simple) {
continue;
}
wnode.new_json = njs;
wnode.current_json = js;
wnode.status = 0;
walker.push(wnode);
continue;
}
}
return r;
}
json *json::deep_copy()
{
bool is_simple;
json *r = _deep_copy_simple(this, is_simple);
if (is_simple) {
return r;
}
return _deep_copy_complex(r, this);
}
json *json::mv_value(json &val)
{
reset();
if (val.type_ == json_type_string) {
std::swap(get_string_value(), val.get_string_value());
}
else
{
type_ = val.type_;
memcpy(&val_, &(val.val_), sizeof(val_));
val.type_ = json_type_null;
}
return this;
}
json *json::mv_value(json *val)
{
reset();
if (!val) {
return this;
}
mv_value(*val);
delete val;
return this;
}
json *json::debug_show()
{
std::string s;
serialize(s, json_serialize_pretty);
#ifdef zdebug_show
zdebug_show("JSON: %s\n", s.c_str());
#else
fprintf(stderr, "JSON: %s\n", s.c_str());
#endif
return this;
}
std::string json::object_get_string_value(const std::string &key, const char *def)
{
json *js = object_get(key);
if (!js) {
return def;
}
return js->get_string_value(def);
}
ssize_t json::object_get_long_value(const std::string &key, ssize_t def)
{
json *js = object_get(key);
if (!js) {
return def;
}
return js->get_long_value(def);
}
bool json::object_get_bool_value(const std::string &key, bool def)
{
json *js = object_get(key);
if (!js) {
return def;
}
return js->get_bool_value(def);
}
} /* namespace zcc */
C++
1
https://gitee.com/linuxmail/lib-zjson.git
git@gitee.com:linuxmail/lib-zjson.git
linuxmail
lib-zjson
lib-zjson
master

搜索帮助