6 Star 60 Fork 20

lengjing/json

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
json.c 117.60 KB
一键复制 编辑 原始数据 按行查看 历史
lengjing 提交于 2024-06-12 19:31 . Adjust code structure
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134
/*******************************************
* SPDX-License-Identifier: MIT *
* Copyright (C) 2019-.... Jing Leng *
* Contact: Jing Leng <lengjingzju@163.com> *
* URL: https://github.com/lengjingzju/json *
*******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include "json.h"
#define type_member jkey.type
#define key_member jkey.str
#define str_member vstr.str
/**************** configuration ****************/
/*
* Algorithm to convert double to string
* 0: ljson dtoa developed by Jing Leng, fastest and best
* 1: sprintf of C standard library, slowest
* 2: grisu2 dtoa developed by Google
* 3: dragonbox dtoa developed by Raffaello Giulietti, faster than grisu2
*/
#ifndef JSON_DTOA_ALGORITHM
#define JSON_DTOA_ALGORITHM 0
#endif
#if JSON_DTOA_ALGORITHM == 1
static inline int json_dtoa(double num, char *buffer)
{
return sprintf(buffer, "%1.16g", num);
}
#elif JSON_DTOA_ALGORITHM == 2
extern int grisu2_dtoa(double num, char *buffer);
#define json_dtoa grisu2_dtoa
#elif JSON_DTOA_ALGORITHM == 3
extern int dragonbox_dtoa(double num, char *buffer);
#define json_dtoa dragonbox_dtoa
#else
#define json_dtoa jnum_dtoa
#endif
/* Whether to allow C-like single-line comments and multi-line comments */
#ifndef JSON_PARSE_SKIP_COMMENT
#define JSON_PARSE_SKIP_COMMENT 1
#endif
/* Whether to allow comma in last element of array or object */
#ifndef JSON_PARSE_LAST_COMMA
#define JSON_PARSE_LAST_COMMA 1
#endif
/* Whether to allow empty key */
#ifndef JSON_PARSE_EMPTY_KEY
#define JSON_PARSE_EMPTY_KEY 0
#endif
/* Whether to allow special characters such as newline in the string */
#ifndef JSON_PARSE_SPECIAL_CHAR
#define JSON_PARSE_SPECIAL_CHAR 1
#endif
/* Whether to allow single quoted string/key and unquoted key */
#ifndef JSON_PARSE_SPECIAL_QUOTES
#define JSON_PARSE_SPECIAL_QUOTES 1
#endif
/* Whether to allow HEX number */
#ifndef JSON_PARSE_HEX_NUM
#define JSON_PARSE_HEX_NUM 1
#endif
/* Whether to allow special number such as starting with '.', '+', '0' */
#ifndef JSON_PARSE_SPECIAL_NUM
#define JSON_PARSE_SPECIAL_NUM 1
#endif
/* Whether to allow special double such as NaN, Infinity, -Infinity */
#ifndef JSON_PARSE_SPECIAL_DOUBLE
#define JSON_PARSE_SPECIAL_DOUBLE 1
#endif
/* Whether to allow json starting with non-array and non-object */
#ifndef JSON_PARSE_SINGLE_VALUE
#define JSON_PARSE_SINGLE_VALUE 1
#endif
/* Whether to allow characters other than spaces after finishing parsing */
#ifndef JSON_PARSE_FINISHED_CHAR
#define JSON_PARSE_FINISHED_CHAR 0
#endif
/**************** debug ****************/
/* error print */
#define JSON_ERROR_PRINT_ENABLE 1
#if JSON_ERROR_PRINT_ENABLE
#define JsonErr(fmt, args...) do { \
printf("[JsonErr][%s:%d] ", __func__, __LINE__); \
printf(fmt, ##args); \
} while(0)
#define JsonPareseErr(s) do { \
if (parse_ptr->str) { \
char ptmp[32] = {0}; \
strncpy(ptmp, parse_ptr->str + parse_ptr->offset, 31); \
JsonErr("====%s====\n%s\n", s, ptmp); \
} else { \
JsonErr("%s\n", s); \
} \
} while(0)
#else
#define JsonErr(fmt, args...) do {} while(0)
#define JsonPareseErr(s) do {} while(0)
#endif
/**************** gcc builtin ****************/
#if defined(__GNUC__) || defined(__clang__)
#define UNUSED_ATTR __attribute__((unused))
#define FALLTHROUGH_ATTR __attribute__((fallthrough))
#define likely(cond) __builtin_expect(!!(cond), 1)
#define unlikely(cond) __builtin_expect(!!(cond), 0)
#else
#define UNUSED_ATTR
#define FALLTHROUGH_ATTR
#define likely(cond) (cond)
#define unlikely(cond) (cond)
#endif
#if JSON_PARSE_SPECIAL_QUOTES
#define UNUSED_END_CH
#else
#define UNUSED_END_CH UNUSED_ATTR
#endif
/**************** definition ****************/
/* head apis */
#define json_malloc malloc
#define json_calloc calloc
#define json_realloc realloc
#define json_strdup strdup
#define json_free free
#define JSON_ITEM_NUM_PLUS_DEF 16
#define JSON_POOL_MEM_SIZE_DEF 8096
/* print choice size */
#define JSON_PRINT_UTF16_SUPPORT 0
#define JSON_PRINT_NUM_INIT_DEF 1024
#define JSON_PRINT_NUM_PLUS_DEF 64
#define JSON_PRINT_DEPTH_DEF 16
#define JSON_PRINT_SIZE_PLUS_DEF 1024
#define JSON_FORMAT_ITEM_SIZE_DEF 32
#define JSON_UNFORMAT_ITEM_SIZE_DEF 24
/* file parse choice size */
#define JSON_PARSE_ERROR_STR "Z"
#define JSON_PARSE_READ_SIZE_DEF 8096
#define JSON_PARSE_NUM_DIV_DEF 8
/**************** json list ****************/
/* args of json_list_entry is different to list_entry of linux */
#define json_list_entry(ptr, type) ((type *)(ptr))
#define json_list_for_each_entry(pos, head, member) \
for (pos = json_list_entry((head)->next, typeof(*pos)); \
&pos->member != (struct json_list *)(head); \
pos = json_list_entry(pos->member.next, typeof(*pos)))
#define json_list_for_each_entry_safe(p, pos, n, head, member) \
for (p = json_list_entry((head), typeof(*pos)), \
pos = json_list_entry((head)->next, typeof(*pos)), \
n = json_list_entry(pos->member.next, typeof(*pos)); \
&pos->member != (struct json_list *)(head); \
p = pos, pos = n, n = json_list_entry(n->member.next, typeof(*n)))
static inline void INIT_JSON_LIST_HEAD(struct json_list_head *head)
{
head->next = (struct json_list *)head;
head->prev = (struct json_list *)head;
}
static inline void json_list_add_head(struct json_list *list, struct json_list_head *head)
{
if (head->next == (struct json_list *)head) {
head->prev = list;
}
list->next = head->next;
head->next = list;
}
static inline void json_list_add_tail(struct json_list *list, struct json_list_head *head)
{
list->next = head->prev->next;
head->prev->next = list;
head->prev = list;
}
static inline void json_list_add(struct json_list *list, struct json_list *prev, struct json_list_head *head)
{
if (prev->next == (struct json_list *)head) {
head->prev = list;
}
list->next = prev->next;
prev->next = list;
}
static inline void json_list_del(struct json_list *list, struct json_list *prev, struct json_list_head *head)
{
if (list->next == (struct json_list *)head) {
head->prev = prev;
}
prev->next = list->next;
list->next = NULL;
}
/**************** json normal apis ****************/
void json_memory_free(void *ptr)
{
if (ptr)
json_free(ptr);
}
static inline int _item_total_get(json_object *json)
{
int cnt = 0;
json_object *item = NULL;
switch (json->type_member) {
case JSON_ARRAY:
case JSON_OBJECT:
json_list_for_each_entry(item, &json->value.head, list) {
cnt += _item_total_get(item);
}
break;
default:
break;
}
++cnt;
return cnt;
}
int json_item_total_get(json_object *json)
{
if (!json)
return 0;
return _item_total_get(json);
}
void json_del_object(json_object *json)
{
json_object *p = NULL, *pos = NULL, *n = NULL;
if (!json)
return;
if (json->key_member)
json_free(json->key_member);
switch (json->type_member) {
case JSON_STRING:
if (json->value.str_member)
json_free(json->value.str_member);
break;
case JSON_ARRAY:
case JSON_OBJECT:
json_list_for_each_entry_safe(p, pos, n, &json->value.head, list) {
json_list_del(&pos->list, &p->list, &json->value.head);
json_del_object(pos);
pos = p;
}
break;
default:
break;
}
json_free(json);
}
json_object *json_new_object(json_type_t type)
{
json_object *json = NULL;
if ((json = json_calloc(1, sizeof(json_object))) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
json->type_member = type;
switch (type) {
case JSON_ARRAY:
case JSON_OBJECT:
INIT_JSON_LIST_HEAD(&json->value.head);
break;
default:
break;
}
return json;
}
json_object *json_create_item(json_type_t type, void *value)
{
json_object *json = NULL;
if ((json = json_calloc(1, sizeof(json_object))) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
json->type_member = type;
switch (type) {
case JSON_NULL:
break;
case JSON_BOOL: json->value.vnum.vbool = *(bool *)value; break;
case JSON_INT: json->value.vnum.vint = *(int32_t *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(uint32_t *)value; break;
case JSON_LINT: json->value.vnum.vlint = *(int64_t *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(uint64_t *)value; break;
case JSON_DOUBLE: json->value.vnum.vdbl = *(double *)value; break;
case JSON_STRING:
if (json_set_string_value(json, (json_string_t *)value) < 0)
return NULL;
break;
case JSON_ARRAY:
case JSON_OBJECT:
INIT_JSON_LIST_HEAD(&json->value.head);
break;
default:
break;
}
return json;
}
json_object *json_create_item_array(json_type_t type, void *values, int count)
{
int i = 0;
void *value = NULL;
json_object *json = NULL, *node = NULL;
if ((json = json_create_array()) == NULL) {
JsonErr("create array failed!\n");
return NULL;
}
for (i = 0; i < count; ++i) {
switch (type) {
case JSON_BOOL: value = ((bool *)values) + i; break;
case JSON_INT: value = ((int32_t *)values) + i; break;
case JSON_HEX: value = ((uint32_t *)values) + i; break;
case JSON_LINT: value = ((int64_t *)values) + i; break;
case JSON_LHEX: value = ((uint64_t *)values) + i; break;
case JSON_DOUBLE: value = ((double *)values) + i; break;
case JSON_STRING: value = ((json_string_t *)values) + i;break;
default: JsonErr("not support json type.\n"); goto err;
}
if ((node = json_create_item(type, value)) == NULL) {
JsonErr("create item failed!\n");
goto err;
}
json_list_add_tail(&node->list, &json->value.head);
}
return json;
err:
json_del_object(json);
return NULL;
}
void json_string_info_update(json_string_t *jstr)
{
const char *str = jstr->str;
int i = 0;
int escaped = 0;
if (jstr->len)
return;
if (str) {
for (i = 0; str[i]; ++i) {
switch (str[i]) {
case '\"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
escaped = 1;
break;
default:
#if JSON_PRINT_UTF16_SUPPORT
{
if ((unsigned char)str[i] < ' ')
escaped = 1;
}
#endif
break;
}
}
}
jstr->escaped = escaped;
jstr->len = i;
}
uint32_t json_string_hash_code(json_string_t *jstr)
{
uint32_t i = 0, hash = 0;
json_string_info_update(jstr);
if (!jstr->len)
return 0;
for (i = 0; i < jstr->len; ++i)
hash = (hash << 5) - hash + jstr->str[i];
return hash;
}
int json_string_strdup(json_string_t *src, json_string_t *dst)
{
json_string_info_update(src);
json_string_info_update(dst);
if (src->len) {
if (dst->len < src->len) {
if ((dst->str = json_realloc(dst->str, src->len + 1)) == NULL) {
JsonErr("malloc failed!\n");
dst->len = 0;
return -1;
}
}
dst->escaped = src->escaped;
dst->len = src->len;
memcpy(dst->str, src->str, src->len);
dst->str[src->len] = '\0';
} else {
dst->escaped = 0;
dst->len = 0;
if (dst->str) {
json_free(dst->str);
dst->str = NULL;
}
}
return 0;
}
int json_get_number_value(json_object *json, json_type_t type, void *value)
{
#define _get_number(json, etype, val) do { \
switch (json->type_member) { \
case JSON_BOOL: *(etype *)val = (etype)json->value.vnum.vbool; break; \
case JSON_INT: *(etype *)val = (etype)json->value.vnum.vint; break; \
case JSON_HEX: *(etype *)val = (etype)json->value.vnum.vhex; break; \
case JSON_LINT: *(etype *)val = (etype)json->value.vnum.vlint; break; \
case JSON_LHEX: *(etype *)val = (etype)json->value.vnum.vlhex; break; \
case JSON_DOUBLE: *(etype *)val = (etype)json->value.vnum.vdbl; break; \
default: *(etype *)val = (etype)0; JsonErr("wrong type!\n"); return -1; \
} \
} while(0)
switch (type) {
case JSON_BOOL: _get_number(json, bool, value); break;
case JSON_INT: _get_number(json, int32_t, value); break;
case JSON_HEX: _get_number(json, uint32_t, value); break;
case JSON_LINT: _get_number(json, int64_t, value); break;
case JSON_LHEX: _get_number(json, uint64_t, value); break;
case JSON_DOUBLE: _get_number(json, double, value); break;
default: JsonErr("wrong type!\n"); return -1;
}
return json->type_member == type ? 0 : json->type_member;
}
int json_set_number_value(json_object *json, json_type_t type, void *value)
{
int ret = 0;
switch (json->type_member) {
case JSON_BOOL:
case JSON_INT:
case JSON_HEX:
case JSON_LINT:
case JSON_LHEX:
case JSON_DOUBLE:
break;
default:
JsonErr("wrong type!\n");
return -1;
}
switch (type) {
case JSON_BOOL: json->value.vnum.vbool = *(bool *)value; break;
case JSON_INT: json->value.vnum.vint = *(int32_t *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(uint32_t *)value; break;
case JSON_LINT: json->value.vnum.vlint = *(int64_t *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(uint64_t *)value; break;
case JSON_DOUBLE: json->value.vnum.vdbl = *(double *)value; break;
default: return -1;
}
if (json->type_member != type) {
ret = json->type_member;
json->type_member = type;
}
return ret;
}
int json_get_array_size(json_object *json)
{
int count = 0;
json_object *pos = NULL;
if (json->type_member == JSON_ARRAY) {
json_list_for_each_entry(pos, &json->value.head, list) {
++count;
}
}
return count;
}
int json_get_object_size(json_object *json)
{
int count = 0;
json_object *pos = NULL;
if (json->type_member == JSON_OBJECT) {
json_list_for_each_entry(pos, &json->value.head, list) {
++count;
}
}
return count;
}
json_object *json_get_array_item(json_object *json, int seq, json_object **prev)
{
int count = 0;
json_object *p = NULL, *pos = NULL, *n = NULL;
if (json->type_member == JSON_ARRAY) {
json_list_for_each_entry_safe(p, pos, n, &json->value.head, list) {
if (count++ == seq) {
if (prev)
*prev = p;
return pos;
}
}
}
return NULL;
}
json_object *json_get_object_item(json_object *json, const char *key, json_object **prev)
{
json_object *p = NULL, *pos = NULL, *n = NULL;
if (json->type_member == JSON_OBJECT) {
if (key && key[0]) {
json_list_for_each_entry_safe(p, pos, n, &json->value.head, list) {
if (pos->key_member && strcmp(key, pos->key_member) == 0) {
if (prev)
*prev = p;
return pos;
}
}
} else {
json_list_for_each_entry_safe(p, pos, n, &json->value.head, list) {
if (!pos->jkey.len) {
if (prev)
*prev = p;
return pos;
}
}
}
}
return NULL;
}
json_object *json_search_object_item(json_items_t *items, json_string_t *jkey, uint32_t hash)
{
int left = 0, right = 0, middle = 0, i = 0, count = 0;
json_object *json = NULL;
if (!hash)
hash = json_string_hash_code(jkey);
count = items->count;
if (!count)
return NULL;
right = count - 1;
while (left <= right) {
middle = (left + right) >> 1;
if (hash == items->items[middle].hash) {
if (!items->conflicted)
return items->items[middle].json;
if (jkey->len) {
for (i = middle; i < count; ++i) {
if (hash != items->items[i].hash)
break;
json = items->items[i].json;
if (jkey->len == json->jkey.len && memcmp(jkey->str, json->key_member, jkey->len) == 0)
return json;
}
for (i = middle - 1; i >= 0; --i) {
if (hash != items->items[i].hash)
break;
json = items->items[i].json;
if (jkey->len == json->jkey.len && memcmp(jkey->str, json->key_member, jkey->len) == 0)
return json;
}
} else {
for (i = middle; i < count; ++i) {
if (hash != items->items[i].hash)
break;
json = items->items[i].json;
if (!json->jkey.len)
return json;
}
for (i = middle - 1; i >= 0; --i) {
if (hash != items->items[i].hash)
break;
json = items->items[i].json;
if (!json->jkey.len)
return json;
}
}
return NULL;
}
if (hash > items->items[middle].hash)
left = middle + 1;
else
right = middle - 1;
}
return NULL;
}
static int _json_hash_cmp(const void *a, const void *b)
{
uint32_t ha = ((const json_item_t *)a)->hash;
uint32_t hb = ((const json_item_t *)b)->hash;
return (int)(ha - hb);
}
static inline void json_object_items_sort(json_items_t *items)
{
items->conflicted = 0;
if (items->count > 1) {
uint32_t i = 0;
qsort(items->items, items->count, sizeof(json_item_t), _json_hash_cmp);
for (i = 1; i < items->count; ++i) {
if (items->items[i-1].hash == items->items[i].hash) {
items->conflicted = 1;
break;
}
}
}
}
void json_free_items(json_items_t *items)
{
if (items->items)
json_free(items->items);
items->items = NULL;
items->conflicted = 0;
items->total = 0;
items->count = 0;
}
int json_get_items(json_object *json, json_items_t *items)
{
json_object *pos = NULL;
items->count = 0;
if (json->type_member != JSON_ARRAY && json->type_member != JSON_OBJECT)
return -1;
json_list_for_each_entry(pos, &json->value.head, list) {
if (items->count == items->total) {
items->total += JSON_ITEM_NUM_PLUS_DEF;
if ((items->items = json_realloc(items->items, items->total * sizeof(json_item_t))) == NULL) {
JsonErr("malloc failed!\n");
goto err;
}
}
if (json->type_member == JSON_OBJECT)
items->items[items->count].hash = json_string_hash_code(&pos->jkey);
items->items[items->count++].json = pos;
}
if (json->type_member == JSON_OBJECT)
json_object_items_sort(items);
return 0;
err:
json_free_items(items);
return -1;
}
int json_add_item_to_array(json_object *array, json_object *item)
{
if (array->type_member == JSON_ARRAY) {
json_list_add_tail(&item->list, &array->value.head);
return 0;
}
return -1;
}
int json_add_item_to_object(json_object *object, json_object *item)
{
if (object->type_member == JSON_OBJECT) {
json_list_add_tail(&item->list, &object->value.head);
return 0;
}
return -1;
}
json_object *json_detach_item_from_array(json_object *json, int seq)
{
json_object *item = NULL, *prev = NULL;
if ((item = json_get_array_item(json, seq, &prev)) == NULL)
return NULL;
json_list_del(&item->list, &prev->list, &json->value.head);
return item;
}
json_object *json_detach_item_from_object(json_object *json, const char *key)
{
json_object *item = NULL, *prev = NULL;
if ((item = json_get_object_item(json, key, &prev)) == NULL)
return NULL;
json_list_del(&item->list, &prev->list, &json->value.head);
return item;
}
int json_del_item_from_array(json_object *json, int seq)
{
json_object *item = NULL;
if ((item = json_detach_item_from_array(json, seq)) == NULL)
return -1;
json_del_object(item);
return 0;
}
int json_del_item_from_object(json_object *json, const char *key)
{
json_object *item = NULL;
if ((item = json_detach_item_from_object(json, key)) == NULL)
return -1;
json_del_object(item);
return 0;
}
int json_replace_item_in_array(json_object *array, int seq, json_object *new_item)
{
json_object *item = NULL, *prev = NULL;
if (array->type_member == JSON_ARRAY) {
if ((item = json_get_array_item(array, seq, &prev)) != NULL) {
json_list_del(&item->list, &prev->list, &array->value.head);
json_del_object(item);
json_list_add(&new_item->list, &prev->list, &array->value.head);
} else {
json_list_add_tail(&new_item->list, &array->value.head);
}
return 0;
}
return -1;
}
int json_replace_item_in_object(json_object *object, json_object *new_item)
{
json_object *item = NULL, *prev = NULL;
if (object->type_member == JSON_OBJECT) {
if ((item = json_get_object_item(object, new_item->key_member, &prev)) != NULL) {
json_list_del(&item->list, &prev->list, &object->value.head);
json_del_object(item);
json_list_add(&new_item->list, &prev->list, &object->value.head);
} else {
json_list_add_tail(&new_item->list, &object->value.head);
}
return 0;
}
return -1;
}
json_object *json_deepcopy(json_object *json)
{
json_object *new_json = NULL;
json_object *item = NULL, *node = NULL;
switch (json->type_member) {
case JSON_NULL: new_json = json_create_null(); break;
case JSON_BOOL: new_json = json_create_bool(json->value.vnum.vbool); break;
case JSON_INT: new_json = json_create_int(json->value.vnum.vint); break;
case JSON_HEX: new_json = json_create_hex(json->value.vnum.vhex); break;
case JSON_LINT: new_json = json_create_lint(json->value.vnum.vlint); break;
case JSON_LHEX: new_json = json_create_lhex(json->value.vnum.vlhex); break;
case JSON_DOUBLE: new_json = json_create_double(json->value.vnum.vdbl); break;
case JSON_STRING: new_json = json_create_string(&json->value.vstr); break;
case JSON_ARRAY: new_json = json_create_array(); break;
case JSON_OBJECT: new_json = json_create_object(); break;
default: break;
}
if (new_json) {
if (json_string_strdup(&json->jkey, &new_json->jkey) < 0) {
JsonErr("add key failed!\n");
json_del_object(new_json);
return NULL;
}
if (json->type_member == JSON_ARRAY || json->type_member == JSON_OBJECT) {
json_list_for_each_entry(item, &json->value.head, list) {
if ((node = json_deepcopy(item)) == NULL) {
JsonErr("copy failed!\n");
json_del_object(new_json);
return NULL;
}
json_list_add_tail(&node->list, &new_json->value.head);
}
}
}
return new_json;
}
int json_copy_item_to_array(json_object *array, json_object *item)
{
json_object *node = NULL;
if (array->type_member == JSON_ARRAY) {
if ((node = json_deepcopy(item)) == NULL) {
JsonErr("copy failed!\n");
return -1;
}
json_list_add_tail(&node->list, &array->value.head);
return 0;
}
return -1;
}
int json_copy_item_to_object(json_object *object, json_object *item)
{
json_object *node = NULL;
if (object->type_member == JSON_OBJECT) {
if ((node = json_deepcopy(item)) == NULL) {
JsonErr("copy failed!\n");
return -1;
}
json_list_add_tail(&node->list, &object->value.head);
return 0;
}
return -1;
}
json_object *json_add_new_item_to_array(json_object *array, json_type_t type, void *value)
{
json_object *item = NULL;
if (array->type_member == JSON_ARRAY) {
switch (type) {
case JSON_NULL:
case JSON_BOOL:
case JSON_INT:
case JSON_HEX:
case JSON_LINT:
case JSON_LHEX:
case JSON_DOUBLE:
case JSON_STRING:
case JSON_ARRAY:
case JSON_OBJECT:
if ((item = json_create_item(type, value)) == NULL) {
JsonErr("create item failed!\n");
return NULL;
}
json_list_add_tail(&item->list, &array->value.head);
return item;
default:
JsonErr("not support json type.\n");
return NULL;
}
}
return NULL;
}
json_object *json_add_new_item_to_object(json_object *object, json_type_t type, json_string_t *jkey, void *value)
{
json_object *item = NULL;
if (object->type_member == JSON_OBJECT) {
switch (type) {
case JSON_NULL:
case JSON_BOOL:
case JSON_INT:
case JSON_HEX:
case JSON_LINT:
case JSON_LHEX:
case JSON_DOUBLE:
case JSON_STRING:
case JSON_ARRAY:
case JSON_OBJECT:
if ((item = json_create_item(type, value)) == NULL) {
JsonErr("create item failed!\n");
return NULL;
}
if (json_set_key(item, jkey) < 0) {
JsonErr("add key failed!\n");
json_del_object(item);
return NULL;
}
json_list_add_tail(&item->list, &object->value.head);
return item;
default:
JsonErr("not support json type.\n");
return NULL;
}
}
return NULL;
}
/**************** json pool memory apis ****************/
static json_mem_node_t s_invalid_json_mem_node;
static json_mem_t s_invalid_json_mem;
static void _json_mem_init(json_mem_mgr_t *mgr)
{
INIT_JSON_LIST_HEAD(&mgr->head);
mgr->cur_node = &s_invalid_json_mem_node;
mgr->mem_size = JSON_POOL_MEM_SIZE_DEF;
}
static void _json_mem_free(json_mem_mgr_t *mgr)
{
json_mem_node_t *p = NULL, *pos = NULL, *n = NULL;
json_list_for_each_entry_safe(p, pos, n, &mgr->head, list) {
json_list_del(&pos->list, &p->list, &mgr->head);
json_free(pos->ptr);
json_free(pos);
pos = p;
}
mgr->cur_node = &s_invalid_json_mem_node;
}
static void *_json_mem_new(size_t size, json_mem_mgr_t *mgr)
{
json_mem_node_t *node = NULL;
if ((node = json_malloc(sizeof(json_mem_node_t))) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
node->size = size;
if ((node->ptr = json_malloc(node->size)) == NULL) {
JsonErr("malloc failed! %d\n", (int)node->size);
json_free(node);
return NULL;
}
node->cur = node->ptr;
json_list_add_head(&node->list, &mgr->head);
return node;
}
static inline void *pjson_memory_alloc(size_t size, json_mem_mgr_t *mgr)
{
void *p = NULL;
if ((mgr->cur_node->cur - mgr->cur_node->ptr) + size > mgr->cur_node->size) {
if ((_json_mem_new((mgr->mem_size >= size) ? mgr->mem_size : size, mgr) == NULL)) {
return NULL;
}
mgr->cur_node = (json_mem_node_t *)(mgr->head.next);
}
p = mgr->cur_node->cur;
mgr->cur_node->cur += size;
return p;
}
void pjson_memory_init(json_mem_t *mem)
{
_json_mem_init(&mem->obj_mgr);
_json_mem_init(&mem->key_mgr);
_json_mem_init(&mem->str_mgr);
}
void pjson_memory_free(json_mem_t *mem)
{
_json_mem_free(&mem->obj_mgr);
_json_mem_free(&mem->key_mgr);
_json_mem_free(&mem->str_mgr);
}
int pjson_memory_statistics(json_mem_mgr_t *mgr)
{
json_mem_node_t *pos = NULL;
int size = 0;
json_list_for_each_entry(pos, &mgr->head, list) {
size += pos->size;
}
return size;
}
json_object *pjson_new_object(json_type_t type, json_mem_t *mem)
{
json_object *json = NULL;
if ((json = pjson_memory_alloc(sizeof(json_object), &mem->obj_mgr)) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
memset(json, 0, sizeof(json_object));
json->type_member = type;
switch (type) {
case JSON_ARRAY:
case JSON_OBJECT:
INIT_JSON_LIST_HEAD(&json->value.head);
break;
default:
break;
}
return json;
}
json_object *pjson_create_item(json_type_t type, void *value, json_mem_t *mem)
{
json_object *json = NULL;
if ((json = pjson_memory_alloc(sizeof(json_object), &mem->obj_mgr)) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
memset(json, 0, sizeof(json_object));
json->type_member = type;
switch (type) {
case JSON_NULL:
break;
case JSON_BOOL: json->value.vnum.vbool = *(bool *)value; break;
case JSON_INT: json->value.vnum.vint = *(int32_t *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(uint32_t *)value; break;
case JSON_LINT: json->value.vnum.vlint = *(int64_t *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(uint64_t *)value; break;
case JSON_DOUBLE: json->value.vnum.vdbl = *(double *)value; break;
case JSON_STRING:
if (pjson_set_string_value(json, (json_string_t *)value, mem) < 0)
return NULL;
break;
case JSON_ARRAY:
case JSON_OBJECT:
INIT_JSON_LIST_HEAD(&json->value.head);
break;
default:
break;
}
return json;
}
json_object *pjson_create_item_array(json_type_t item_type, void *values, int count, json_mem_t *mem)
{
int i = 0;
void *value = NULL;
json_object *json = NULL, *node = NULL;
if ((json = pjson_create_array(mem)) == NULL) {
JsonErr("create array failed!\n");
return NULL;
}
for (i = 0; i < count; ++i) {
switch (item_type) {
case JSON_BOOL: value = ((bool *)values) + i; break;
case JSON_INT: value = ((int32_t *)values) + i; break;
case JSON_HEX: value = ((uint32_t *)values) + i; break;
case JSON_LINT: value = ((int64_t *)values) + i; break;
case JSON_LHEX: value = ((uint64_t *)values) + i; break;
case JSON_DOUBLE: value = ((double *)values) + i; break;
case JSON_STRING: value = ((json_string_t *)values) + i;break;
default: JsonErr("not support json type.\n"); return NULL;
}
if ((node = pjson_create_item(item_type, value, mem)) == NULL) {
JsonErr("create item failed!\n");
return NULL;
}
json_list_add_tail(&node->list, &json->value.head);
}
return json;
}
int pjson_string_strdup(json_string_t *src, json_string_t *dst, json_mem_mgr_t *mgr)
{
json_string_info_update(src);
json_string_info_update(dst);
if (src->len) {
if (dst->len < src->len) {
if ((dst->str = pjson_memory_alloc(src->len + 1, mgr)) == NULL) {
JsonErr("malloc failed!\n");
dst->len = 0;
return -1;
}
}
dst->escaped = src->escaped;
dst->len = src->len;
memcpy(dst->str, src->str, src->len);
dst->str[src->len] = '\0';
} else {
dst->escaped = 0;
dst->len = 0;
dst->str = NULL;
}
return 0;
}
int pjson_replace_item_in_array(json_object *array, int seq, json_object *new_item)
{
json_object *item = NULL, *prev = NULL;
if (array->type_member == JSON_ARRAY) {
if ((item = json_get_array_item(array, seq, &prev)) != NULL) {
json_list_del(&item->list, &prev->list, &array->value.head);
json_list_add(&new_item->list, &prev->list, &array->value.head);
} else {
json_list_add_tail(&new_item->list, &array->value.head);
}
return 0;
}
return -1;
}
int pjson_replace_item_in_object(json_object *object, json_object *new_item)
{
json_object *item = NULL, *prev = NULL;
if (object->type_member == JSON_OBJECT) {
if ((item = json_get_object_item(object, new_item->key_member, &prev)) != NULL) {
json_list_del(&item->list, &prev->list, &object->value.head);
json_list_add(&new_item->list, &prev->list, &object->value.head);
} else {
json_list_add_tail(&new_item->list, &object->value.head);
}
return 0;
}
return -1;
}
json_object *pjson_deepcopy(json_object *json, json_mem_t *mem)
{
json_object *new_json = NULL;
json_object *item = NULL, *node = NULL;
switch (json->type_member) {
case JSON_NULL: new_json = pjson_create_null(mem); break;
case JSON_BOOL: new_json = pjson_create_bool(json->value.vnum.vbool, mem); break;
case JSON_INT: new_json = pjson_create_int(json->value.vnum.vint, mem); break;
case JSON_HEX: new_json = pjson_create_hex(json->value.vnum.vhex, mem); break;
case JSON_LINT: new_json = pjson_create_lint(json->value.vnum.vlint, mem); break;
case JSON_LHEX: new_json = pjson_create_lhex(json->value.vnum.vlhex, mem); break;
case JSON_DOUBLE: new_json = pjson_create_double(json->value.vnum.vdbl, mem); break;
case JSON_STRING: new_json = pjson_create_string(&json->value.vstr, mem); break;
case JSON_ARRAY: new_json = pjson_create_array(mem); break;
case JSON_OBJECT: new_json = pjson_create_object(mem); break;
default: break;
}
if (new_json) {
if (pjson_string_strdup(&json->jkey, &new_json->jkey, &mem->key_mgr) < 0) {
JsonErr("add key failed!\n");
return NULL;
}
if (json->type_member == JSON_ARRAY || json->type_member == JSON_OBJECT) {
json_list_for_each_entry(item, &json->value.head, list) {
if ((node = pjson_deepcopy(item, mem)) == NULL) {
JsonErr("copy failed!\n");
return NULL;
}
json_list_add_tail(&node->list, &new_json->value.head);
}
}
}
return new_json;
}
int pjson_copy_item_to_array(json_object *array, json_object *item, json_mem_t *mem)
{
json_object *node = NULL;
if (array->type_member == JSON_ARRAY) {
if ((node = pjson_deepcopy(item, mem)) == NULL) {
JsonErr("copy failed!\n");
return -1;
}
json_list_add_tail(&node->list, &array->value.head);
return 0;
}
return -1;
}
int pjson_copy_item_to_object(json_object *object, json_object *item, json_mem_t *mem)
{
json_object *node = NULL;
if (object->type_member == JSON_OBJECT) {
if ((node = pjson_deepcopy(item, mem)) == NULL) {
JsonErr("copy failed!\n");
return -1;
}
json_list_add_tail(&node->list, &object->value.head);
return 0;
}
return -1;
}
json_object *pjson_add_new_item_to_array(json_object *array, json_type_t type, void *value, json_mem_t *mem)
{
json_object *item = NULL;
if (array->type_member == JSON_ARRAY) {
switch (type) {
case JSON_NULL:
case JSON_BOOL:
case JSON_INT:
case JSON_HEX:
case JSON_LINT:
case JSON_LHEX:
case JSON_DOUBLE:
case JSON_STRING:
case JSON_ARRAY:
case JSON_OBJECT:
if ((item = pjson_create_item(type, value, mem)) == NULL) {
JsonErr("create item failed!\n");
return NULL;
}
json_list_add_tail(&item->list, &array->value.head);
return item;
default:
JsonErr("not support json type.\n");
return NULL;
}
}
return NULL;
}
json_object *pjson_add_new_item_to_object(json_object *object, json_type_t type, json_string_t *jkey, void *value, json_mem_t *mem)
{
json_object *item = NULL;
if (object->type_member == JSON_OBJECT) {
switch (type) {
case JSON_NULL:
case JSON_BOOL:
case JSON_INT:
case JSON_HEX:
case JSON_LINT:
case JSON_LHEX:
case JSON_DOUBLE:
case JSON_STRING:
case JSON_ARRAY:
case JSON_OBJECT:
if ((item = pjson_create_item(type, value, mem)) == NULL) {
JsonErr("create item failed!\n");
return NULL;
}
if (pjson_set_key(item, jkey, mem) < 0) {
JsonErr("add key failed!\n");
return NULL;
}
json_list_add_tail(&item->list, &object->value.head);
return item;
default:
JsonErr("not support json type.\n");
return NULL;
}
}
return NULL;
}
/**************** json print apis ****************/
typedef struct _json_print_t {
int fd;
char *ptr;
char *cur;
int (*realloc)(struct _json_print_t *print_ptr, size_t slen);
size_t size;
size_t plus_size;
size_t item_size;
int item_total;
int item_count;
bool format_flag;
} json_print_t;
#define GET_BUF_USED_SIZE(bp) ((bp)->cur - (bp)->ptr)
#define GET_BUF_FREE_SIZE(bp) ((bp)->size - ((bp)->cur - (bp)->ptr))
static int _print_file_ptr_realloc(json_print_t *print_ptr, size_t slen)
{
size_t len = GET_BUF_USED_SIZE(print_ptr);
if (len > 0) {
if (len != (size_t)write(print_ptr->fd, print_ptr->ptr, len)) {
JsonErr("write failed!\n");
return -1;
}
print_ptr->cur = print_ptr->ptr;
}
len = slen + 1;
if (print_ptr->size < len) {
while (print_ptr->size < len)
print_ptr->size += print_ptr->plus_size;
if ((print_ptr->ptr = json_realloc(print_ptr->ptr, print_ptr->size)) == NULL) {
JsonErr("malloc failed!\n");
print_ptr->cur = print_ptr->ptr;
return -1;
}
print_ptr->cur = print_ptr->ptr;
}
return 0;
}
static int _print_str_ptr_realloc(json_print_t *print_ptr, size_t slen)
{
size_t used = GET_BUF_USED_SIZE(print_ptr);
size_t len = used + slen + 1;
while (print_ptr->item_total < print_ptr->item_count)
print_ptr->item_total += JSON_PRINT_NUM_PLUS_DEF;
if (print_ptr->item_total - print_ptr->item_count > print_ptr->item_count) {
print_ptr->size += print_ptr->size;
} else {
print_ptr->size += (uint64_t)print_ptr->size *
(print_ptr->item_total - print_ptr->item_count) / print_ptr->item_count;
}
while (print_ptr->size < len)
print_ptr->size += print_ptr->plus_size;
if ((print_ptr->ptr = json_realloc(print_ptr->ptr, print_ptr->size)) == NULL) {
JsonErr("malloc failed!\n");
print_ptr->cur = print_ptr->ptr;
return -1;
}
print_ptr->cur = print_ptr->ptr + used;
return 0;
}
#define _PRINT_PTR_REALLOC(nz) do { \
if (unlikely(GET_BUF_FREE_SIZE(print_ptr) < nz \
&& print_ptr->realloc(print_ptr, nz) < 0)) \
goto err; \
} while(0)
#define _PRINT_PTR_NUMBER(fname, num) do { \
_PRINT_PTR_REALLOC(129); \
print_ptr->cur += fname(num, print_ptr->cur); \
} while(0)
#define _PRINT_PTR_STRNCAT(str, slen) do { \
_PRINT_PTR_REALLOC((slen + 1)); \
memcpy(print_ptr->cur, str, slen); \
print_ptr->cur += slen; \
} while(0)
static inline int _print_addi_format(json_print_t *print_ptr, size_t depth)
{
_PRINT_PTR_REALLOC((depth + 2));
*print_ptr->cur++ = '\n';
memset(print_ptr->cur, '\t', depth);
print_ptr->cur += depth;
return 0;
err:
return -1;
}
#define _PRINT_ADDI_FORMAT(ptr, depth) do { if (unlikely(_print_addi_format(ptr, depth) < 0)) goto err; } while(0)
static int _json_print_string(json_print_t *print_ptr, json_string_t *jstr)
{
#define _JSON_PRINT_SEGMENT() do { \
size = str - bak - 1; \
memcpy(print_ptr->cur, bak, size); \
print_ptr->cur += size; \
bak = str; \
} while(0)
char ch = '\0';
size_t len = 0, size = 0, alloced = 0;
const char *str = NULL, *bak = NULL, *end = NULL;
str = jstr->str;
len = jstr->len;
end = str + len;
if (likely(!jstr->escaped)) {
alloced = len + 3;
_PRINT_PTR_REALLOC(alloced);
*print_ptr->cur++ = '\"';
memcpy(print_ptr->cur, str, len);
print_ptr->cur += len;
*print_ptr->cur++ = '\"';
return 0;
}
#if JSON_PRINT_UTF16_SUPPORT
alloced = (len << 2) + (len << 1) + 3;
#else
alloced = (len << 1) + 3;
#endif
_PRINT_PTR_REALLOC(alloced);
*print_ptr->cur++ = '\"';
bak = str;
while (str < end) {
switch ((*str++)) {
case '\"': ch = '\"'; break;
case '\\': ch = '\\'; break;
case '\b': ch = 'b' ; break;
case '\f': ch = 'f' ; break;
case '\n': ch = 'n' ; break;
case '\r': ch = 'r' ; break;
case '\t': ch = 't' ; break;
case '\v': ch = 'v' ; break;
default:
#if JSON_PRINT_UTF16_SUPPORT
{
unsigned char uc = (unsigned char)(*(str-1));
if (uc < ' ') {
_JSON_PRINT_SEGMENT();
*print_ptr->cur++ = '\\';
*print_ptr->cur++ = 'u';
*print_ptr->cur++ = '0';
*print_ptr->cur++ = '0';
*print_ptr->cur++ = hex_array[uc >> 4 & 0xf];
*print_ptr->cur++ = hex_array[uc & 0xf];
}
}
#endif
continue;
}
_JSON_PRINT_SEGMENT();
*print_ptr->cur++ = '\\';
*print_ptr->cur++ = ch;
}
++str;
_JSON_PRINT_SEGMENT();
*print_ptr->cur++ = '\"';
return 0;
err:
JsonErr("malloc failed!\n");
return -1;
}
#define _JSON_PRINT_STRING(ptr, val) do { if (unlikely(_json_print_string(ptr, val) < 0)) goto err; } while(0)
static int _json_print_value(json_print_t *print_ptr, json_object *json)
{
json_object *parent = NULL, *tmp = NULL;
json_object **item_array = NULL;
int item_depth = -1, item_total = 0;
goto next3;
next1:
if (unlikely(item_depth >= item_total - 1)) {
item_total += JSON_ITEM_NUM_PLUS_DEF;
if (unlikely((item_array = json_realloc(item_array, sizeof(json_object *) * item_total)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
}
item_array[++item_depth] = json;
parent = json;
json = (json_object *)json->value.head.next;
if (parent->type_member == JSON_ARRAY) {
if (print_ptr->format_flag) {
if (json->type_member == JSON_OBJECT || json->type_member == JSON_ARRAY)
_PRINT_ADDI_FORMAT(print_ptr, item_depth + 1);
}
goto next3;
}
next2a:
if (print_ptr->format_flag) {
_PRINT_ADDI_FORMAT(print_ptr, item_depth + 1);
if (unlikely(!json->jkey.len)) {
#if !JSON_PARSE_EMPTY_KEY
JsonErr("key is empty!\n");
goto err;
#else
_PRINT_PTR_STRNCAT("\"\":\t", 4);
#endif
} else {
_JSON_PRINT_STRING(print_ptr, &json->jkey);
_PRINT_PTR_STRNCAT(":\t", 2);
}
} else {
if (unlikely(!json->jkey.len)) {
#if !JSON_PARSE_EMPTY_KEY
JsonErr("key is empty!\n");
goto err;
#else
_PRINT_PTR_STRNCAT("\"\":", 3);
#endif
} else {
_JSON_PRINT_STRING(print_ptr, &json->jkey);
_PRINT_PTR_STRNCAT(":", 1);
}
}
goto next3;
next2b:
if (print_ptr->format_flag) {
if (json->type_member == JSON_ARRAY)
_PRINT_ADDI_FORMAT(print_ptr, item_depth + 1);
else
_PRINT_PTR_STRNCAT(" ", 1);
}
next3:
switch (json->type_member) {
case JSON_NULL:
_PRINT_PTR_STRNCAT("null", 4);
break;
case JSON_BOOL:
if (json->value.vnum.vbool) {
_PRINT_PTR_STRNCAT("true", 4);
} else {
_PRINT_PTR_STRNCAT("false", 5);
}
break;
case JSON_INT:
_PRINT_PTR_NUMBER(jnum_itoa, json->value.vnum.vint);
break;
case JSON_HEX:
_PRINT_PTR_NUMBER(jnum_htoa, json->value.vnum.vhex);
break;
case JSON_LINT:
_PRINT_PTR_NUMBER(jnum_ltoa, json->value.vnum.vlint);
break;
case JSON_LHEX:
_PRINT_PTR_NUMBER(jnum_lhtoa, json->value.vnum.vlhex);
break;
case JSON_DOUBLE:
_PRINT_PTR_NUMBER(json_dtoa, json->value.vnum.vdbl);
break;
case JSON_STRING:
if (unlikely(!json->value.vstr.len)) {
_PRINT_PTR_STRNCAT("\"\"", 2);
} else {
_JSON_PRINT_STRING(print_ptr, &json->value.vstr);
}
break;
case JSON_OBJECT:
if (unlikely(json->value.head.prev == (struct json_list *)&json->value.head)) {
_PRINT_PTR_STRNCAT("{}", 2);
break;
}
_PRINT_PTR_STRNCAT("{", 1);
goto next1;
case JSON_ARRAY:
if (unlikely(json->value.head.prev == (struct json_list *)&json->value.head)) {
_PRINT_PTR_STRNCAT("[]", 2);
break;
}
_PRINT_PTR_STRNCAT("[", 1);
goto next1;
default:
break;
}
++print_ptr->item_count;
next4:
if (likely(item_depth >= 0)) {
tmp = (json_object*)(json->list.next);
if (likely(&tmp->list != (struct json_list *)&parent->value.head)) {
_PRINT_PTR_STRNCAT(",", 1);
json = tmp;
if (parent->type_member == JSON_OBJECT)
goto next2a;
else
goto next2b;
} else {
if (parent->type_member == JSON_OBJECT) {
if (print_ptr->format_flag) {
if (item_depth > 0) {
_PRINT_ADDI_FORMAT(print_ptr, item_depth);
} else {
_PRINT_PTR_STRNCAT("\n", 1);
}
}
_PRINT_PTR_STRNCAT("}", 1);
} else {
if (print_ptr->format_flag) {
if (json->type_member == JSON_OBJECT || json->type_member == JSON_ARRAY) {
if (likely(item_depth > 0)) {
_PRINT_ADDI_FORMAT(print_ptr, item_depth);
} else {
_PRINT_PTR_STRNCAT("\n", 1);
}
}
}
_PRINT_PTR_STRNCAT("]", 1);
}
++print_ptr->item_count;
if (likely(item_depth > 0)) {
json = parent;
parent = item_array[--item_depth];
goto next4;
}
}
}
if (item_array) {
json_free(item_array);
}
return 0;
err:
if (item_array) {
json_free(item_array);
}
return -1;
}
static int _print_val_release(json_print_t *print_ptr, bool free_all_flag, size_t *length)
{
#define _clear_free_ptr(ptr) do { if (ptr) json_free(ptr); ptr = NULL; } while(0)
#define _clear_close_fd(fd) do { if (fd >= 0) close(fd); fd = -1; } while(0)
int ret = 0;
size_t used = GET_BUF_USED_SIZE(print_ptr);
if (print_ptr->fd >= 0) {
if (!free_all_flag && used > 0) {
if (used != (size_t)write(print_ptr->fd, print_ptr->ptr, used)) {
JsonErr("write failed!\n");
ret = -1;
}
}
_clear_close_fd(print_ptr->fd);
_clear_free_ptr(print_ptr->ptr);
} else {
if (free_all_flag) {
_clear_free_ptr(print_ptr->ptr);
} else {
if (length)
*length = print_ptr->cur - print_ptr->ptr;
*print_ptr->cur = '\0';
print_ptr->ptr = json_realloc(print_ptr->ptr, used + 1);
}
}
return ret;
}
static int _print_val_init(json_print_t *print_ptr, json_print_choice_t *choice)
{
print_ptr->format_flag = choice->format_flag;
print_ptr->plus_size = choice->plus_size ? choice->plus_size : JSON_PRINT_SIZE_PLUS_DEF;
print_ptr->fd = -1;
if (choice->path) {
print_ptr->realloc = _print_file_ptr_realloc;
if ((print_ptr->fd = open(choice->path, O_CREAT|O_TRUNC|O_WRONLY, 0666)) < 0) {
JsonErr("open(%s) failed!\n", choice->path);
goto err;
}
print_ptr->size = print_ptr->plus_size;
} else {
size_t item_size = 0;
size_t total_size = 0;
print_ptr->realloc = _print_str_ptr_realloc;
item_size = (choice->format_flag) ? JSON_FORMAT_ITEM_SIZE_DEF : JSON_UNFORMAT_ITEM_SIZE_DEF;
if (choice->item_size > item_size)
item_size = choice->item_size;
total_size = print_ptr->item_total * item_size;
if (total_size < JSON_PRINT_SIZE_PLUS_DEF)
total_size = JSON_PRINT_SIZE_PLUS_DEF;
print_ptr->size = total_size;
}
if ((print_ptr->ptr = json_malloc(print_ptr->size)) == NULL) {
JsonErr("malloc failed!\n");
goto err;
}
print_ptr->cur = print_ptr->ptr;
return 0;
err:
_print_val_release(print_ptr, true, NULL);
return -1;
}
char *json_print_common(json_object *json, json_print_choice_t *choice)
{
json_print_t print_val = {0};
if (!json)
return NULL;
print_val.item_total = choice->item_total ? choice->item_total : JSON_PRINT_NUM_INIT_DEF;
if (_print_val_init(&print_val, choice) < 0)
return NULL;
if (_json_print_value(&print_val, json) < 0) {
JsonErr("print failed!\n");
goto err;
}
if (_print_val_release(&print_val, false, &choice->str_len) < 0)
goto err;
return choice->path ? "ok" : print_val.ptr;
err:
_print_val_release(&print_val, true, NULL);
return NULL;
}
#if JSON_SAX_APIS_SUPPORT
typedef struct {
json_type_t type;
int num;
} json_sax_print_depth_t;
typedef struct {
int total;
int count;
json_sax_print_depth_t *array;
json_print_t print_val;
json_type_t last_type;
bool error_flag;
} json_sax_print_t;
int json_sax_print_value(json_sax_print_hd handle, json_type_t type, json_string_t *jkey, const void *value)
{
json_sax_print_t *print_handle = handle;
json_print_t *print_ptr = &print_handle->print_val;
json_string_t *jstr = NULL;
int cur_pos = print_handle->count - 1;
if (unlikely(print_handle->error_flag)) {
return -1;
}
if (likely(print_handle->count > 0
&& !((type == JSON_ARRAY || type == JSON_OBJECT) && (*(json_sax_cmd_t*)value) == JSON_SAX_FINISH))) {
// add ","
if (print_handle->array[cur_pos].num > 0)
_PRINT_PTR_STRNCAT(",", 1);
// add key
if (print_handle->array[cur_pos].type == JSON_OBJECT) {
if (print_ptr->format_flag) {
if (unlikely(!jkey || !jkey->str || !jkey->str[0])) {
#if !JSON_PARSE_EMPTY_KEY
JsonErr("key is empty!\n");
goto err;
#else
_PRINT_ADDI_FORMAT(print_ptr, print_handle->count);
_PRINT_PTR_STRNCAT("\"\":\t", 4);
#endif
} else {
_PRINT_ADDI_FORMAT(print_ptr, print_handle->count);
json_string_info_update(jkey);
_JSON_PRINT_STRING(print_ptr, jkey);
_PRINT_PTR_STRNCAT(":\t", 2);
}
} else {
if (unlikely(!jkey || !jkey->str || !jkey->str[0])) {
#if !JSON_PARSE_EMPTY_KEY
JsonErr("key is empty!\n");
goto err;
#else
_PRINT_PTR_STRNCAT("\"\":", 3);
#endif
} else {
json_string_info_update(jkey);
_JSON_PRINT_STRING(print_ptr, jkey);
_PRINT_PTR_STRNCAT(":", 1);
}
}
} else {
if (print_ptr->format_flag) {
if (type == JSON_ARRAY) {
_PRINT_ADDI_FORMAT(print_ptr, print_handle->count);
} else {
if (print_handle->array[cur_pos].num > 0) {
_PRINT_PTR_STRNCAT(" ", 1);
} else {
if (type == JSON_OBJECT)
_PRINT_ADDI_FORMAT(print_ptr, print_handle->count);
}
}
}
}
}
// add value
switch (type) {
case JSON_NULL:
_PRINT_PTR_STRNCAT("null", 4);
break;
case JSON_BOOL:
if ((*(bool*)value)) {
_PRINT_PTR_STRNCAT("true", 4);
} else {
_PRINT_PTR_STRNCAT("false", 5);
}
break;
case JSON_INT:
_PRINT_PTR_NUMBER(jnum_itoa, *(int32_t*)value);
break;
case JSON_HEX:
_PRINT_PTR_NUMBER(jnum_htoa, *(uint32_t*)value);
break;
case JSON_LINT:
_PRINT_PTR_NUMBER(jnum_ltoa, *(int64_t*)value);
break;
case JSON_LHEX:
_PRINT_PTR_NUMBER(jnum_lhtoa, *(uint64_t*)value);
break;
case JSON_DOUBLE:
_PRINT_PTR_NUMBER(json_dtoa, *(double*)value);
break;
case JSON_STRING:
jstr = (json_string_t*)value;
if (unlikely(!jstr || !jstr->str || !jstr->str[0])) {
_PRINT_PTR_STRNCAT("\"\"", 2);
} else {
json_string_info_update(jstr);
_JSON_PRINT_STRING(print_ptr, jstr);
}
break;
case JSON_ARRAY:
case JSON_OBJECT:
switch ((*(json_sax_cmd_t*)value)) {
case JSON_SAX_START:
if (unlikely(print_handle->count == print_handle->total)) {
print_handle->total += JSON_PRINT_DEPTH_DEF;
if (unlikely((print_handle->array = json_realloc(print_handle->array,
print_handle->total * sizeof(json_sax_print_depth_t))) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
}
if (type == JSON_OBJECT) {
_PRINT_PTR_STRNCAT("{", 1);
} else {
_PRINT_PTR_STRNCAT("[", 1);
}
if (print_handle->count > 0)
++print_handle->array[cur_pos].num;
print_handle->array[print_handle->count].type = type;
print_handle->array[print_handle->count].num = 0;
++print_handle->count;
break;
case JSON_SAX_FINISH:
if (unlikely(print_handle->count == 0 || print_handle->array[cur_pos].type != type)) {
JsonErr("unexpected array or object finish!\n");
goto err;
}
if (print_ptr->format_flag) {
if (print_handle->count > 1) {
if (print_handle->array[print_handle->count-1].num > 0) {
if (type == JSON_OBJECT) {
_PRINT_ADDI_FORMAT(print_ptr, cur_pos);
} else {
if (print_handle->last_type == JSON_OBJECT || print_handle->last_type == JSON_ARRAY)
_PRINT_ADDI_FORMAT(print_ptr, cur_pos);
}
}
} else {
_PRINT_PTR_STRNCAT("\n", 1);
}
}
if (type == JSON_OBJECT) {
_PRINT_PTR_STRNCAT("}", 1);
} else {
_PRINT_PTR_STRNCAT("]", 1);
}
--print_handle->count;
print_handle->last_type = type;
return 0;
default:
goto err;
}
break;
default:
goto err;
}
print_handle->last_type = type;
if (cur_pos >= 0)
++print_handle->array[cur_pos].num;
++print_ptr->item_count;
return 0;
err:
print_handle->error_flag = true;
return -1;
}
json_sax_print_hd json_sax_print_start(json_print_choice_t *choice)
{
json_sax_print_t *print_handle = NULL;
if ((print_handle = json_calloc(1, sizeof(json_sax_print_t))) == NULL) {
JsonErr("malloc failed!\n");
return NULL;
}
if (choice->item_total == 0)
choice->item_total = JSON_PRINT_NUM_INIT_DEF;
if (_print_val_init(&print_handle->print_val, choice) < 0) {
json_free(print_handle);
return NULL;
}
print_handle->total = JSON_PRINT_DEPTH_DEF;
if ((print_handle->array = json_malloc(print_handle->total * sizeof(json_sax_print_depth_t))) == NULL) {
_print_val_release(&print_handle->print_val, true, NULL);
json_free(print_handle);
JsonErr("malloc failed!\n");
return NULL;
}
return print_handle;
}
char *json_sax_print_finish(json_sax_print_hd handle, size_t *length)
{
char *ret = NULL;
json_sax_print_t *print_handle = handle;
if (!print_handle)
return NULL;
if (print_handle->array)
json_free(print_handle->array);
if (print_handle->error_flag) {
_print_val_release(&print_handle->print_val, true, NULL);
json_free(print_handle);
return NULL;
}
ret = (print_handle->print_val.fd >= 0) ? "ok" : print_handle->print_val.ptr;
if (_print_val_release(&print_handle->print_val, false, length) < 0) {
json_free(print_handle);
return NULL;
}
json_free(print_handle);
return ret;
}
#endif
typedef struct _json_parse_t {
int fd;
size_t size;
size_t offset;
size_t readed;
size_t read_size;
bool reuse_flag;
char *str;
json_mem_t *mem;
void (*skip_blank)(struct _json_parse_t *parse_ptr);
int (*parse_string)(struct _json_parse_t *parse_ptr, char end_ch, json_string_t *jstr, json_mem_mgr_t *mgr);
int (*parse_value)(struct _json_parse_t *parse_ptr, json_object **root);
#if JSON_SAX_APIS_SUPPORT
json_sax_parser_t parser;
json_sax_cb_t cb;
json_sax_ret_t ret;
#endif
} json_parse_t;
#define IS_BLANK(c) ((((c) + 0xdf) & 0xff) > 0xdf)
static inline void *_parse_alloc(json_parse_t *parse_ptr, size_t size, json_mem_mgr_t *mgr)
{
if (parse_ptr->mem == &s_invalid_json_mem)
return json_malloc(size);
return pjson_memory_alloc(size, mgr);
}
static int _get_file_parse_ptr(json_parse_t *parse_ptr, int read_offset, size_t read_size, char **sstr)
{
size_t offset = 0;
ssize_t size = 0, rsize = 0;
offset = parse_ptr->offset + read_offset;
size = parse_ptr->readed - offset;
if (likely(offset + read_size <= parse_ptr->readed)) {
*sstr = parse_ptr->str + offset;
} else if (parse_ptr->read_size == 0) {
if (size >= 0) {
*sstr = parse_ptr->str + offset;
} else {
*sstr = JSON_PARSE_ERROR_STR; /* Reduce the judgment pointer is NULL. */
size = 0;
}
} else {
size = parse_ptr->readed - parse_ptr->offset;
if (size && parse_ptr->offset)
memmove(parse_ptr->str, parse_ptr->str + parse_ptr->offset, size);
parse_ptr->offset = 0;
parse_ptr->readed = size;
if (read_size > parse_ptr->size) {
while (read_size > parse_ptr->size)
parse_ptr->size += parse_ptr->read_size;
if ((parse_ptr->str = json_realloc(parse_ptr->str, parse_ptr->size + 1)) == NULL) {
JsonErr("malloc failed!\n");
*sstr = JSON_PARSE_ERROR_STR; /* Reduce the judgment pointer is NULL. */
return 0;
}
}
size = parse_ptr->size - parse_ptr->readed;
if ((rsize = read(parse_ptr->fd, parse_ptr->str + parse_ptr->readed, size)) != size)
parse_ptr->read_size = 0; /* finish readding file */
parse_ptr->readed += rsize < 0 ? 0 : rsize;
parse_ptr->str[parse_ptr->readed] = '\0';
*sstr = parse_ptr->str + read_offset;
size = parse_ptr->readed - read_offset;
}
return size;
}
static inline int _get_str_parse_ptr(json_parse_t *parse_ptr, int read_offset, size_t read_size UNUSED_ATTR, char **sstr)
{
size_t offset = parse_ptr->offset + read_offset;
*sstr = parse_ptr->str + offset;
return (parse_ptr->size - offset);
}
static inline int _get_parse_ptr(json_parse_t *parse_ptr, int read_offset, size_t read_size, char **sstr)
{
if (parse_ptr->fd >= 0)
return _get_file_parse_ptr(parse_ptr, read_offset, read_size, sstr);
return _get_str_parse_ptr(parse_ptr, read_offset, read_size, sstr);
}
#define _UPDATE_PARSE_OFFSET(add_offset) parse_ptr->offset += add_offset
#if JSON_PARSE_HEX_NUM
static json_type_t _parse_hex(const char **sstr, json_number_t *value)
{
json_type_t type = JSON_NULL;
const char *s = *sstr;
char c;
uint64_t m = 0;
s += 2;
while ((s - *sstr) < 18) {
switch ((c = *s)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c -= '0';
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
c -= 'a' - 10;
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
c -= 'A' - 10;
break;
default:
goto end;
}
m = (m << 4) + c;
++s;
}
end:
if (s - *sstr == 2) {
value->vhex = 0;
JsonErr("Not HEX!\n");
return JSON_NULL;
}
if (m > 4294967295U /*UINT_MAX*/) {
type = JSON_LHEX;
value->vlhex = m;
} else {
type = JSON_HEX;
value->vhex = (uint32_t)m;
}
*sstr = s;
return type;
}
#endif
static int _parse_num(const char **sstr, json_number_t *value)
{
static const double div10_lut[20] = {
1 , 1e-1 , 1e-2 , 1e-3 , 1e-4 , 1e-5 , 1e-6 , 1e-7 , 1e-8 , 1e-9 ,
1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19,
};
static const double mul10_lut[20] = {
1 , 1e1 , 1e2 , 1e3 , 1e4 , 1e5 , 1e6 , 1e7 , 1e8 , 1e9 ,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
};
const char *s = *sstr;
json_type_t type;
int32_t sign = 1, k = 0;
uint64_t m = 0;
double d = 0;
switch (*s) {
case '-': ++s; sign = -1; break;
case '+': ++s; break;
default: break;
}
#if !JSON_PARSE_SPECIAL_NUM
switch (*s) {
case '0':
switch (*(s + 1)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'e': case 'E':
JsonErr("Leading 0 is not allowed in standard json!\n");
return JSON_NULL; /* Just use it to indicate error */
default:
break;
}
break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
case '.':
JsonErr("The integer part of double cannot be omitted in standard json!\n");
break;
default:
JsonErr("Not number char (%c)!\n", *s);
return JSON_NULL;
}
#else
switch (*s) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
break;
default:
JsonErr("Not number char (%c)!\n", *s);
return JSON_NULL;
}
#endif
while (*s == '0')
++s;
while (*s >= '0' && *s <= '9') {
m = (m << 3) + (m << 1) + (*s++ - '0');
++k;
}
if (k < 20) {
switch (*s) {
case 'e': case 'E':
d = m;
goto next4;
case '.':
d = m;
goto next2;
default:
goto next1;
}
} else {
s -= k;
while (1) {
m = 0;
k = 0;
while (*s >= '0' && *s <= '9') {
m = (m << 3) + (m << 1) + (*s++ - '0');
++k;
if (k == 19)
break;
}
d = d * mul10_lut[k] + m;
switch (*s) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
case 'e': case 'E':
goto next4;
case '.':
goto next2;
default:
goto next3;
}
}
}
next1:
if (m <= 2147483647U /*INT_MAX*/) {
type = JSON_INT;
value->vint = sign == 1 ? (int32_t)m : -((int32_t)m);
} else if (m <= 9223372036854775807U /*LLONG_MAX*/) {
type = JSON_LINT;
value->vlint = sign == 1 ? (int64_t)m : -((int64_t)m);
} else {
if (m == 9223372036854775808U && sign == -1) {
type = JSON_LINT;
value->vlint = -m;
} else {
type = JSON_DOUBLE;
value->vdbl = sign == 1 ? (double)m : -((double)m);
}
}
*sstr = s;
return type;
next2:
++s;
#if !JSON_PARSE_SPECIAL_NUM
switch (*s) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
default:
JsonErr("The decimal part of double cannot be omitted in standard json!\n");
return JSON_NULL;
}
#endif
m = 0;
k = 0;
while (*s >= '0' && *s <= '9') {
m = (m << 3) + (m << 1) + (*s++ - '0');
++k;
}
if (k < 20) {
d += m * div10_lut[k];
} else {
s -= k;
m = 0;
k = 0;
while (*s >= '0' && *s <= '9') {
m = (m << 3) + (m << 1) + (*s++ - '0');
++k;
if (k == 19)
break;
}
d += m * div10_lut[k];
while (*s >= '0' && *s <= '9')
++s;
}
switch (*s) {
case 'e': case 'E':
goto next4;
default:
break;
}
next3:
type = JSON_DOUBLE;
value->vdbl = sign == 1 ? d : -d;
*sstr = s;
return type;
next4:
type = JSON_BOOL; /* Only used to mark exponential */
value->vdbl = sign == 1 ? d : -d;
*sstr = s;
return type;
}
static inline json_type_t _json_parse_number(const char **sstr, json_number_t *vnum)
{
const char *s = *sstr;
if (unlikely(*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X'))) {
#if !JSON_PARSE_HEX_NUM
JsonErr("HEX can't be parsed in standard json!\n");
return JSON_NULL;
#else
return _parse_hex(sstr, vnum);
#endif
}
json_number_t e;
json_type_t type = _parse_num(sstr, vnum);
switch (type) {
case JSON_NULL:
return JSON_NULL;
case JSON_BOOL:
++*sstr;
type = _parse_num(sstr, &e);
switch (type) {
case JSON_INT: vnum->vdbl *= pow(10, e.vint); break;
case JSON_LINT: vnum->vdbl *= pow(10, e.vlint); break;
case JSON_DOUBLE: vnum->vdbl *= pow(10, e.vdbl); break;
default: return JSON_NULL;
}
type = JSON_DOUBLE;
break;
default:
break;
}
return type;
}
static inline uint32_t _parse_hex4(const unsigned char *str)
{
int i = 0;
uint32_t val = 0;
for (i = 0; i < 4; ++i) {
switch (str[i]) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
val = (val << 4) + (str[i] - '0');
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
val = (val << 4) + 10 + (str[i] - 'a');
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
val = (val << 4) + 10 + (str[i] - 'A');
break;
default:
return 0;
}
}
return val;
}
static int utf16_literal_to_utf8(const unsigned char *start_str, const unsigned char *finish_str, unsigned char **pptr)
{ /* copy from cJSON */
const unsigned char *str = start_str;
unsigned char *ptr = *pptr;
int seq_len = 0;
int i = 0;
unsigned long uc = 0;
unsigned int uc1 = 0, uc2 = 0;
unsigned char len = 0;
unsigned char first_byte_mark = 0;
/* converts a UTF-16 literal to UTF-8, A literal can be one or two sequences of the form \uXXXX */
if ((finish_str - str) < 6) /* input ends unexpectedly */
goto fail;
str += 2;
uc1 = _parse_hex4(str); /* get the first utf16 sequence */
if (((uc1 >= 0xDC00) && (uc1 <= 0xDFFF))) /* check first_code is valid */
goto fail;
if ((uc1 >= 0xD800) && (uc1 <= 0xDBFF)) { /* UTF16 surrogate pair */
str += 4;
seq_len = 12; /* \uXXXX\uXXXX */
if ((finish_str - str) < 6) /* input ends unexpectedly */
goto fail;
if ((str[0] != '\\') || (str[1] != 'u')) /* missing second half of the surrogate pair */
goto fail;
str += 2;
uc2 = _parse_hex4(str); /* get the second utf16 sequence */
if ((uc2 < 0xDC00) || (uc2 > 0xDFFF)) /* check second_code is valid */
goto fail;
uc = 0x10000 + (((uc1 & 0x3FF) << 10) | (uc2 & 0x3FF)); /* calculate the unicode uc from the surrogate pair */
} else {
seq_len = 6; /* \uXXXX */
uc = uc1;
}
/* encode as UTF-8 takes at maximum 4 bytes to encode: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
if (uc < 0x80) { /* normal ascii, encoding 0xxxxxxx */
len = 1;
} else if (uc < 0x800) { /* two bytes, encoding 110xxxxx 10xxxxxx */
len = 2;
first_byte_mark = 0xC0; /* 11000000 */
} else if (uc < 0x10000) { /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
len = 3;
first_byte_mark = 0xE0; /* 11100000 */
} else if (uc <= 0x10FFFF) { /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
len = 4;
first_byte_mark = 0xF0; /* 11110000 */
} else { /* invalid unicode */
goto fail;
}
for (i = len - 1; i > 0; --i) { /* encode as utf8 */
ptr[i] = (unsigned char)((uc | 0x80) & 0xBF); /* 10xxxxxx */
uc >>= 6;
}
if (len > 1) { /* encode first byte */
ptr[0] = (unsigned char)((uc | first_byte_mark) & 0xFF);
} else {
ptr[0] = (unsigned char)(uc & 0x7F);
}
*pptr += len;
return seq_len;
fail:
return 0;
}
#if JSON_PARSE_SKIP_COMMENT
static bool _skip_comment(json_parse_t *parse_ptr, int *pcnt)
{
char *str = NULL;
int cnt = 0;
if (_get_parse_ptr(parse_ptr, *pcnt, 64, &str) == 1)
goto end;
switch (*(str + 1)) {
case '/':
str += 2;
*pcnt += 2;
while (1) {
switch (*str) {
case '\n':
++str;
++*pcnt;
goto next;
case '\0':
if (_get_parse_ptr(parse_ptr, *pcnt, 64, &str) == 0)
goto end;
break;
default:
++str;
++*pcnt;
break;
}
}
break;
case '*':
cnt = 2;
str += 2;
while (1) {
switch (*str) {
case '*':
switch (*(str + 1)) {
case '/':
str += 2;
cnt += 2;
*pcnt += cnt;
goto next;
case '\0':
if (_get_parse_ptr(parse_ptr, *pcnt + cnt, 64, (char **)&str) == 1)
goto end;
if (*(str + 1) == '/') {
str += 2;
cnt += 2;
*pcnt += cnt;
goto next;
} else {
++str;
++cnt;
}
break;
default:
++str;
++cnt;
break;
}
break;
case '\0':
if (_get_parse_ptr(parse_ptr, *pcnt + cnt, 64, (char **)&str) == 0)
goto end;
break;
default:
++str;
++cnt;
break;
}
}
break;
default:
goto end;
}
next:
return false;
end:
return true;
}
#endif
static inline void _skip_blank(json_parse_t *parse_ptr)
{
unsigned char *str = NULL;
int cnt = 0;
while (_get_parse_ptr(parse_ptr, cnt, 64, (char **)&str)) {
while (IS_BLANK(*str)) {
++str;
++cnt;
}
if (likely(*str)) {
#if JSON_PARSE_SKIP_COMMENT
if (unlikely(*str == '/')) {
if (!_skip_comment(parse_ptr, &cnt))
continue;
}
#endif
break;
}
}
_UPDATE_PARSE_OFFSET(cnt);
}
static int _parse_strcpy(char *ptr, const char *str, int nsize)
{
const char *bak = ptr, *last = str, *end = str + nsize;
char ch = '\0';
int size = 0, seq_len = 0;
while (str < end) {
if (unlikely(*str++ == '\\')) {
switch ((*str++)) {
case 'b' : ch = '\b'; break;
case 'f' : ch = '\f'; break;
case 'n' : ch = '\n'; break;
case 'r' : ch = '\r'; break;
case 't' : ch = '\t'; break;
case 'v' : ch = '\v'; break;
case '\"': ch = '\"'; break;
case '\'': ch = '\''; break;
case '\\': ch = '\\'; break;
case '/' : ch = '/' ; break;
#if JSON_PARSE_SPECIAL_CHAR
case '\r':
size = str - last - 2;
memcpy(ptr, last, size);
ptr += size;
if (*str == '\n')
++str;
last = str;
continue;
case '\n':
size = str - last - 2;
memcpy(ptr, last, size);
ptr += size;
last = str;
continue;
#endif
case 'u' :
str -= 2;
size = str - last;
memcpy(ptr, last, size);
ptr += size;
if (unlikely((seq_len = utf16_literal_to_utf8((unsigned char*)str,
(unsigned char*)end, (unsigned char**)&ptr)) == 0)) {
JsonErr("invalid utf16 code(\\u%c)!\n", str[2]);
return -1;
}
str += seq_len;
last = str;
continue;
default :
JsonErr("invalid escape character(\\%c)!\n", str[1]);
return -1;
}
size = str - last - 2;
memcpy(ptr, last, size);
ptr += size;
*ptr++ = ch;
last = str;
}
}
size = str - last;
memcpy(ptr, last, size);
ptr += size;
*ptr = '\0';
return ptr - bak;
}
static int _parse_strlen(json_parse_t *parse_ptr, char end_ch UNUSED_END_CH, int *escaped)
{
#define PARSE_READ_SIZE 128
char *str = NULL, *bak = NULL;
int total = 0, rsize = 0;
char c = '\0';
_get_parse_ptr(parse_ptr, 0, PARSE_READ_SIZE, &str);
bak = str;
while (1) {
switch ((c = *str++)) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
case ':':
if (c == end_ch)
#endif
{
total += str - bak - 1;
return total;
}
#if JSON_PARSE_SPECIAL_QUOTES
if (c == '\"' && !*escaped)
*escaped = -1;
break;
#endif
case '\\':
if (likely(rsize != (str - bak))) {
++str;
*escaped = 1;
} else {
--str;
total += str - bak;
if (unlikely((rsize = _get_parse_ptr(parse_ptr, total, PARSE_READ_SIZE, &str)) < 2)) {
JsonErr("last char is slash!\n");
goto err;
}
bak = str;
}
break;
case '\0':
--str;
total += str - bak;
if (unlikely((rsize = _get_parse_ptr(parse_ptr, total, PARSE_READ_SIZE, &str)) < 1)) {
JsonErr("No more string!\n");
goto err;
}
bak = str;
break;
#if !JSON_PARSE_SPECIAL_CHAR
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in standard json!\n");
goto err;
#endif
default:
break;
}
}
err:
JsonPareseErr("str format err!");
return -1;
}
static int _json_parse_string(json_parse_t *parse_ptr, char end_ch, json_string_t *jstr, json_mem_mgr_t *mgr)
{
char *ptr = NULL, *str = NULL;
int escaped = 0;
int len = 0, total = 0;
memset(jstr, 0, sizeof(json_string_t));
if (unlikely((total = _parse_strlen(parse_ptr, end_ch, &escaped)) < 0)) {
return -1;
}
len = total;
_get_parse_ptr(parse_ptr, 0, total, &str);
if (unlikely((ptr = _parse_alloc(parse_ptr, len + 1, mgr)) == NULL)) {
JsonErr("malloc failed!\n");
return -1;
}
if (likely(escaped != 1)) {
memcpy(ptr, str, len);
ptr[len] = '\0';
} else {
if (unlikely((len = _parse_strcpy(ptr, str, len)) < 0)) {
JsonErr("_parse_strcpy failed!\n");
if (parse_ptr->mem == &s_invalid_json_mem)
json_free(ptr);
goto err;
}
}
_UPDATE_PARSE_OFFSET(total);
jstr->escaped = escaped != 0;
jstr->len = len;
jstr->str = ptr;
return len;
err:
JsonPareseErr("parse string failed!");
return -1;
}
static int _json_parse_key(json_parse_t *parse_ptr, json_string_t *jkey)
{
char *str = NULL;
char end_ch = '\"';
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 2, &str);
switch (*str) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
#endif
if (unlikely(str[1] == str[0])) {
#if !JSON_PARSE_EMPTY_KEY
JsonPareseErr("key is empty!");
goto err;
#else
_UPDATE_PARSE_OFFSET(2);
#endif
} else {
end_ch = *str;
_UPDATE_PARSE_OFFSET(1);
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
}
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (unlikely(*str != ':')) {
JsonPareseErr("key is not before ':'");
goto err;
}
_UPDATE_PARSE_OFFSET(1);
break;
default:
#if JSON_PARSE_SPECIAL_QUOTES
if (unlikely(*str == ':')) {
#if !JSON_PARSE_EMPTY_KEY
JsonPareseErr("key is empty!");
goto err;
#else
_UPDATE_PARSE_OFFSET(1);
#endif
} else {
end_ch = ':';
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
while (IS_BLANK((unsigned char)jkey->str[jkey->len - 1]))
--jkey->len;
jkey->str[jkey->len] = '\0';
}
break;
#else
JsonPareseErr("key is not started with quotes!");
goto err;
#endif
}
return 0;
err:
return -1;
}
static int _json_parse_single_value(json_parse_t *parse_ptr, char *str, json_string_t *jkey, json_value_t *value)
{
char end_ch = '\"';
char *bak = NULL;
switch (*str) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
#endif
jkey->type = JSON_STRING;
if (unlikely(str[1] == str[0])) {
memset(&value->vstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(2);
} else {
end_ch = *str;
_UPDATE_PARSE_OFFSET(1);
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, &value->vstr, &parse_ptr->mem->str_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
}
break;
#if JSON_PARSE_SPECIAL_NUM
case '+':
#endif
case '-':
#if JSON_PARSE_SPECIAL_DOUBLE
if (strncmp("Infinity", str + 1, 8) == 0) {
jkey->type = JSON_DOUBLE;
value->vnum.vlhex = (*str == '-' ? 0xFFF0000000000000 : 0x7FF0000000000000);
_UPDATE_PARSE_OFFSET(9);
break;
}
FALLTHROUGH_ATTR;
#endif
#if JSON_PARSE_SPECIAL_NUM
case '.':
#endif
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
bak = str;
if (unlikely((jkey->type = _json_parse_number((const char **)&str, &value->vnum)) == JSON_NULL)) {
JsonPareseErr("Not number!");
goto err;
}
_UPDATE_PARSE_OFFSET(str - bak);
break;
case 'f':
if (likely(parse_ptr->size - parse_ptr->offset >= 5 && memcmp("false", str, 5) == 0)) {
jkey->type = JSON_BOOL;
value->vnum.vbool = false;
_UPDATE_PARSE_OFFSET(5);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 't':
if (likely(parse_ptr->size - parse_ptr->offset >= 4 && memcmp("true", str, 4) == 0)) {
jkey->type = JSON_BOOL;
value->vnum.vbool = true;
_UPDATE_PARSE_OFFSET(4);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 'n':
if (likely(parse_ptr->size - parse_ptr->offset >= 4 && memcmp("null", str, 4) == 0)) {
jkey->type = JSON_NULL;
_UPDATE_PARSE_OFFSET(4);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
#if JSON_PARSE_SPECIAL_DOUBLE
case 'N':
if (likely(parse_ptr->size - parse_ptr->offset >= 3 && memcmp("NaN", str, 3) == 0)) {
jkey->type = JSON_DOUBLE;
value->vnum.vlhex = 0x7FF0000000000001;
_UPDATE_PARSE_OFFSET(3);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 'I':
if (likely(parse_ptr->size - parse_ptr->offset >= 8 && memcmp("Infinity", str, 8) == 0)) {
jkey->type = JSON_DOUBLE;
value->vnum.vlhex = 0x7FF0000000000000;
_UPDATE_PARSE_OFFSET(8);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
#endif
default:
JsonPareseErr("invalid next ptr!");
goto err;
}
return 0;
err:
return -1;
}
static int _json_parse_value(json_parse_t *parse_ptr, json_object **root)
{
json_string_t jkey = {0};
char *str = NULL;
json_object *item = NULL, *parent = NULL;
json_object **item_array = NULL;
int item_depth = -1, item_total = 0;
goto next3;
next1:
if (unlikely(item_depth >= item_total - 1)) {
item_total += JSON_ITEM_NUM_PLUS_DEF;
if (unlikely((item_array = json_realloc(item_array, sizeof(json_object *) * item_total)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
}
item_array[++item_depth] = item;
parent = item;
*root = *item_array;
if (parent->type_member == JSON_ARRAY)
goto next3;
next2:
if (unlikely(_json_parse_key(parse_ptr, &jkey) < 0)) {
goto err;
}
next3:
if (unlikely((item = _parse_alloc(parse_ptr, sizeof(json_object), &parse_ptr->mem->obj_mgr)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
memcpy(&item->jkey, &jkey, sizeof(json_string_t));
memset(&jkey, 0, sizeof(json_string_t));
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 128, &str);
switch (*str) {
case '{':
item->type_member = JSON_OBJECT;
INIT_JSON_LIST_HEAD(&item->value.head);
_UPDATE_PARSE_OFFSET(1);
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (likely(*str != '}')) {
if (parent)
json_list_add_tail(&item->list, &parent->value.head);
goto next1;
} else {
_UPDATE_PARSE_OFFSET(1);
}
break;
case '[':
item->type_member = JSON_ARRAY;
INIT_JSON_LIST_HEAD(&item->value.head);
_UPDATE_PARSE_OFFSET(1);
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (likely(*str != ']')) {
if (parent)
json_list_add_tail(&item->list, &parent->value.head);
goto next1;
} else {
_UPDATE_PARSE_OFFSET(1);
}
break;
default:
if (_json_parse_single_value(parse_ptr, str, &item->jkey, &item->value) < 0)
goto err;
break;
}
if (parent) {
json_list_add_tail(&item->list, &parent->value.head);
item = NULL;
}
next4:
if (likely(item_depth >= 0)) {
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (parent->type_member == JSON_OBJECT) {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next2;
#else
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (*str != '}')
goto next2;
FALLTHROUGH_ATTR;
#endif
case '}':
_UPDATE_PARSE_OFFSET(1);
if (likely(item_depth > 0)) {
parent = item_array[--item_depth];
goto next4;
}
break;
default:
JsonPareseErr("invalid object!");
goto err;
}
} else {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next3;
#else
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (*str != ']')
goto next3;
FALLTHROUGH_ATTR;
#endif
case ']':
_UPDATE_PARSE_OFFSET(1);
if (likely(item_depth > 0)) {
parent = item_array[--item_depth];
goto next4;
}
break;
default:
JsonPareseErr("invalid array!");
goto err;
}
}
}
if (item_array) {
*root = *item_array;
json_free(item_array);
} else {
*root = item;
}
return 0;
err:
if (item_array) {
*root = *item_array;
json_free(item_array);
} else {
if (!(*root)) {
*root = item;
item = NULL;
}
}
if (parse_ptr->mem == &s_invalid_json_mem) {
if (item)
json_free(item);
if (jkey.str)
json_free(jkey.str);
}
return -1;
}
#if JSON_PARSE_SKIP_COMMENT
static bool _skip_comment_rapid(json_parse_t *parse_ptr, int *pcnt)
{
char *str = parse_ptr->str + parse_ptr->offset + *pcnt;
int cnt = 0;
switch (*(str + 1)) {
case '/':
str += 2;
*pcnt += 2;
while (1) {
switch (*str) {
case '\n':
++str;
++*pcnt;
goto next;
case '\0':
goto end;
default:
++str;
++*pcnt;
break;
}
}
break;
case '*':
cnt = 2;
str += 2;
while (1) {
switch (*str) {
case '*':
if (*(str + 1) == '/') {
str += 2;
cnt += 2;
*pcnt += cnt;
goto next;
} else {
++str;
++cnt;
}
break;
case '\0':
goto end;
default:
++str;
++cnt;
break;
}
}
break;
default:
goto end;
}
next:
return false;
end:
return true;
}
#endif
static inline void _skip_blank_rapid(json_parse_t *parse_ptr)
{
unsigned char *str, *bak;
#if JSON_PARSE_SKIP_COMMENT
next:
#endif
str = (unsigned char *)(parse_ptr->str + parse_ptr->offset);
bak = str;
while (IS_BLANK(*str))
++str;
_UPDATE_PARSE_OFFSET(str - bak);
#if JSON_PARSE_SKIP_COMMENT
if (unlikely(*str == '/')) {
int cnt = 0;
if (!_skip_comment_rapid(parse_ptr, &cnt)) {
_UPDATE_PARSE_OFFSET(cnt);
goto next;
}
_UPDATE_PARSE_OFFSET(cnt);
}
#endif
}
static int _json_parse_string_reuse(json_parse_t *parse_ptr, char end_ch UNUSED_END_CH, json_string_t *jstr, json_mem_mgr_t *mgr UNUSED_ATTR)
{
char *str = NULL, *end = NULL, *last = NULL, *bak = NULL, *ptr= NULL;
int len = 0, seq_len = 0, size = 0;
char c = '\0', ch = '\0';
int escaped = 0;
memset(jstr, 0, sizeof(json_string_t));
end = parse_ptr->str + parse_ptr->size;
str = parse_ptr->str + parse_ptr->offset;
bak = str;
ptr = str;
jstr->str = str;
while (1) {
switch ((c = *str++)) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
case ':':
if (c == end_ch)
#endif
{
len = str - bak - 1;
_UPDATE_PARSE_OFFSET(len);
ptr[len] = '\0';
jstr->escaped = escaped != 0;
jstr->len = len;
return len;
}
#if JSON_PARSE_SPECIAL_QUOTES
if (c == '\"' && !escaped)
escaped = -1;
break;
#endif
case '\0':
goto err;
case '\\':
--str;
last = str;
ptr += str - bak;
goto next;
#if !JSON_PARSE_SPECIAL_CHAR
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in standard json!\n");
goto err;
#endif
default:
break;
}
}
next:
while (1) {
switch ((c = *str++)) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
case ':':
if (c == end_ch)
#endif
{
size = str - last - 1;
memmove(ptr, last, size);
ptr += size;
*ptr = '\0';
len = str - bak - 1;
_UPDATE_PARSE_OFFSET(len);
jstr->escaped = 1;
jstr->len = ptr - bak;
return jstr->len;
}
break;
case '\0':
goto err;
case '\\':
switch ((*str++)) {
case 'b' : ch = '\b'; break;
case 'f' : ch = '\f'; break;
case 'n' : ch = '\n'; break;
case 'r' : ch = '\r'; break;
case 't' : ch = '\t'; break;
case 'v' : ch = '\v'; break;
case '\"': ch = '\"'; break;
case '\'': ch = '\''; break;
case '\\': ch = '\\'; break;
case '/' : ch = '/' ; break;
#if JSON_PARSE_SPECIAL_CHAR
case '\r':
size = str - last - 2;
memmove(ptr, last, size);
ptr += size;
if (*str == '\n')
++str;
last = str;
continue;
case '\n':
size = str - last - 2;
memmove(ptr, last, size);
ptr += size;
last = str;
continue;
#endif
case 'u' :
str -= 2;
size = str - last;
memmove(ptr, last, size);
ptr += size;
if (unlikely((seq_len = utf16_literal_to_utf8((unsigned char*)str,
(unsigned char*)end, (unsigned char**)&ptr)) == 0)) {
JsonErr("invalid utf16 code(\\u%c)!\n", str[2]);
goto err;
}
str += seq_len;
last = str;
continue;
default :
JsonErr("invalid escape character(\\%c)!\n", str[1]);
goto err;
}
size = str - last - 2;
memmove(ptr, last, size);
ptr += size;
*ptr++ = ch;
last = str;
break;
#if !JSON_PARSE_SPECIAL_CHAR
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in standard json!\n");
goto err;
#endif
default:
break;
}
}
err:
memset(jstr, 0, sizeof(json_string_t));
JsonPareseErr("parse string failed!");
return -1;
}
static int _json_parse_string_rapid(json_parse_t *parse_ptr, char end_ch UNUSED_END_CH, json_string_t *jstr, json_mem_mgr_t *mgr)
{
char *str = NULL, *bak = NULL, *ptr= NULL;
char c = '\0';
int len = 0, total = 0;
int escaped = 0;
memset(jstr, 0, sizeof(json_string_t));
str = parse_ptr->str + parse_ptr->offset;
bak = str;
while (1) {
switch ((c = *str++)) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
case ':':
if (c == end_ch)
#endif
{
goto next;
}
#if JSON_PARSE_SPECIAL_QUOTES
if (c == '\"' && !escaped)
escaped = -1;
break;
#endif
case '\0':
goto err;
case '\\':
++str;
escaped = 1;
break;
#if !JSON_PARSE_SPECIAL_CHAR
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in standard json!\n");
goto err;
#endif
default:
break;
}
}
next:
total = str - bak - 1;
len = total;
if (unlikely((ptr = _parse_alloc(parse_ptr, len + 1, mgr)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
if (likely(escaped != 1)) {
memcpy(ptr, bak, len);
ptr[len] = '\0';
} else {
if (unlikely((len = _parse_strcpy(ptr, bak, len)) < 0)) {
JsonErr("_parse_strcpy failed!\n");
if (parse_ptr->mem == &s_invalid_json_mem)
json_free(ptr);
goto err;
}
}
_UPDATE_PARSE_OFFSET(total);
jstr->escaped = escaped != 0;
jstr->len = len;
jstr->str = ptr;
return len;
err:
JsonPareseErr("parse string failed!");
return -1;
}
static int _json_parse_value_rapid(json_parse_t *parse_ptr, json_object **root)
{
json_string_t jkey = {0};
char *str = NULL, *bak = NULL;
char end_ch = '\"';
json_object *item = NULL, *parent = NULL;
json_object **item_array = NULL;
int item_depth = -1, item_total = 0;
goto next3;
next1:
if (unlikely(item_depth >= item_total - 1)) {
item_total += JSON_ITEM_NUM_PLUS_DEF;
if (unlikely((item_array = json_realloc(item_array, sizeof(json_object *) * item_total)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
}
item_array[++item_depth] = item;
parent = item;
*root = *item_array;
if (parent->type_member == JSON_ARRAY)
goto next3;
next2:
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
switch (*str) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
#endif
if (unlikely(str[1] == str[0])) {
#if !JSON_PARSE_EMPTY_KEY
JsonPareseErr("key is empty!");
goto err;
#else
_UPDATE_PARSE_OFFSET(2);
#endif
} else {
end_ch = *str;
_UPDATE_PARSE_OFFSET(1);
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, &jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
}
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (unlikely(*str != ':')) {
JsonPareseErr("key is not before ':'");
goto err;
}
_UPDATE_PARSE_OFFSET(1);
break;
default:
#if JSON_PARSE_SPECIAL_QUOTES
if (unlikely(*str == ':')) {
#if !JSON_PARSE_EMPTY_KEY
JsonPareseErr("key is empty!");
goto err;
#else
_UPDATE_PARSE_OFFSET(1);
#endif
} else {
end_ch = ':';
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, &jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
while (IS_BLANK((unsigned char)jkey.str[jkey.len - 1]))
--jkey.len;
jkey.str[jkey.len] = '\0';
}
break;
#else
JsonPareseErr("key is not started with quotes!");
goto err;
#endif
}
next3:
if (unlikely((item = _parse_alloc(parse_ptr, sizeof(json_object), &parse_ptr->mem->obj_mgr)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
memcpy(&item->jkey, &jkey, sizeof(json_string_t));
memset(&jkey, 0, sizeof(json_string_t));
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
switch (*str) {
case '\"':
#if JSON_PARSE_SPECIAL_QUOTES
case '\'':
#endif
item->type_member = JSON_STRING;
if (unlikely(str[1] == str[0])) {
memset(&item->value.vstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(2);
} else {
end_ch = *str;
_UPDATE_PARSE_OFFSET(1);
if (unlikely(parse_ptr->parse_string(parse_ptr, end_ch, &item->value.vstr, &parse_ptr->mem->str_mgr) < 0)) {
goto err;
}
_UPDATE_PARSE_OFFSET(1);
}
break;
#if JSON_PARSE_SPECIAL_NUM
case '+':
#endif
case '-':
#if JSON_PARSE_SPECIAL_DOUBLE
if (strncmp("Infinity", str + 1, 8) == 0) {
item->type_member = JSON_DOUBLE;
item->value.vnum.vlhex = (*str == '-' ? 0xFFF0000000000000 : 0x7FF0000000000000);
_UPDATE_PARSE_OFFSET(9);
break;
}
FALLTHROUGH_ATTR;
#endif
#if JSON_PARSE_SPECIAL_NUM
case '.':
#endif
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
bak = str;
if (unlikely((item->type_member = _json_parse_number((const char **)&str, &item->value.vnum)) == JSON_NULL)) {
JsonPareseErr("Not number!");
goto err;
}
_UPDATE_PARSE_OFFSET(str - bak);
break;
case '{':
item->type_member = JSON_OBJECT;
INIT_JSON_LIST_HEAD(&item->value.head);
_UPDATE_PARSE_OFFSET(1);
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (likely(*str != '}')) {
if (parent)
json_list_add_tail(&item->list, &parent->value.head);
goto next1;
} else {
_UPDATE_PARSE_OFFSET(1);
}
break;
case '[':
item->type_member = JSON_ARRAY;
INIT_JSON_LIST_HEAD(&item->value.head);
_UPDATE_PARSE_OFFSET(1);
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (likely(*str != ']')) {
if (parent)
json_list_add_tail(&item->list, &parent->value.head);
goto next1;
} else {
_UPDATE_PARSE_OFFSET(1);
}
break;
case 'f':
if (likely(parse_ptr->size - parse_ptr->offset >= 5 && memcmp("false", str, 5) == 0)) {
item->type_member = JSON_BOOL;
item->value.vnum.vbool = false;
_UPDATE_PARSE_OFFSET(5);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 't':
if (likely(parse_ptr->size - parse_ptr->offset >= 4 && memcmp("true", str, 4) == 0)) {
item->type_member = JSON_BOOL;
item->value.vnum.vbool = true;
_UPDATE_PARSE_OFFSET(4);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 'n':
if (likely(parse_ptr->size - parse_ptr->offset >= 4 && memcmp("null", str, 4) == 0)) {
item->type_member = JSON_NULL;
_UPDATE_PARSE_OFFSET(4);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
#if JSON_PARSE_SPECIAL_DOUBLE
case 'N':
if (likely(parse_ptr->size - parse_ptr->offset >= 3 && memcmp("NaN", str, 3) == 0)) {
item->type_member = JSON_DOUBLE;
item->value.vnum.vlhex = 0x7FF0000000000001;
_UPDATE_PARSE_OFFSET(3);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
case 'I':
if (likely(parse_ptr->size - parse_ptr->offset >= 8 && memcmp("Infinity", str, 8) == 0)) {
item->type_member = JSON_DOUBLE;
item->value.vnum.vlhex = 0x7FF0000000000000;
_UPDATE_PARSE_OFFSET(8);
} else {
JsonPareseErr("invalid next ptr!");
goto err;
}
break;
#endif
default:
JsonPareseErr("invalid next ptr!");
goto err;
}
if (parent) {
json_list_add_tail(&item->list, &parent->value.head);
item = NULL;
}
next4:
if (likely(item_depth >= 0)) {
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (parent->type_member == JSON_OBJECT) {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next2;
#else
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (*str != '}')
goto next2;
FALLTHROUGH_ATTR;
#endif
case '}':
_UPDATE_PARSE_OFFSET(1);
if (likely(item_depth > 0)) {
parent = item_array[--item_depth];
goto next4;
}
break;
default:
JsonPareseErr("invalid object!");
goto err;
}
} else {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next3;
#else
_skip_blank_rapid(parse_ptr);
str = parse_ptr->str + parse_ptr->offset;
if (*str != ']')
goto next3;
FALLTHROUGH_ATTR;
#endif
case ']':
_UPDATE_PARSE_OFFSET(1);
if (likely(item_depth > 0)) {
parent = item_array[--item_depth];
goto next4;
}
break;
default:
JsonPareseErr("invalid array!");
goto err;
}
}
}
if (item_array) {
*root = *item_array;
json_free(item_array);
} else {
*root = item;
}
return 0;
err:
if (item_array) {
*root = *item_array;
json_free(item_array);
} else {
if (!(*root)) {
*root = item;
item = NULL;
}
}
if (parse_ptr->mem == &s_invalid_json_mem) {
if (item)
json_free(item);
if (jkey.str)
json_free(jkey.str);
}
return -1;
}
json_object *json_parse_common(json_parse_choice_t *choice)
{
json_object *json = NULL;
json_parse_t parse_val = {0};
size_t mem_size = 0, total_size = 0;
parse_val.read_size = parse_val.read_size ? parse_val.read_size : JSON_PARSE_READ_SIZE_DEF;
parse_val.mem = choice->mem ? choice->mem : &s_invalid_json_mem;
parse_val.fd = -1;
if (choice->path) {
if ((parse_val.fd = open(choice->path, O_RDONLY)) < 0) {
JsonErr("open(%s) failed!\n", choice->path);
return NULL;
}
if (choice->str_len) {
total_size = choice->str_len;
} else {
total_size = lseek(parse_val.fd, 0, SEEK_END);
lseek(parse_val.fd, 0, SEEK_SET);
}
parse_val.skip_blank = _skip_blank;
parse_val.parse_string = _json_parse_string;
parse_val.parse_value = _json_parse_value;
} else {
parse_val.str = choice->str;
total_size = choice->str_len ? choice->str_len : strlen(choice->str);
parse_val.size = total_size;
if (choice->mem) {
parse_val.reuse_flag = choice->reuse_flag;
}
parse_val.skip_blank = _skip_blank_rapid;
if (parse_val.reuse_flag) {
parse_val.parse_string = _json_parse_string_reuse;
} else {
parse_val.parse_string = _json_parse_string_rapid;
}
parse_val.parse_value = _json_parse_value_rapid;
}
if (choice->mem) {
pjson_memory_init(choice->mem);
mem_size = total_size / JSON_PARSE_NUM_DIV_DEF;
if (mem_size < choice->mem_size)
mem_size = choice->mem_size;
choice->mem->obj_mgr.mem_size = mem_size;
choice->mem->key_mgr.mem_size = mem_size;
choice->mem->str_mgr.mem_size = mem_size;
}
#if !JSON_PARSE_SINGLE_VALUE
parse_val.skip_blank(&parse_val);
if (parse_val.str[parse_val.offset] != '{' && parse_val.str[parse_val.offset] != '[') {
JsonErr("The first object isn't object or array\n");
goto end;
}
#endif
if (parse_val.parse_value(&parse_val, &json) < 0) {
if (choice->mem) {
pjson_memory_free(choice->mem);
} else {
json_del_object(json);
}
json = NULL;
goto end;
}
#if !JSON_PARSE_FINISHED_CHAR
parse_val.skip_blank(&parse_val);
if (parse_val.str[parse_val.offset]) {
JsonErr("Extra trailing characters!\n%s\n", parse_val.str + parse_val.offset);
if (choice->mem) {
pjson_memory_free(choice->mem);
} else {
json_del_object(json);
}
json = NULL;
goto end;
}
#endif
end:
if (choice->path) {
if (parse_val.str)
json_free(parse_val.str);
if (parse_val.fd >= 0)
close(parse_val.fd);
}
return json;
}
#if JSON_SAX_APIS_SUPPORT
static inline int _json_sax_parse_string(json_parse_t *parse_ptr, char end_ch, json_string_t *jstr, json_mem_mgr_t *mgr)
{
char *ptr = NULL, *str = NULL;
int len = 0, total = 0;
int escaped = 0;
memset(jstr, 0, sizeof(json_string_t));
if (unlikely((total = _parse_strlen(parse_ptr, end_ch, &escaped)) < 0)) {
return -1;
}
len = total;
_get_parse_ptr(parse_ptr, 0, total, &str);
if (likely(escaped != 1)) {
if (!(parse_ptr->fd >= 0 && mgr == &parse_ptr->mem->key_mgr)) {
jstr->escaped = escaped != 0;
jstr->alloced = 0;
jstr->len = len;
jstr->str = str;
} else {
if (unlikely((ptr = json_malloc(len+1)) == NULL)) {
JsonErr("malloc failed!\n");
return -1;
}
memcpy(ptr, str, len);
ptr[len] = '\0';
jstr->escaped = escaped != 0;
jstr->alloced = 1;
jstr->len = len;
jstr->str = ptr;
}
} else {
if (unlikely((ptr = json_malloc(len+1)) == NULL)) {
JsonErr("malloc failed!\n");
return -1;
}
if (unlikely((len = _parse_strcpy(ptr, str, len)) < 0)) {
JsonErr("_parse_strcpy failed!\n");
json_free(ptr);
goto err;
}
jstr->escaped = 1;
jstr->alloced = 1;
jstr->len = len;
jstr->str = ptr;
}
_UPDATE_PARSE_OFFSET(total);
return len;
err:
JsonPareseErr("parse string failed!");
return -1;
}
static int _json_sax_parse_value(json_parse_t *parse_ptr)
{
char *str = NULL;
json_string_t *jkey = NULL, *parent = NULL;
json_value_t *value = &parse_ptr->parser.value;
json_string_t *tarray = NULL;
int i = 0;
memset(value, 0, sizeof(*value));
parse_ptr->parser.total += JSON_ITEM_NUM_PLUS_DEF;
if (unlikely((parse_ptr->parser.array = json_malloc(sizeof(json_string_t) * parse_ptr->parser.total)) == NULL)) {
JsonErr("malloc failed!\n");
return -1;
}
memset(parse_ptr->parser.array, 0, sizeof(json_string_t));
goto next3;
next1:
if (unlikely(parse_ptr->parser.index >= parse_ptr->parser.total - 1)) {
parse_ptr->parser.total += JSON_ITEM_NUM_PLUS_DEF;
if (unlikely((tarray = json_malloc(sizeof(json_string_t) * parse_ptr->parser.total)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
memcpy(tarray, parse_ptr->parser.array, sizeof(json_string_t) * (parse_ptr->parser.index + 1));
json_free(parse_ptr->parser.array);
parse_ptr->parser.array = tarray;
}
parent = parse_ptr->parser.array + parse_ptr->parser.index;
++parse_ptr->parser.index;
memset(parse_ptr->parser.array + parse_ptr->parser.index, 0, sizeof(json_string_t));
if (parent->type == JSON_ARRAY)
goto next3;
next2:
jkey = parse_ptr->parser.array + parse_ptr->parser.index;
if (unlikely(_json_parse_key(parse_ptr, jkey) < 0)) {
goto err;
}
next3:
jkey = parse_ptr->parser.array + parse_ptr->parser.index;
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 128, &str);
switch (*str) {
case '{':
jkey->type = JSON_OBJECT;
value->vcmd = JSON_SAX_START;
_UPDATE_PARSE_OFFSET(1);
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
if (unlikely(parse_ptr->ret == JSON_SAX_PARSE_STOP)) {
goto end;
}
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (likely(*str != '}')) {
goto next1;
} else {
jkey->type = JSON_OBJECT;
value->vcmd = JSON_SAX_FINISH;
_UPDATE_PARSE_OFFSET(1);
}
break;
case '[':
jkey->type = JSON_ARRAY;
value->vcmd = JSON_SAX_START;
_UPDATE_PARSE_OFFSET(1);
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
if (unlikely(parse_ptr->ret == JSON_SAX_PARSE_STOP)) {
goto end;
}
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (likely(*str != ']')) {
goto next1;
} else {
jkey->type = JSON_ARRAY;
value->vcmd = JSON_SAX_FINISH;
_UPDATE_PARSE_OFFSET(1);
}
break;
default:
if (_json_parse_single_value(parse_ptr, str, jkey, value) < 0)
goto err;
break;
}
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
if (jkey->type == JSON_STRING && value->vstr.alloced) {
json_free(value->vstr.str);
}
memset(value, 0, sizeof(*value));
if (jkey->alloced) {
json_free(jkey->str);
}
memset(jkey, 0, sizeof(*jkey));
if (unlikely(parse_ptr->ret == JSON_SAX_PARSE_STOP)) {
--parse_ptr->parser.index;
goto end;
}
next4:
if (likely(parse_ptr->parser.index > 0)) {
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (parent->type == JSON_OBJECT) {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next2;
#else
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (*str != '}')
goto next2;
FALLTHROUGH_ATTR;
#endif
case '}':
_UPDATE_PARSE_OFFSET(1);
--parse_ptr->parser.index;
jkey = parse_ptr->parser.array + parse_ptr->parser.index;
value->vcmd = JSON_SAX_FINISH;
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
memset(value, 0, sizeof(*value));
if (jkey->alloced) {
json_free(jkey->str);
}
memset(jkey, 0, sizeof(*jkey));
if (unlikely(parse_ptr->ret == JSON_SAX_PARSE_STOP)) {
--parse_ptr->parser.index;
goto end;
}
if (likely(parse_ptr->parser.index > 0)) {
parent = parse_ptr->parser.array + parse_ptr->parser.index - 1;
goto next4;
}
break;
default:
JsonPareseErr("invalid object!");
goto err;
}
} else {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
#if !JSON_PARSE_LAST_COMMA
goto next3;
#else
parse_ptr->skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (*str != ']')
goto next3;
FALLTHROUGH_ATTR;
#endif
case ']':
_UPDATE_PARSE_OFFSET(1);
--parse_ptr->parser.index;
jkey = parse_ptr->parser.array + parse_ptr->parser.index;
value->vcmd = JSON_SAX_FINISH;
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
memset(value, 0, sizeof(*value));
if (jkey->alloced) {
json_free(jkey->str);
}
memset(jkey, 0, sizeof(*jkey));
if (unlikely(parse_ptr->ret == JSON_SAX_PARSE_STOP)) {
--parse_ptr->parser.index;
goto end;
}
if (likely(parse_ptr->parser.index > 0)) {
parent = parse_ptr->parser.array + parse_ptr->parser.index - 1;
goto next4;
}
break;
default:
JsonPareseErr("invalid array!");
goto err;
}
}
}
parse_ptr->parser.index = -1;
end:
value->vcmd = JSON_SAX_FINISH;
for (i =parse_ptr->parser.index; i >= 0; --i) {
parse_ptr->ret = parse_ptr->cb(&parse_ptr->parser);
if (parse_ptr->parser.array[i].alloced) {
json_free(parse_ptr->parser.array[i].str);
}
}
json_free(parse_ptr->parser.array);
memset(&parse_ptr->parser, 0, sizeof(parse_ptr->parser));
return 0;
err:
if (parse_ptr->parser.array) {
for (i = 0; i < parse_ptr->parser.index; ++i) {
if (parse_ptr->parser.array[i].alloced) {
json_free(parse_ptr->parser.array[i].str);
}
}
json_free(parse_ptr->parser.array);
}
memset(&parse_ptr->parser, 0, sizeof(parse_ptr->parser));
return -1;
}
int json_sax_parse_common(json_sax_parse_choice_t *choice)
{
int ret = -1;
json_parse_t parse_val = {0};
parse_val.read_size = parse_val.read_size ? parse_val.read_size : JSON_PARSE_READ_SIZE_DEF;
parse_val.mem = &s_invalid_json_mem;
parse_val.fd = -1;
if (choice->path) {
if ((parse_val.fd = open(choice->path, O_RDONLY)) < 0) {
JsonErr("open(%s) failed!\n", choice->path);
return -1;
}
parse_val.skip_blank = _skip_blank;
} else {
parse_val.str = choice->str;
parse_val.size = choice->str_len ? choice->str_len : strlen(choice->str);
parse_val.skip_blank = _skip_blank_rapid;
}
parse_val.parse_string = _json_sax_parse_string;
parse_val.cb = choice->cb;
#if !JSON_PARSE_SINGLE_VALUE
parse_val.skip_blank(&parse_val);
if (parse_val.str[parse_val.offset] != '{' && parse_val.str[parse_val.offset] != '[') {
JsonErr("The first object isn't object or array!\n");
goto end;
}
#endif
ret = _json_sax_parse_value(&parse_val);
#if !JSON_PARSE_FINISHED_CHAR
if (ret == 0) {
parse_val.skip_blank(&parse_val);
if (parse_val.str[parse_val.offset]) {
JsonErr("Extra trailing characters!\n%s\n", parse_val.str + parse_val.offset);
ret = -1;
}
}
#endif
#if !JSON_PARSE_SINGLE_VALUE
end:
#endif
if (choice->path) {
if (parse_val.str)
json_free(parse_val.str);
if (parse_val.fd >= 0)
close(parse_val.fd);
}
return ret;
}
#endif
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/lengjingzju/json.git
git@gitee.com:lengjingzju/json.git
lengjingzju
json
json
master

搜索帮助