加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
json.c 160.88 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935
/*******************************************
* 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 <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include "json.h"
#define type_member jkey.type
#define key_member jkey.str
#define str_member vstr.str
/*
* 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
/*
* JSON_STRICT_PARSE_MODE can be: 0 / 1 / 2
* 0: not strict mode
* 1: will enable more checks
* 2: further turns off some features that are not standard, such as hexadecimal
*/
#define JSON_STRICT_PARSE_MODE 1
/**************** debug ****************/
/* error print */
#define JSON_ERROR_PRINT_ENABLE 0
#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::%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 likely(cond) __builtin_expect(!!(cond), 1)
#define unlikely(cond) __builtin_expect(!!(cond), 0)
#else
#define UNUSED_ATTR
#define likely(cond) (cond)
#define unlikely(cond) (cond)
#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 = *(int *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(unsigned int *)value; break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: json->value.vnum.vlint = *(long long int *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(unsigned long long int *)value;break;
#endif
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 = ((int *)values) + i; break;
case JSON_HEX: value = ((unsigned int *)values) + i; break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: value = ((long long int *)values) + i; break;
case JSON_LHEX: value = ((unsigned long long int *)values) + i;break;
#endif
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;
}
unsigned int json_string_hash_code(json_string_t *jstr)
{
unsigned int 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)
{
#if JSON_LONG_LONG_SUPPORT
#define _get_lnumber(json, etype, val) \
case JSON_LINT: *(etype *)val = (etype)json->value.vnum.vlint; break; \
case JSON_LHEX: *(etype *)val = (etype)json->value.vnum.vlhex; break;
#else
#define _get_lnumber(json, etype, val)
#endif
#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; \
_get_lnumber(json, etype, val) \
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, int, value); break;
case JSON_HEX: _get_number(json, unsigned int, value); break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: _get_number(json, long long int, value); break;
case JSON_LHEX: _get_number(json, unsigned long long int, value);break;
#endif
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:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
case JSON_LHEX:
#endif
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 = *(int *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(unsigned int *)value; break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: json->value.vnum.vlint = *(long long int *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(unsigned long long int *)value;break;
#endif
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, unsigned int 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)
{
unsigned int ha = ((const json_item_t *)a)->hash;
unsigned int 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) {
unsigned int 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;
#if JSON_LONG_LONG_SUPPORT
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;
#endif
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:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
case JSON_LHEX:
#endif
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:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
case JSON_LHEX:
#endif
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 = *(int *)value; break;
case JSON_HEX: json->value.vnum.vhex = *(unsigned int *)value; break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: json->value.vnum.vlint = *(long long int *)value; break;
case JSON_LHEX: json->value.vnum.vlhex = *(unsigned long long int *)value;break;
#endif
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 = ((int *)values) + i; break;
case JSON_HEX: value = ((unsigned int *)values) + i; break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT: value = ((long long int *)values) + i; break;
case JSON_LHEX: value = ((unsigned long long int *)values) + i; break;
#endif
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;
#if JSON_LONG_LONG_SUPPORT
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;
#endif
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:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
case JSON_LHEX:
#endif
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:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
case JSON_LHEX:
#endif
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))
#if !FAST_FILL_DIGITS_EXISTED
#define FAST_FILL_DIGITS_EXISTED 1
static const char ch_100_lut[200] = {
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9',
};
static const uint8_t tz_100_lut[100] = {
2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define FAST_DIV10(n) (ch_100_lut[(n) << 1] - '0') /* 0 <= n < 100 */
#define FAST_DIV100(n) (((n) * 5243) >> 19) /* 0 <= n < 10000 */
#define FAST_DIV10000(n) ((uint32_t)(((uint64_t)(n) * 109951163) >> 40)) /* 0 <= n < 100000000 */
static inline int32_t fill_1_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100) {
if (digits >= 10) {
*ptz = tz_100_lut[digits];
memcpy(s, &ch_100_lut[digits<<1], 2);
s += 2;
} else {
*ptz = 0;
*s++ = digits + '0';
}
} else {
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
if (q >= 10) {
*ptz = tz_100_lut[q];
memcpy(s, &ch_100_lut[q<<1], 2);
s += 2;
} else {
*ptz = 0;
*s++ = q + '0';
}
if (!r) {
*ptz += 2;
memset(s, '0', 2);
s += 2;
} else {
*ptz = tz_100_lut[r];
memcpy(s, &ch_100_lut[r<<1], 2);
s += 2;
}
}
return s - buffer;
}
static inline int32_t fill_t_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
memcpy(s, &ch_100_lut[q<<1], 2);
memcpy(s + 2, &ch_100_lut[r<<1], 2);
if (!r) {
*ptz = tz_100_lut[q] + 2;
} else {
*ptz = tz_100_lut[r];
}
return 4;
}
static inline int32_t fill_1_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
return fill_1_4_digits(s, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
s += fill_1_4_digits(s, q, ptz);
if (!r) {
*ptz += 4;
memset(s, '0', 4);
s += 4;
} else {
s += fill_t_4_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_t_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
memset(s, '0', 4);
fill_t_4_digits(s + 4, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
fill_t_4_digits(s, q, ptz);
if (!r) {
memset(s + 4, '0', 4);
*ptz += 4;
} else {
fill_t_4_digits(s + 4, r, ptz);
}
}
return 8;
}
static inline int32_t fill_1_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
return fill_1_8_digits(s, (uint32_t)digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
s += fill_1_8_digits(s, q, ptz);
if (!r) {
*ptz += 8;
memset(s, '0', 8);
s += 8;
} else {
s += fill_t_8_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_t_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
memset(s, '0', 8);
fill_t_8_digits(s + 8, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
fill_t_8_digits(s, q, ptz);
if (!r) {
memset(s + 8, '0', 8);
*ptz += 8;
} else {
fill_t_8_digits(s + 8, r, ptz);
}
}
return 16;
}
static inline int32_t fill_1_20_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000000000000000llu) {
return fill_1_16_digits(s, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 10000000000000000llu);
uint64_t r = (digits - (uint64_t)q * 10000000000000000llu);
s += fill_1_4_digits(s, q, ptz);
if (!r) {
memset(s, '0', 16);
s += 16;
*ptz += 16;
} else {
s += fill_t_16_digits(s, r, ptz);
}
}
return s - buffer;
}
#endif
static const char hex_array[] = {
'0', '1', '2', '3', '4',
'5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};
#define INT_TO_STRING_FUNC(fname, ftype) \
static int fname(ftype n, char *c) \
{ \
char *s = c; \
ftype m = n, t = 0; \
int h = 0, i = 0, j = 0, k = 0, a = 0; \
\
if (m == 0) { \
*s++ = '0'; \
*s = '\0'; \
return 1; \
} \
\
if (n < 0) { \
m = -n; \
*s++ = '-'; \
a = 1; \
} \
\
while (m > 0) { \
t = m; \
m /= 10; \
t -= (m << 3) + (m << 1); \
s[i++] = t + '0'; \
} \
s[i] = '\0'; \
\
h = i >> 1; \
while (j < h) { \
k = i - j - 1; \
t = s[k]; \
s[k] = s[j]; \
s[j++] = t; \
} \
\
return i + a; \
}
#define HEX_TO_STRING_FUNC(fname, ftype) \
static int fname(ftype n, char *c) \
{ \
char *s = c; \
ftype m = n, t = 0; \
int h = 0, i = 0, j = 0, k = 0, a = 0; \
\
*s++ = '0'; \
*s++ = 'x'; \
if (m == 0) { \
*s++ = '0'; \
*s = '\0'; \
return 3; \
} \
a = 2; \
\
while (m > 0) { \
s[i++] = hex_array[m & 0xf]; \
m >>= 4; \
} \
s[i] = '\0'; \
\
h = i >> 1; \
while (j < h) { \
k = i - j - 1; \
t = s[k]; \
s[k] = s[j]; \
s[j++] = t; \
} \
\
return i + a; \
}
#if INT_MAX > 2147483647U
INT_TO_STRING_FUNC(int_to_string, int)
#else
static int int_to_string(int num, char *buffer)
{
char *s = buffer;
uint32_t n = 0;
int32_t tz = 0;
if (num == 0) {
memcpy(s, "0", 2);
return 1;
}
if (num < 0) {
n = -num;
*s++ = '-';
} else {
n = num;
}
if (n < 100000000) {
s += fill_1_8_digits(s, (uint32_t)n, &tz);
} else {
uint32_t q = (uint32_t)(((uint64_t)n * 1441151881) >> 57); /* n / 100000000 */
uint32_t r = n - q * 100000000;
if (q >= 10) {
tz = tz_100_lut[q];
memcpy(s, &ch_100_lut[q<<1], 2);
s += 2;
} else {
tz = 0;
*s++ = q + '0';
}
if (!r) {
tz += 8;
memset(s, '0', 8);
s += 8;
} else {
s += fill_t_8_digits(s, r, &tz);
}
}
return s - buffer;
}
#endif
#if LLONG_MAX > 9223372036854775807LLU
INT_TO_STRING_FUNC(lint_to_string, long long int)
#else
static int lint_to_string(long long int num, char *buffer)
{
char *s = buffer;
uint64_t n = 0;
int32_t tz = 0;
if (num == 0) {
memcpy(s, "0", 2);
return 1;
}
if (num < 0) {
n = -num;
*s++ = '-';
} else {
n = num;
}
s += fill_1_20_digits(buffer, n, &tz);
return s - buffer;
}
#endif
HEX_TO_STRING_FUNC(hex_to_string, unsigned int)
#if JSON_LONG_LONG_SUPPORT
HEX_TO_STRING_FUNC(lhex_to_string, unsigned long long int)
#endif
#if JSON_DTOA_ALGORITHM == 1
static inline int double_to_string(double value, char* buffer)
{
return sprintf(buffer, "%1.16g", value);
}
#elif JSON_DTOA_ALGORITHM == 2
#include "grisu2.h"
#define double_to_string grisu2_dtoa
#elif JSON_DTOA_ALGORITHM == 3
#include "dragonbox.h"
#define double_to_string dragonbox_dtoa
#else
#define DIY_SIGNIFICAND_SIZE 64 /* Symbol: 1 bit, Exponent, 11 bits, Mantissa, 52 bits */
#define DP_SIGNIFICAND_SIZE 52 /* Mantissa, 52 bits */
#define DP_EXPONENT_OFFSET 0x3FF /* Exponent offset is 0x3FF */
#define DP_EXPONENT_MAX 0x7FF /* Max Exponent value */
#define DP_EXPONENT_MASK 0x7FF0000000000000 /* Exponent Mask, 11 bits */
#define DP_SIGNIFICAND_MASK 0x000FFFFFFFFFFFFF /* Mantissa Mask, 52 bits */
#define DP_HIDDEN_BIT 0x0010000000000000 /* Integer bit for Mantissa */
#ifndef USE_FLOAT_MUL_CONVERT
#define USE_FLOAT_MUL_CONVERT 0
#endif
#ifndef LSHIFT_RESERVED_BIT
#define LSHIFT_RESERVED_BIT 11 /* The value should be less than or equal to 11 */
#endif
#ifndef APPROX_TAIL_CMP_VAL
#define APPROX_TAIL_CMP_VAL 2 /* The value should be less than or equal to 4 */
#endif
static const unsigned int s_tail_cmp = (APPROX_TAIL_CMP_VAL << 1) + 1;
typedef struct {
uint64_t f;
int32_t e;
} diy_fp_t;
#if !USE_FLOAT_MUL_CONVERT
typedef struct {
uint32_t hi;
uint32_t lo;
} u32x2_t;
typedef struct {
uint32_t hi;
uint32_t lo;
int32_t e;
} pow9x2_t;
#else
static inline uint64_t u128_calc(uint64_t x, uint64_t y)
{
const uint64_t div = 10000000000000000000llu;
uint64_t hi, lo, ret;
double val;
#if defined(_MSC_VER) && defined(_M_AMD64)
lo = _umul128(x, y, &hi);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __clang_major__ >= 9) && (__WORDSIZE == 64)
__extension__ typedef unsigned __int128 uint128;
const uint128 p = (uint128)x * (uint128)y;
hi = (uint64_t)(p >> 64);
lo = (uint64_t)p;
#else
const uint64_t M32 = 0XFFFFFFFF;
const uint64_t a = x >> 32;
const uint64_t b = x & M32;
const uint64_t c = y >> 32;
const uint64_t d = y & M32;
const uint64_t ac = a * c;
const uint64_t bc = b * c;
const uint64_t ad = a * d;
const uint64_t bd = b * d;
const uint64_t mid1 = ad + (bd >> 32);
const uint64_t mid2 = bc + (mid1 & M32);
hi = ac + (mid1 >> 32) + (mid2 >> 32);
lo = (bd & M32) | (mid2 & M32) << 32;
#endif
val = hi * 1.8446744073709551616; /* 1<<64 = 18446744073709551616 */
ret = (uint64_t)val + 1;
if (lo >= div)
++ret;
return ret;
}
#endif
static inline int32_t u64_pz_get(uint64_t f)
{
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return 63 - index;
#elif defined(__GNUC__) || defined(__clang__)
return __builtin_clzll(f);
#else
int32_t index = DP_SIGNIFICAND_SIZE; /* max value of f is smaller than pow(2, 53) */
while (!(f & ((uint64_t)1 << index)))
--index;
return 63 - index;
#endif
}
#if !USE_FLOAT_MUL_CONVERT
/*
# python to get lut
def print_pow_array(unit, index, end, positive):
cmp_value = 1000000000000000000 # ULONG_MAX = 18446744073709551615
base_lut = []
index_lut = []
for i in range(end + 1):
a = unit ** i
b = a
j = 0
if a < cmp_value:
while b < cmp_value:
j += 1
b = a * (10 ** j)
j -= 1
b = a * (10 ** j)
j = i * index + j
else:
while b >= cmp_value:
j += 1
b = a // (10 ** j)
b = a // (10 ** j)
if b != cmp_value:
b += 1;
j = i * index - j
#print('%-3d: %d 0x%016x %d' % (i, j, b, b))
base_lut.append(b)
index_lut.append(j)
print('static const u32x2_t %s_base_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 4 == 0:
print()
print(' ', end='')
hi = base_lut[i] // 1000000000;
lo = base_lut[i] - hi * 1000000000;
print('{%9d,%9d}' % (hi, lo), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
print()
print('static const int8_t %s_index_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 20 == 0:
print()
print(' ', end='')
print('%-3d' % (index_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
def print_positive_array():
# 1 * (2 ** 4) = 1.6 * (10 ** 1)
# 16 = 1.6 * (10 ** 1)
# 243 = (1023 - 52 - (11 - x)) / 4 + 1
print_pow_array(16, 1, 243, True)
def print_negative_array():
# 1 * (2 ** -4) = 0.625 * (10 ** -1)
# 625 = 0.625 * (10 ** 3)
# 285 = (1022 + 52 + (63 - (11 - x))) / 4 + 1
print_pow_array(625, 3, 285, False)
print_positive_array()
print()
print_negative_array()
*/
static inline pow9x2_t positive_diy_fp(int32_t e)
{
static const u32x2_t positive_base_lut[244] = {
{100000000, 0}, {160000000, 0}, {256000000, 0}, {409600000, 0},
{655360000, 0}, {104857600, 0}, {167772160, 0}, {268435456, 0},
{429496729,600000000}, {687194767,360000000}, {109951162,777600000}, {175921860,444160000},
{281474976,710656000}, {450359962,737049600}, {720575940,379279360}, {115292150,460684698},
{184467440,737095517}, {295147905,179352826}, {472236648,286964522}, {755578637,259143235},
{120892581,961462918}, {193428131,138340668}, {309485009,821345069}, {495176015,714152110},
{792281625,142643376}, {126765060, 22822941}, {202824096, 36516705}, {324518553,658426727},
{519229685,853482763}, {830767497,365572421}, {132922799,578491588}, {212676479,325586540},
{340282366,920938464}, {544451787, 73501542}, {871122859,317602467}, {139379657,490816395},
{223007451,985306232}, {356811923,176489971}, {570899077, 82383953}, {913438523,331814324},
{146150163,733090292}, {233840261,972944467}, {374144419,156711148}, {598631070,650737836},
{957809713, 41180537}, {153249554, 86588886}, {245199286,538542218}, {392318858,461667548},
{627710173,538668077}, {100433627,766186893}, {160693804,425899028}, {257110087, 81438445},
{411376139,330301511}, {658201822,928482417}, {105312291,668557187}, {168499666,669691499},
{269599466,671506398}, {431359146,674410237}, {690174634,679056379}, {110427941,548649021},
{176684706,477838433}, {282695530,364541493}, {452312848,583266389}, {723700557,733226222},
{115792089,237316196}, {185267342,779705913}, {296427748,447529461}, {474284397,516047137},
{758855036, 25675419}, {121416805,764108067}, {194266889,222572908}, {310827022,756116652},
{497323236,409786643}, {795717178,255658628}, {127314748,520905381}, {203703597,633448609},
{325925756,213517774}, {521481209,941628439}, {834369935,906605501}, {133499189,745056881},
{213598703,592091009}, {341757925,747345614}, {546812681,195752982}, {874900289,913204770},
{139984046,386112764}, {223974474,217780422}, {358359158,748448674}, {573374653,997517878},
{917399446,396028605}, {146783911,423364577}, {234854258,277383323}, {375766813,243813317},
{601226901,190101307}, {961963041,904162091}, {153914086,704665935}, {246262538,727465496},
{394020061,963944793}, {630432099,142311668}, {100869135,862769867}, {161390617,380431787},
{258224987,808690859}, {413159980,493905375}, {661055968,790248599}, {105768955, 6439776},
{169230328, 10303642}, {270768524,816485827}, {433229639,706377322}, {693167423,530203715},
{110906787,764832595}, {177450860,423732152}, {283921376,677971442}, {454274202,684754307},
{726838724,295606891}, {116294195,887297103}, {186070713,419675364}, {297713141,471480583},
{476341026,354368932}, {762145642,166990291}, {121943302,746718447}, {195109284,394749515},
{312174855, 31599224}, {499479768, 50558758}, {799167628,880894012}, {127866820,620943042},
{204586912,993508867}, {327339060,789614188}, {523742497,263382700}, {837987995,621412319},
{134078079,299425971}, {214524926,879081554}, {343239883, 6530486}, {549183812,810448778},
{878694100,496718044}, {140591056, 79474887}, {224945689,727159820}, {359913103,563455711},
{575860965,701529137}, {921377545,122446620}, {147420407,219591460}, {235872651,551346335},
{377396242,482154136}, {603833987,971446617}, {966134380,754314587}, {154581500,920690334},
{247330401,473104535}, {395728642,356967255}, {633165827,771147608}, {101306532,443383618},
{162090451,909413788}, {259344723, 55062060}, {414951556,888099296}, {663922491, 20958874},
{106227598,563353420}, {169964157,701365472}, {271942652,322184755}, {435108243,715495608},
{696173189,944792972}, {111387710,391166876}, {178220336,625867001}, {285152538,601387202},
{456244061,762219522}, {729990498,819551235}, {116798479,811128198}, {186877567,697805117},
{299004108,316488186}, {478406573,306381098}, {765450517,290209756}, {122472082,766433561},
{195955332,426293698}, {313528531,882069916}, {501645651, 11311866}, {802633041,618098985},
{128421286,658895838}, {205474058,654233341}, {328758493,846773345}, {526013590,154837351},
{841621744,247739762}, {134659479, 79638362}, {215455166,527421379}, {344728266,443874207},
{551565226,310198730}, {882504362, 96317968}, {141200697,935410875}, {225921116,696657400},
{361473786,714651840}, {578358058,743442944}, {925372893,989508710}, {148059663, 38321394},
{236895460,861314230}, {379032737,378102768}, {606452379,804964428}, {970323807,687943085},
{155251809,230070894}, {248402894,768113430}, {397444631,628981488}, {635911410,606370380},
{101745825,697019261}, {162793321,115230818}, {260469313,784369308}, {416750902, 54990893},
{666801443,287985428}, {106688230,926077669}, {170701169,481724270}, {273121871,170758832},
{436994993,873214130}, {699191990,197142608}, {111870718,431542818}, {178993149,490468508},
{286389039,184749613}, {458222462,695599380}, {733155940,312959007}, {117304950,450073442},
{187687920,720117506}, {300300673,152188010}, {480481077, 43500815}, {768769723,269601304},
{123003155,723136209}, {196805049,157017934}, {314888078,651228694}, {503820925,841965911},
{806113481,347145457}, {128978157, 15543274}, {206365051,224869237}, {330184081,959790779},
{528294531,135665247}, {845271249,817064395}, {135243399,970730304}, {216389439,953168485},
{346223103,925069576}, {553956966,280111322}, {886331146, 48178115}, {141812983,367708499},
{226900773,388333598}, {363041237,421333756}, {580865979,874134009}, {929385567,798614415},
{148701690,847778307}, {237922705,356445291}, {380676328,570312465}, {609082125,712499943},
{974531401,139999909}, {155925024,182399986}, {249480038,691839977}, {399168061,906943963}
};
static const int8_t positive_index_lut[244] = {
17 , 17 , 17 , 17 , 17 , 16 , 16 , 16 , 16 , 16 , 15 , 15 , 15 , 15 , 15 , 14 , 14 , 14 , 14 , 14 ,
13 , 13 , 13 , 13 , 13 , 12 , 12 , 12 , 12 , 12 , 11 , 11 , 11 , 11 , 11 , 10 , 10 , 10 , 10 , 10 ,
9 , 9 , 9 , 9 , 9 , 8 , 8 , 8 , 8 , 7 , 7 , 7 , 7 , 7 , 6 , 6 , 6 , 6 , 6 , 5 ,
5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 1 ,
1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , -1 , -1 , -1 , -1 , -1 , -2 , -2 , -2 , -2 , -3 , -3 ,
-3 , -3 , -3 , -4 , -4 , -4 , -4 , -4 , -5 , -5 , -5 , -5 , -5 , -6 , -6 , -6 , -6 , -6 , -7 , -7 ,
-7 , -7 , -7 , -8 , -8 , -8 , -8 , -8 , -9 , -9 , -9 , -9 , -9 , -10, -10, -10, -10, -10, -11, -11,
-11, -11, -11, -12, -12, -12, -12, -13, -13, -13, -13, -13, -14, -14, -14, -14, -14, -15, -15, -15,
-15, -15, -16, -16, -16, -16, -16, -17, -17, -17, -17, -17, -18, -18, -18, -18, -18, -19, -19, -19,
-19, -19, -20, -20, -20, -20, -20, -21, -21, -21, -21, -21, -22, -22, -22, -22, -23, -23, -23, -23,
-23, -24, -24, -24, -24, -24, -25, -25, -25, -25, -25, -26, -26, -26, -26, -26, -27, -27, -27, -27,
-27, -28, -28, -28, -28, -28, -29, -29, -29, -29, -29, -30, -30, -30, -30, -30, -31, -31, -31, -31,
-31, -32, -32, -32
};
const pow9x2_t v = { .hi = positive_base_lut[e].hi, .lo = positive_base_lut[e].lo, .e = positive_index_lut[e] };
return v;
}
static inline pow9x2_t negative_diy_fp(int32_t e)
{
static const u32x2_t negative_base_lut[286] = {
{100000000, 0}, {625000000, 0}, {390625000, 0}, {244140625, 0},
{152587890,625000000}, {953674316,406250000}, {596046447,753906250}, {372529029,846191407},
{232830643,653869629}, {145519152,283668519}, {909494701,772928238}, {568434188,608080149},
{355271367,880050093}, {222044604,925031309}, {138777878, 78144568}, {867361737,988403548},
{542101086,242752218}, {338813178,901720136}, {211758236,813575085}, {132348898, 8484428},
{827180612,553027675}, {516987882,845642297}, {323117426,778526436}, {201948391,736579023},
{126217744,835361889}, {788860905,221011806}, {493038065,763132379}, {308148791,101957737},
{192592994,438723586}, {120370621,524202241}, {752316384,526264006}, {470197740,328915004},
{293873587,705571877}, {183670992,315982424}, {114794370,197489015}, {717464813,734306341},
{448415508,583941463}, {280259692,864963415}, {175162308, 40602134}, {109476442,525376334},
{684227765,783602086}, {427642353,614751304}, {267276471, 9219565}, {167047794,380762228},
{104404871,487976393}, {652530446,799852453}, {407831529,249907783}, {254894705,781192365},
{159309191,113245228}, {995682444,457782674}, {622301527,786114171}, {388938454,866321357},
{243086534,291450848}, {151929083,932156780}, {949556774,575979875}, {593472984,109987422},
{370920615, 68742139}, {231825384,417963837}, {144890865,261227398}, {905567907,882671237},
{565979942,426669523}, {353737464, 16668452}, {221085915, 10417783}, {138178696,881511115},
{863616855,509444463}, {539760534,693402790}, {337350334,183376744}, {210843958,864610465},
{131777474,290381541}, {823609214,314884627}, {514755758,946802892}, {321722349,341751808},
{201076468,338594880}, {125672792,711621800}, {785454954,447636249}, {490909346,529772656},
{306818341,581107910}, {191761463,488192444}, {119850914,680120278}, {749068216,750751733},
{468167635,469219833}, {292604772,168262396}, {182877982,605163998}, {114298739,128227499},
{714367119,551421864}, {446479449,719638665}, {279049656, 74774166}, {174406035, 46733854},
{109003771,904208659}, {681273574,401304116}, {425795984, 815072}, {266122490, 509420},
{166326556,250318388}, {103954097,656448993}, {649713110,352806202}, {406070693,970503876},
{253794183,731564923}, {158621364,832228077}, {991383530,201425478}, {619614706,375890924},
{387259191,484931828}, {242036994,678082393}, {151273121,673801496}, {945457010,461259344},
{590910631,538287090}, {369319144,711429432}, {230824465,444643395}, {144265290,902902122},
{901658068,143138260}, {563536292,589461413}, {352210182,868413383}, {220131364,292758365},
{137582102,682973978}, {859888141,768587361}, {537430088,605367101}, {335893805,378354438},
{209933628,361471524}, {131208517,725919703}, {820053235,786998139}, {512533272,366873837},
{320333295,229296148}, {200208309,518310093}, {125130193,448943808}, {782063709, 55898799},
{488789818,159936750}, {305493636,349960469}, {190933522,718725293}, {119333451,699203308},
{745834073,120020675}, {466146295,700012922}, {291341434,812508076}, {182088396,757817548},
{113805247,973635968}, {711282799,835224795}, {444551749,897015497}, {277844843,685634686},
{173653027,303521679}, {108533142, 64701049}, {678332137,904381557}, {423957586,190238473},
{264973491,368899046}, {165608432,105561904}, {103505270, 65976190}, {646907937,912351186},
{404317461,195219491}, {252698413,247012182}, {157936508,279382614}, {987103176,746141335},
{616939485,466338335}, {385587178,416461459}, {240991986,510288412}, {150619991,568930258},
{941374947,305814109}, {588359342, 66133818}, {367724588,791333637}, {229827867,994583523},
{143642417,496614702}, {897765109,353841886}, {561103193,346151179}, {350689495,841344487},
{219180934,900840304}, {136988084,313025190}, {856175526,956407438}, {535109704,347754649},
{334443565,217346656}, {209027228,260841660}, {130642017,663026038}, {816512610,393912733},
{510320381,496195458}, {318950238,435122162}, {199343899, 21951351}, {124589936,888719595},
{778687105,554497464}, {486679440,971560915}, {304174650,607225572}, {190109156,629515983},
{118818222,893447489}, {742613893, 84046807}, {464133683,177529254}, {290083551,985955784},
{181302219,991222365}, {113313887,494513978}, {708211796,840712363}, {442632373, 25445227},
{276645233,140903267}, {172903270,713064542}, {108064544,195665339}, {675403401,222908366},
{422127125,764317729}, {263829453,602698581}, {164893408,501686613}, {103058380,313554133},
{644114876,959713331}, {402571798, 99820832}, {251607373,812388020}, {157254608,632742513},
{982841303,954640703}, {614275814,971650440}, {383922384,357281525}, {239951490,223300953},
{149969681,389563096}, {937310508,684769347}, {585819067,927980842}, {366136917,454988027},
{228835573,409367517}, {143022233,380854698}, {893888958,630341861}, {558680599,143963663},
{349175374,464977290}, {218234609, 40610806}, {136396630,650381754}, {852478941,564885961},
{532799338,478053726}, {332999586,548783579}, {208124741,592989737}, {130077963,495618586},
{812987271,847616158}, {508117044,904760099}, {317573153, 65475062}, {198483220,665921914},
{124052012,916201196}, {775325080,726257475}, {484578175,453910922}, {302861359,658694327},
{189288349,786683954}, {118305218,616677472}, {739407616,354234195}, {462129760,221396372},
{288831100,138372733}, {180519437,586482958}, {112824648,491551849}, {705154053, 72199054},
{440721283,170124409}, {275450801,981327756}, {172156751,238329847}, {107597969,523956155},
{672487309,524725965}, {420304568,452953728}, {262690355,283096080}, {164181472, 51935050},
{102613420, 32459407}, {641333875,202871289}, {400833672, 1794556}, {250521045, 1121598},
{156575653,125700999}, {978597832, 35631240}, {611623645, 22269525}, {382264778,138918453},
{238915486,336824034}, {149322178,960515021}, {933263618,503218879}, {583289761,564511800},
{364556100,977819875}, {227847563,111137422}, {142404726,944460889}, {890029543,402880554},
{556268464,626800346}, {347667790,391750217}, {217292368,994843886}, {135807730,621777429},
{848798316,386108927}, {530498947,741318079}, {331561842,338323800}, {207226151,461452375},
{129516344,663407735}, {809477154,146298338}, {505923221,341436462}, {316202013,338397789},
{197626258,336498618}, {123516411,460311637}, {771977571,626947726}, {482485982,266842329},
{301553738,916776456}, {188471086,822985285}, {117794429,264365803}, {736215182,902286268},
{460134489,313928918}, {287584055,821205574}, {179740034,888253484}, {112337521,805158428},
{702109511,282240170}, {438818444,551400106}, {274261527,844625067}, {171413454,902890667},
{107133409,314306667}, {669583808,214416666}
};
static const int8_t negative_index_lut[286] = {
17 , 18 , 18 , 18 , 18 , 19 , 19 , 19 , 19 , 19 , 20 , 20 , 20 , 20 , 20 , 21 , 21 , 21 , 21 , 21 ,
22 , 22 , 22 , 22 , 22 , 23 , 23 , 23 , 23 , 23 , 24 , 24 , 24 , 24 , 24 , 25 , 25 , 25 , 25 , 25 ,
26 , 26 , 26 , 26 , 26 , 27 , 27 , 27 , 27 , 28 , 28 , 28 , 28 , 28 , 29 , 29 , 29 , 29 , 29 , 30 ,
30 , 30 , 30 , 30 , 31 , 31 , 31 , 31 , 31 , 32 , 32 , 32 , 32 , 32 , 33 , 33 , 33 , 33 , 33 , 34 ,
34 , 34 , 34 , 34 , 35 , 35 , 35 , 35 , 35 , 36 , 36 , 36 , 36 , 36 , 37 , 37 , 37 , 37 , 38 , 38 ,
38 , 38 , 38 , 39 , 39 , 39 , 39 , 39 , 40 , 40 , 40 , 40 , 40 , 41 , 41 , 41 , 41 , 41 , 42 , 42 ,
42 , 42 , 42 , 43 , 43 , 43 , 43 , 43 , 44 , 44 , 44 , 44 , 44 , 45 , 45 , 45 , 45 , 45 , 46 , 46 ,
46 , 46 , 46 , 47 , 47 , 47 , 47 , 48 , 48 , 48 , 48 , 48 , 49 , 49 , 49 , 49 , 49 , 50 , 50 , 50 ,
50 , 50 , 51 , 51 , 51 , 51 , 51 , 52 , 52 , 52 , 52 , 52 , 53 , 53 , 53 , 53 , 53 , 54 , 54 , 54 ,
54 , 54 , 55 , 55 , 55 , 55 , 55 , 56 , 56 , 56 , 56 , 56 , 57 , 57 , 57 , 57 , 58 , 58 , 58 , 58 ,
58 , 59 , 59 , 59 , 59 , 59 , 60 , 60 , 60 , 60 , 60 , 61 , 61 , 61 , 61 , 61 , 62 , 62 , 62 , 62 ,
62 , 63 , 63 , 63 , 63 , 63 , 64 , 64 , 64 , 64 , 64 , 65 , 65 , 65 , 65 , 65 , 66 , 66 , 66 , 66 ,
66 , 67 , 67 , 67 , 67 , 68 , 68 , 68 , 68 , 68 , 69 , 69 , 69 , 69 , 69 , 70 , 70 , 70 , 70 , 70 ,
71 , 71 , 71 , 71 , 71 , 72 , 72 , 72 , 72 , 72 , 73 , 73 , 73 , 73 , 73 , 74 , 74 , 74 , 74 , 74 ,
75 , 75 , 75 , 75 , 75 , 76
};
const pow9x2_t v = { .hi = negative_base_lut[e].hi, .lo = negative_base_lut[e].lo, .e = negative_index_lut[e] };
return v;
}
static inline void ldouble_convert(diy_fp_t *v)
{
uint64_t f = v->f;
int32_t e = v->e, t = v->e;
pow9x2_t x;
uint64_t hi, lo;
e >>= 2;
t -= e << 2;
if (t) {
++e;
f >>= 4 - t;
}
x = e >= 0 ? positive_diy_fp(e) : negative_diy_fp(-e);
hi = f / 1000000000;
lo = f - hi * 1000000000;
if (x.lo && lo) {
f = x.hi * hi + (x.hi * lo + x.lo * hi + (x.lo * lo) / 1000000000) / 1000000000;
} else {
f = x.hi * hi + (x.hi * lo + x.lo * hi) / 1000000000;
}
#if LSHIFT_RESERVED_BIT > 10
v->f = f;
v->e = e - x.e + 18;
#elif LSHIFT_RESERVED_BIT > 7
v->f = f / 10;
v->e = e - x.e + 19;
#elif LSHIFT_RESERVED_BIT > 4
v->f = f / 100;
v->e = e - x.e + 20;
#else
v->f = f / 1000;
v->e = e - x.e + 21;
#endif
}
#else
/*
# python to get lut
def print_pow_array(unit, index, end, positive):
cmp_value = 10000000000000000000 # ULONG_MAX = 18446744073709551615
base_lut = []
index_lut = []
for i in range(end + 1):
a = unit ** i
b = a
j = 0
if a < cmp_value:
while b < cmp_value:
j += 1
b = a * (10 ** j)
j -= 1
b = a * (10 ** j)
j = i * index + j
else:
while b >= cmp_value:
j += 1
b = a // (10 ** j)
b = a // (10 ** j)
if b != cmp_value:
b += 1;
j = i * index - j
#print('%-3d: %d 0x%016x %d' % (i, j, b, b))
base_lut.append(b)
index_lut.append(j)
print('static const uint64_t %s_base_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 4 == 0:
print()
print(' ', end='')
print('0x%016x' % (base_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
print()
print('static const int8_t %s_index_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 20 == 0:
print()
print(' ', end='')
print('%-3d' % (index_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
def print_positive_array():
# 1 * (2 ** 4) = 1.6 * (10 ** 1)
# 16 = 1.6 * (10 ** 1)
# 243 = (1023 - 52 - (11 - x)) / 4 + 1
print_pow_array(16, 1, 243, True)
def print_negative_array():
# 1 * (2 ** -4) = 0.625 * (10 ** -1)
# 625 = 0.625 * (10 ** 3)
# 285 = (1022 + 52 + (63 - (11 - x))) / 4 + 1
print_pow_array(625, 3, 285, False)
print_positive_array()
print()
print_negative_array()
*/
static inline diy_fp_t positive_diy_fp(int32_t e)
{
static const uint64_t positive_base_lut[244] = {
0x0de0b6b3a7640000, 0x16345785d8a00000, 0x2386f26fc1000000, 0x38d7ea4c68000000,
0x5af3107a40000000, 0x0e8d4a5100000000, 0x174876e800000000, 0x2540be4000000000,
0x3b9aca0000000000, 0x5f5e100000000000, 0x0f42400000000000, 0x186a000000000000,
0x2710000000000000, 0x3e80000000000000, 0x6400000000000000, 0x1000000000000000,
0x199999999999999a, 0x28f5c28f5c28f5c3, 0x4189374bc6a7ef9e, 0x68db8bac710cb296,
0x10c6f7a0b5ed8d37, 0x1ad7f29abcaf4858, 0x2af31dc4611873c0, 0x44b82fa09b5a52cc,
0x6df37f675ef6eae0, 0x119799812dea111a, 0x1c25c268497681c3, 0x2d09370d42573604,
0x480ebe7b9d58566d, 0x734aca5f6226f0ae, 0x12725dd1d243aba1, 0x1d83c94fb6d2ac35,
0x2f394219248446bb, 0x4b8ed0283a6d3df8, 0x78e480405d7b9659, 0x1357c299a88ea76b,
0x1ef2d0f5da7dd8ab, 0x318481895d962777, 0x4f3a68dbc8f03f25, 0x7ec3daf941806507,
0x14484bfeebc29f87, 0x2073accb12d0ff3e, 0x33ec47ab514e652f, 0x5313a5dee87d6eb1,
0x84ec3c97da624ab5, 0x154484932d2e725b, 0x22073a8515171d5e, 0x3671f73b54f1c896,
0x571cbec554b60dbc, 0x0df01e85f912e37b, 0x164cfda3281e38c4, 0x23ae629ea696c139,
0x391704310a8acec2, 0x5b5806b4ddaae469, 0x0e9d71b689dde71b, 0x17624f8a762fd82c,
0x256a18dd89e626ac, 0x3bdcf495a9703de0, 0x5fc7edbc424d2fcc, 0x0f53304714d9265e,
0x18851a0b548ea3ca, 0x273b5cdeedb10610, 0x3ec56164af81a34c, 0x646f023ab2690546,
0x1011c2eaabe7d7e3, 0x19b604aaaca62637, 0x29233aaaadd6a38b, 0x41d1f7777c8a9f45,
0x694ff258c7443208, 0x10d9976a5d52975e, 0x1af5bf109550f22f, 0x2b22cb4dbbb4b6b2,
0x4504787c5f878ab6, 0x6e6d8d93cc0c1123, 0x11ab20e472914a6c, 0x1c45016d841baa47,
0x2d3b357c0692aa0b, 0x485ebbf9a41ddcdd, 0x73cac65c39c96162, 0x1286d80ec190dc62,
0x1da48ce468e7c703, 0x2f6dae3a4172d804, 0x4be2b05d35848cd3, 0x796ab3c855a0e152,
0x136d3b7c36a919d0, 0x1f152bf9f10e8fb3, 0x31bb798fe8174c51, 0x4f925c1973587a1c,
0x7f50935bebc0c35f, 0x145ecfe5bf520ac8, 0x2097b309321cde0c, 0x3425eb41e9c7c9ad,
0x536fdecfdc72dc48, 0x857fcae62d8493a6, 0x155c2076bf9a5511, 0x222d00bdff5d54e7,
0x36ae679665622172, 0x577d728a3bd03582, 0x0dff9772470297ec, 0x1665bf1d3e6a8cad,
0x23d5fe9530aa7aae, 0x39566421e7772ab0, 0x5bbd6d030bf1dde6, 0x0eadab0aba3b2dbf,
0x177c44ddf6c515fe, 0x2593a163246e8996, 0x3c1f689ea0b0dc23, 0x603240fdcde7c69d,
0x0f64335bcf065d38, 0x18a0522c7e709527, 0x2766e9e0ca4dbb71, 0x3f0b0fce107c5f1a,
0x64de7fb01a60982a, 0x1023998cd1053711, 0x19d28f47b4d524e8, 0x2950e53f87bb6e40,
0x421b0865a5f8b066, 0x69c4da3c3cc11a3d, 0x10ec4be0ad8f8952, 0x1b13ac9aaf4c0ee9,
0x2b52adc44bace4a8, 0x45511606df7b0773, 0x6ee8233e325e7251, 0x11bebdf578b2f392,
0x1c6463225ab7ec1d, 0x2d6d6b6a2abfe02f, 0x48af1243779966b1, 0x744b506bf28f0ab4,
0x129b69070816e2fe, 0x1dc574d80cf16b30, 0x2fa2548ce182451a, 0x4c36edae359d3b5c,
0x79f17c49ef61f894, 0x1382cc34ca2427c6, 0x1f37ad21436d0c70, 0x31f2ae9b9f14e0b3,
0x4feab0f8fe87cdea, 0x7fdde7f4ca72e310, 0x14756ccb01abfb5f, 0x20bbe144cf799232,
0x345fced47f28e9e9, 0x53cc7e20cb74a974, 0x8613fd0145877586, 0x1573d68f903ea22a,
0x2252f0e5b39769dd, 0x36eb1b091f58a961, 0x57de91a832277568, 0x0e0f218b8d25088c,
0x167e9c127b6e7413, 0x23fdc683f8b0b9b8, 0x39960a6cc11ac2bf, 0x5c2343e134f79dfe,
0x0ebdf661791d60f6, 0x179657025b6234bc, 0x25bd5803c569edfa, 0x3c62266c6f0fe329,
0x609d0a4718196b74, 0x0f7549530e188c13, 0x18bba884e35a79b8, 0x2792a73b055d8f8c,
0x3f510b91a22f4c13, 0x654e78e9037ee01e, 0x103583fc527ab338, 0x19ef3993b72ab85a,
0x297ec285f1ddf3c3, 0x42646a6fe9631f9e, 0x6a3a43e642383296, 0x10ff151a99f482fa,
0x1b31bb5dc320d18f, 0x2b82c562d1ce1c18, 0x459e089e1c7cf9c0, 0x6f6340fcfa618f99,
0x11d270cc51055ea8, 0x1c83e7ad4e6efdda, 0x2d9fd9154a4b2fc3, 0x48ffc1bbaa11e604,
0x74cc692c434fd66c, 0x12b010d3e1cf5582, 0x1de6815302e5559d, 0x2fd735519e3bbc2e,
0x4c8b888296c5f9e3, 0x7a78da6a8ad65c9e, 0x139874ddd8c6234d, 0x1f5a549627a36bae,
0x322a20f03f6bdf7d, 0x504367e6cbdfcbfa, 0x806bd9714632dff7, 0x148c22ca71a1bd70,
0x20e037aa4f692f19, 0x3499f2aa18a84b5a, 0x542984435aa6def6, 0x86a8d39ef77164bd,
0x158ba6fab6f36c48, 0x22790b2abe5246d9, 0x372811ddfd50715a, 0x58401c96621a4ef7,
0x0e1ebce4dc7f16e0, 0x169794a160cb57cd, 0x2425ba9bce122614, 0x39d5f75fb01d09ba,
0x5c898bcc4cfb42c3, 0x0ece53cec4a314ec, 0x17b08617a104ee47, 0x25e73cf29b3b16d7,
0x3ca52e50f85e8af2, 0x61084a1b26fdab1c, 0x0f867241c8cc6d4d, 0x18d71d360e13e214,
0x27be952349b969b9, 0x3f97550542c242c1, 0x65beee6ed136d135, 0x1047824f2bb6d9cb,
0x1a0c03b1df8af612, 0x29acd2b63277f01c, 0x42ae1df050bfe694, 0x6ab02fe6e79970ec,
0x1111f32f2f4bc026, 0x1b4feb7eb212cd0a, 0x2bb31264501e14dc, 0x45eb50a08030215f,
0x6fdee76733803565, 0x11e6398126f5cb1b, 0x1ca38f350b22de91, 0x2dd27ebb4504974e,
0x4950cac53b3a8bb0, 0x754e113b91f745e6, 0x12c4cf8ea6b6ec77, 0x1e07b27dd78b13f2,
0x300c50c958de864f, 0x4ce0814227ca707e, 0x7b00ced03faa4d96, 0x13ae3591f5b4d937,
0x1f7d228322baf525, 0x3261d0d1d12b21d4, 0x509c814fb511cfba, 0x80fa687f881c7f8f,
0x14a2f1ffecd15c17, 0x2104b66647b56025, 0x34d4570a0c5566a1, 0x5486f1a9ad557102,
0x873e4f75e2224e69, 0x15a391d56bdc876d, 0x229f4fbbdfc73f15, 0x37654c5fcc71fe88
};
static const int8_t positive_index_lut[244] = {
18 , 18 , 18 , 18 , 18 , 17 , 17 , 17 , 17 , 17 , 16 , 16 , 16 , 16 , 16 , 15 , 15 , 15 , 15 , 15 ,
14 , 14 , 14 , 14 , 14 , 13 , 13 , 13 , 13 , 13 , 12 , 12 , 12 , 12 , 12 , 11 , 11 , 11 , 11 , 11 ,
10 , 10 , 10 , 10 , 10 , 9 , 9 , 9 , 9 , 8 , 8 , 8 , 8 , 8 , 7 , 7 , 7 , 7 , 7 , 6 ,
6 , 6 , 6 , 6 , 5 , 5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 2 ,
2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , -1 , -1 , -1 , -1 , -2 , -2 ,
-2 , -2 , -2 , -3 , -3 , -3 , -3 , -3 , -4 , -4 , -4 , -4 , -4 , -5 , -5 , -5 , -5 , -5 , -6 , -6 ,
-6 , -6 , -6 , -7 , -7 , -7 , -7 , -7 , -8 , -8 , -8 , -8 , -8 , -9 , -9 , -9 , -9 , -9 , -10, -10,
-10, -10, -10, -11, -11, -11, -11, -12, -12, -12, -12, -12, -13, -13, -13, -13, -13, -14, -14, -14,
-14, -14, -15, -15, -15, -15, -15, -16, -16, -16, -16, -16, -17, -17, -17, -17, -17, -18, -18, -18,
-18, -18, -19, -19, -19, -19, -19, -20, -20, -20, -20, -20, -21, -21, -21, -21, -22, -22, -22, -22,
-22, -23, -23, -23, -23, -23, -24, -24, -24, -24, -24, -25, -25, -25, -25, -25, -26, -26, -26, -26,
-26, -27, -27, -27, -27, -27, -28, -28, -28, -28, -28, -29, -29, -29, -29, -29, -30, -30, -30, -30,
-30, -31, -31, -31
};
const diy_fp_t v = { .f = positive_base_lut[e], .e = positive_index_lut[e] };
return v;
}
static inline diy_fp_t negative_diy_fp(int32_t e)
{
static const uint64_t negative_base_lut[286] = {
0x0de0b6b3a7640000, 0x56bc75e2d6310000, 0x3635c9adc5dea000, 0x21e19e0c9bab2400,
0x152d02c7e14af680, 0x84595161401484a0, 0x52b7d2dcc80cd2e4, 0x33b2e3c9fd0803cf,
0x204fce5e3e250262, 0x1431e0fae6d7217d, 0x7e37be2022c0914c, 0x4ee2d6d415b85acf,
0x314dc6448d9338c2, 0x1ed09bead87c0379, 0x13426172c74d822c, 0x785ee10d5da46d91,
0x4b3b4ca85a86c47b, 0x2f050fe938943acd, 0x1d6329f1c35ca4c0, 0x125dfa371a19e6f8,
0x72cb5bd86321e38d, 0x47bf19673df52e38, 0x2cd76fe086b93ce3, 0x1c06a5ec5433c60e,
0x118427b3b4a05bc9, 0x6d79f82328ea3da7, 0x446c3b15f9926688, 0x2ac3a4edbbfb8015,
0x1aba4714957d300e, 0x10b46c6cdd6e3e09, 0x6867a5a867f103b3, 0x4140c78940f6a250,
0x28c87cb5c89a2572, 0x197d4df19d605768, 0x0fee50b7025c36a1, 0x63917877cec0556c,
0x3e3aeb4ae1383563, 0x26e4d30eccc3215e, 0x184f03e93ff9f4db, 0x0f316271c7fc3909,
0x5ef4a74721e86477, 0x3b58e88c75313eca, 0x25179157c93ec73f, 0x172ebad6ddc73c87,
0x0e7d34c64a9c85d5, 0x5a8e89d75252446f, 0x3899162693736ac6, 0x235fadd81c2822bc,
0x161bcca7119915b6, 0x8a2dbf142dfcc7ac, 0x565c976c9cbdfccc, 0x35f9dea3e1f6bdff,
0x21bc2b266d3a36c0, 0x15159af804446238, 0x83c7088e1aab65dc, 0x525c6558d0ab1faa,
0x3379bf57826af3ca, 0x202c1796b182d85f, 0x141b8ebe2ef1c73b, 0x7dac3c24a5671d30,
0x4e8ba596e760723e, 0x3117477e509c4767, 0x1eae8caef261aca1, 0x132d17ed577d0be5,
0x77d9d58b62cd8a52, 0x4ae825771dc07673, 0x2ed1176a72984a08, 0x1d42aea2879f2e45,
0x1249ad2594c37cec, 0x724c7a2ae1c5ccbe, 0x476fcc5acd1b9ff7, 0x2ca5dfb8c03143fa,
0x1be7abd3781eca7d, 0x1170cb642b133e8e, 0x6d00f7320d3846f5, 0x44209a7f48432c5a,
0x2a94608f8d29fbb8, 0x1a9cbc59b83a3d53, 0x10a1f5b813246654, 0x67f43fbe77a37f8c,
0x40f8a7d70ac62fb8, 0x289b68e666bbddd3, 0x1961219000356aa4, 0x0fdcb4fa002162a7,
0x63236b1a80d0a88f, 0x3df622f09082695a, 0x26b9d5d65a5181d8, 0x183425a5f872f127,
0x0f209787bb47d6b9, 0x5e8bb3105280fe00, 0x3b174fea33909ec0, 0x24ee91f2603a6338,
0x17151b377c247e03, 0x0e6d3102ad96cec2, 0x5a2a7250bcee8c3c, 0x385a8772761517a6,
0x233894a789cd2ec8, 0x16035ce8b6203d3d, 0x899504ae72497ebb, 0x55fd22ed076def35,
0x35be35d424a4b581, 0x2196e1a496e6f171, 0x14fe4d06de5056e7, 0x8335616aed761f20,
0x52015ce2d469d374, 0x3340da0dc4c22429, 0x200888489af9569a, 0x1405552d60dbd620,
0x7d21545b9d5dfa47, 0x4e34d4b9425abc6c, 0x30e104f3c978b5c4, 0x1e8ca3185deb719b,
0x1317e5ef3ab32701, 0x77555d172edfb3c3, 0x4a955a2e7d4bd05a, 0x2e9d585d0e4f6238,
0x1d22573a28f19d63, 0x123576845997025e, 0x71ce24bb2fefcecb, 0x4720d6f4fdf5e13f,
0x2c7486591eb9acc8, 0x1bc8d3f7b3340bfd, 0x115d847ad000877e, 0x6c887bff94034ed3,
0x43d54d7fbc821144, 0x2a65506fd5d14acb, 0x1a7f5245e5a2cebf, 0x108f936baf85c137,
0x678159610903f798, 0x40b0d7dca5a27abf, 0x286e86e9e7858cb8, 0x1945145230b377f3,
0x0fcb2cb35e702af8, 0x62b5d7610e3d0c8c, 0x3db1a69ca8e627d7, 0x268f0821e98fd8e7,
0x1819651531f9e790, 0x0f0fdf2d3f3c30ba, 0x5e2332dacb38308b, 0x3ad5ffc8bf031e57,
0x24c5bfdd7761f2f7, 0x16fb97ea6a9d37da, 0x0e5d3ef282a242e9, 0x59c6c96bb076222b,
0x381c3de34e49d55b, 0x2311a6ae10ee2559, 0x15eb082cca94d758, 0x88fcf317f22241e3,
0x559e17eef755692e, 0x3582cef55a9561bd, 0x2171c159589d5d16, 0x14e718d7d7625a2e,
0x82a45b450226b39d, 0x51a6b90b21583043, 0x330833a6f4d71e2a, 0x1fe52048590672da,
0x13ef342d37a407c9, 0x7c97061a9bc130a3, 0x4dde63d0a158be66, 0x30aafe6264d77700,
0x1e6adefd7f06aa60, 0x1302cb5e6f642a7c, 0x76d1770e38320987, 0x4a42ea68e31f45f4,
0x2e69d2818df38bb9, 0x1d022390f8b83754, 0x1221563a9b732295, 0x71505aee4b8f981e,
0x46d238d4ef39bf13, 0x2c4363851584176c, 0x1baa1e332d728ea4, 0x114a52dffc679926,
0x6c1085f7e9877d2e, 0x438a53baf1f4ae3d, 0x2a367454d738ece6, 0x1a6208b506839410,
0x107d457124123c8a, 0x670ef2032171fa5d, 0x40695741f4e73c7a, 0x2841d689391085cd,
0x19292615c3aa53a0, 0x0fb9b7cd9a4a7444, 0x6248bcc5045156a8, 0x3d6d75fb22b2d629,
0x266469bcf5afc5da, 0x17fec216198ddba8, 0x0eff394dcff8a949, 0x5dbb262653d22208,
0x3a94f7d7f4635545, 0x249d1ae6f8be154c, 0x16e230d05b76cd4f, 0x0e4d5e82392a4052,
0x59638eade54811fd, 0x37de392caf4d0b3e, 0x22eae3bbed902707, 0x15d2ce55747a1865,
0x8865899617fb1872, 0x553f75fdcefcef47, 0x3547a9bea15e158d, 0x214cca1724dacd78,
0x14cffe4e7708c06b, 0x8213f56a67f6b29c, 0x514c796280fa2fa2, 0x32cfcbdd909c5dc5,
0x1fc1df6a7a61ba9b, 0x13d92ba28c7d14a1, 0x7c0d50b7ee0dc0ee, 0x4d885272f4c89895,
0x30753387d8fd5f5d, 0x1e494034e79e5b9a, 0x12edc82110c2f941, 0x764e22cea8c295d2,
0x49f0d5c129799da3, 0x2e368598b9ec0286, 0x1ce2137f74338194, 0x120d4c2fa8a030fd,
0x70d31c29dde93229, 0x4683f19a2ab1bf5a, 0x2c1277005aaf1798, 0x1b8b8a6038ad6ebf,
0x1137367c236c6538, 0x6b991487dd65789a, 0x433facd4ea5f6b61, 0x2a07cc05127ba31d,
0x1a44df832b8d45f2, 0x106b0bb1fb384bb7, 0x669d0918621fd938, 0x402225af3d53e7c3,
0x2815578d865470da, 0x190d56b873f4c689, 0x0fa856334878fc16, 0x61dc1ac084f42784,
0x3d2990b8531898b3, 0x2639fa7333ef5f70, 0x17e43c8800759ba6, 0x0eeea5d500498148,
0x5d538c7341cb67ff, 0x3a5437c8091f2100, 0x2474a2dd05b374a0, 0x16c8e5ca239028e4,
0x0e3d8f9e563a198f, 0x5900c19d9aeb1fba, 0x37a0790280d2f3d4, 0x22c44ba19083d865,
0x15baaf44fa52673f, 0x87cec76f1c830549, 0x54e13ca571d1e34e, 0x350cc5e767232e11,
0x2127fbb0a075fccb, 0x14b8fd4e6449bdff, 0x81842f29f2cce376, 0x50f29d7a37c00e2a,
0x3297a26c62d808db, 0x1f9ec583bdc70589, 0x13c33b72569c6376, 0x7b84338a9d516d9d,
0x4d32a036a252e482, 0x303fa4222573ced2, 0x1e27c69557686143, 0x12d8dc1d56a13cca,
0x75cb5fb75d6fbbed, 0x499f1bd29a65d574, 0x2e037163a07fa569, 0x1cc226de444fc762,
0x11f9584aeab1dc9d, 0x705667d43ad7a2d4, 0x463600e4a4c6c5c5, 0x2be1c08ee6fc3b9b,
0x1b6d1859505da541, 0x11242f37d23a8749, 0x6b22271ce1edcd85, 0x42f558720d34a073,
0x29d957474840e448, 0x1a27d68c8d288ead, 0x1058e617d839592d, 0x662b9e1507666d54,
0x3fdb42cd24a00455, 0x27e909c036e402b5, 0x18f1a618224e81b1, 0x0f9707cf1571110f,
0x616ff0ce4602aa9b, 0x3ce5f680ebc1aaa1, 0x260fba1093590aa5, 0x17c9d44a5c17a6a7,
0x0ede24ae798ec829, 0x5cec654277bc62fc
};
static const int8_t negative_index_lut[286] = {
18 , 19 , 19 , 19 , 19 , 20 , 20 , 20 , 20 , 20 , 21 , 21 , 21 , 21 , 21 , 22 , 22 , 22 , 22 , 22 ,
23 , 23 , 23 , 23 , 23 , 24 , 24 , 24 , 24 , 24 , 25 , 25 , 25 , 25 , 25 , 26 , 26 , 26 , 26 , 26 ,
27 , 27 , 27 , 27 , 27 , 28 , 28 , 28 , 28 , 29 , 29 , 29 , 29 , 29 , 30 , 30 , 30 , 30 , 30 , 31 ,
31 , 31 , 31 , 31 , 32 , 32 , 32 , 32 , 32 , 33 , 33 , 33 , 33 , 33 , 34 , 34 , 34 , 34 , 34 , 35 ,
35 , 35 , 35 , 35 , 36 , 36 , 36 , 36 , 36 , 37 , 37 , 37 , 37 , 37 , 38 , 38 , 38 , 38 , 39 , 39 ,
39 , 39 , 39 , 40 , 40 , 40 , 40 , 40 , 41 , 41 , 41 , 41 , 41 , 42 , 42 , 42 , 42 , 42 , 43 , 43 ,
43 , 43 , 43 , 44 , 44 , 44 , 44 , 44 , 45 , 45 , 45 , 45 , 45 , 46 , 46 , 46 , 46 , 46 , 47 , 47 ,
47 , 47 , 47 , 48 , 48 , 48 , 48 , 49 , 49 , 49 , 49 , 49 , 50 , 50 , 50 , 50 , 50 , 51 , 51 , 51 ,
51 , 51 , 52 , 52 , 52 , 52 , 52 , 53 , 53 , 53 , 53 , 53 , 54 , 54 , 54 , 54 , 54 , 55 , 55 , 55 ,
55 , 55 , 56 , 56 , 56 , 56 , 56 , 57 , 57 , 57 , 57 , 57 , 58 , 58 , 58 , 58 , 59 , 59 , 59 , 59 ,
59 , 60 , 60 , 60 , 60 , 60 , 61 , 61 , 61 , 61 , 61 , 62 , 62 , 62 , 62 , 62 , 63 , 63 , 63 , 63 ,
63 , 64 , 64 , 64 , 64 , 64 , 65 , 65 , 65 , 65 , 65 , 66 , 66 , 66 , 66 , 66 , 67 , 67 , 67 , 67 ,
67 , 68 , 68 , 68 , 68 , 69 , 69 , 69 , 69 , 69 , 70 , 70 , 70 , 70 , 70 , 71 , 71 , 71 , 71 , 71 ,
72 , 72 , 72 , 72 , 72 , 73 , 73 , 73 , 73 , 73 , 74 , 74 , 74 , 74 , 74 , 75 , 75 , 75 , 75 , 75 ,
76 , 76 , 76 , 76 , 76 , 77
};
const diy_fp_t v = { .f = negative_base_lut[e], .e = negative_index_lut[e] };
return v;
}
static inline void ldouble_convert(diy_fp_t *v)
{
uint64_t f = v->f;
int32_t e = v->e, t = v->e;
diy_fp_t x;
e >>= 2;
t -= e << 2;
if (t) {
++e;
f >>= 4 - t;
}
x = e >= 0 ? positive_diy_fp(e) : negative_diy_fp(-e);
f = u128_calc(x.f, f);
#if LSHIFT_RESERVED_BIT > 10
v->f = f;
v->e = e - x.e + 19;
#elif LSHIFT_RESERVED_BIT > 7
v->f = f / 10;
v->e = e - x.e + 20;
#elif LSHIFT_RESERVED_BIT > 4
v->f = f / 100;
v->e = e - x.e + 21;
#else
v->f = f / 1000;
v->e = e - x.e + 22;
#endif
}
#endif
static inline int32_t fill_a_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
memcpy(s, &ch_100_lut[q<<1], 2);
memcpy(s + 2, &ch_100_lut[r<<1], 2);
if (r < s_tail_cmp) {
*ptz = tz_100_lut[q] + 2;
} else {
if (s[3] < (char)s_tail_cmp + '0') {
s[3] = '0';
*ptz = 1;
} else {
s[3] -= APPROX_TAIL_CMP_VAL;
*ptz = 0;
}
}
return 4;
}
static inline int32_t fill_a_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
memset(s, '0', 4);
fill_a_4_digits(s + 4, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
fill_t_4_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s + 4, '0', 4);
*ptz += 4;
} else {
fill_a_4_digits(s + 4, r, ptz);
}
}
return 8;
}
static inline int32_t fill_a_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
memset(s, '0', 8);
fill_a_8_digits(s + 8, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
fill_t_8_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s + 8, '0', 8);
*ptz += 8;
} else {
fill_a_8_digits(s + 8, r, ptz);
}
}
return 16;
}
static inline int32_t fill_significand(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
digits += APPROX_TAIL_CMP_VAL;
if (digits < 10000000000000000llu) {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
s += fill_1_8_digits(s, q, ptz);
if (r < s_tail_cmp) {
*ptz += 8;
memset(s, '0', 8);
s += 8;
} else {
s += fill_a_8_digits(s, r, ptz);
}
} else {
uint32_t q = (uint32_t)(digits / 10000000000000000llu);
uint64_t r = (digits - (uint64_t)q * 10000000000000000llu);
s += fill_1_4_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s, '0', 16);
s += 16;
*ptz += 16;
} else {
s += fill_a_16_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_exponent(int32_t K, char* buffer)
{
int32_t i = 0, k = 0;
if (K < 0) {
buffer[i++] = '-';
K = -K;
} else {
buffer[i++] = '+';
}
if (K < 100) {
if (K < 10) {
buffer[i++] = '0' + K;
} else {
memcpy(&buffer[i], &ch_100_lut[K<<1], 2);
i += 2;
}
} else {
k = FAST_DIV100(K);
K -= k * 100;
buffer[i++] = '0' + k;
memcpy(&buffer[i], &ch_100_lut[K<<1], 2);
i += 2;
}
return i;
}
static inline char* ldouble_format(char* buffer, uint64_t digits, int32_t decimal_exponent)
{
int32_t num_digits, trailing_zeros, vnum_digits, decimal_point;
num_digits = fill_significand(buffer + 1, digits, &trailing_zeros);
vnum_digits = num_digits - trailing_zeros;
decimal_point = num_digits + decimal_exponent;
switch (decimal_point) {
case -6: case -5: case -4: case -3: case -2: case -1: case 0:
/* 0.[000]digits */
memmove(buffer + 2 - decimal_point, buffer + 1, vnum_digits);
memset(buffer, '0', 2 - decimal_point);
buffer[1] = '.';
buffer += 2 - decimal_point + vnum_digits;
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17:
if (decimal_point < vnum_digits) {
/* dig.its */
memmove(buffer, buffer + 1, decimal_point);
buffer[decimal_point] = '.';
buffer += vnum_digits + 1;
} else {
/* digits[000] */
memmove(buffer, buffer + 1, decimal_point);
buffer += decimal_point;
memcpy(buffer, ".0", 2);
buffer += 2;
}
break;
default:
buffer[0] = buffer[1];
++buffer;
if (vnum_digits != 1) {
/* d.igitsE+123 */
*buffer = '.';
buffer += vnum_digits;
} else {
/* dE+123 */
}
*buffer++ = 'e';
buffer += fill_exponent(decimal_point - 1, buffer);
break;
}
*buffer = '\0';
return buffer;
}
static int ldouble_dtoa(double value, char* buffer)
{
diy_fp_t v;
char *s = buffer;
int32_t lshiftbit = 11 - LSHIFT_RESERVED_BIT;
union {double d; uint64_t n;} u = {.d = value};
int32_t signbit = u.n >> (DIY_SIGNIFICAND_SIZE - 1);
int32_t exponent = (u.n & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE; /* Exponent */
uint64_t significand = u.n & DP_SIGNIFICAND_MASK; /* Mantissa */
if (signbit) {
*s++ = '-';
}
switch (exponent) {
case DP_EXPONENT_MAX:
if (significand) {
memcpy(buffer, "nan", 4);
return 3;
} else {
memcpy(s, "inf", 4);
return signbit + 3;
}
break;
case 0:
if (!significand) {
/* no-normalized double */
v.f = significand; /* Non-normalized double doesn't have a extra integer bit for Mantissa */
v.e = 1 - DP_EXPONENT_OFFSET - DP_SIGNIFICAND_SIZE; /* Fixed Exponent: -1022, divisor of Mantissa: pow(2,52) */
lshiftbit = u64_pz_get(v.f) - LSHIFT_RESERVED_BIT;
v.f <<= lshiftbit;
v.e -= lshiftbit; /* The smallest e is (-1022 - 52 - (63 - LSHIFT_RESERVED_BIT)) */
} else {
memcpy(s, "0.0", 4);
return signbit + 3;
}
break;
default:
/* normalized double */
v.f = significand + DP_HIDDEN_BIT; /* Normalized double has a extra integer bit for Mantissa */
v.e = exponent - DP_EXPONENT_OFFSET - DP_SIGNIFICAND_SIZE; /* Exponent offset: -1023, divisor of Mantissa: pow(2,52) */
if (0 <= -v.e && -v.e <= DP_SIGNIFICAND_SIZE && ((v.f & (((uint64_t)1 << -v.e) - 1)) == 0)) {
/* small integer. */
int32_t tz, n;
n = fill_1_20_digits(s, v.f >> -v.e, &tz);
memcpy(s + n, ".0", 3);
return n + 2 + signbit;
} else {
v.f <<= lshiftbit;
v.e -= lshiftbit; /* The largest e is (1023 - 52 - (11 - LSHIFT_RESERVED_BIT)) */
}
break;
}
ldouble_convert(&v);
s = ldouble_format(s, v.f, v.e);
return s - buffer;
}
#define double_to_string ldouble_dtoa
#endif
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 += (long long)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;
str = jstr->str;
len = jstr->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 << 1) + 3;
#else
alloced = (len << 2) + (len << 1) + 3;
#endif
_PRINT_PTR_REALLOC(alloced);
*print_ptr->cur++ = '\"';
bak = str;
while (1) {
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;
case '\0':
_JSON_PRINT_SEGMENT();
*print_ptr->cur++ = '\"';
return 0;
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;
}
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_STRICT_PARSE_MODE
JsonErr("key is null!\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_STRICT_PARSE_MODE
JsonErr("key is null!\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(int_to_string, json->value.vnum.vint);
break;
case JSON_HEX:
_PRINT_PTR_NUMBER(hex_to_string, json->value.vnum.vhex);
break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
_PRINT_PTR_NUMBER(lint_to_string, json->value.vnum.vlint);
break;
case JSON_LHEX:
_PRINT_PTR_NUMBER(lhex_to_string, json->value.vnum.vlhex);
break;
#endif
case JSON_DOUBLE:
_PRINT_PTR_NUMBER(double_to_string, 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_STRICT_PARSE_MODE
JsonErr("key is null!\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_STRICT_PARSE_MODE
JsonErr("key is null!\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(int_to_string, *(int*)value);
break;
case JSON_HEX:
_PRINT_PTR_NUMBER(hex_to_string, *(unsigned int*)value);
break;
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
_PRINT_PTR_NUMBER(lint_to_string, *(long long int*)value);
break;
case JSON_LHEX:
_PRINT_PTR_NUMBER(lhex_to_string, *(unsigned long long int*)value);
break;
#endif
case JSON_DOUBLE:
_PRINT_PTR_NUMBER(double_to_string, *(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;
/* The two func ptrs are only for DOM parser */
int (*parse_string)(struct _json_parse_t *parse_ptr, 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;
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
static inline bool _hex_char_check(char c)
{
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return true;
default:
return false;
}
}
static inline bool _dec_char_check(char c)
{
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return true;
default:
return false;
}
}
static inline unsigned int _hex_char_calculate(char c)
{
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return c - '0';
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
return 10 + c - 'a';
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return 10 + c - 'A';
default:
return 0;
}
}
static int _parse_num(char **sstr, json_number_t *vnum)
{
int sign = 1, k = 0;
unsigned long long int m = 0, n = 0;
double d = 0;
char *num = *sstr;
if (*num == '0' && (*(num+1) == 'x' || *(num+1) == 'X')) {
num += 2;
while (_hex_char_check(*num))
m = (m << 4) + _hex_char_calculate(*num++);
*sstr = num;
if (m > UINT_MAX) {
#if JSON_LONG_LONG_SUPPORT
vnum->vlhex = m;
return JSON_LHEX;
#else
vnum->vdbl = m;
return JSON_DOUBLE;
#endif
} else {
vnum->vhex = m;
return JSON_HEX;
}
} else {
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,
};
switch (*num) {
case '-': ++num; sign = -1; break;
case '+': ++num; break;
default: break;
}
while (*num == '0')
++num;
k = 0;
while (_dec_char_check(*num)) {
m = (m << 3) + (m << 1) + (*num++ - '0');
++k;
}
if (k >= 20)
return 0xff;
if (*num == '.') {
++num;
k = 0;
while (_dec_char_check(*num)) {
n = (n << 3) + (n << 1) + (*num++ - '0');
++k;
}
if (k >= 20)
return 0xff;
d = m + n * div10_lut[k];
*sstr = num;
vnum->vdbl = sign == 1 ? d : -d;
return JSON_DOUBLE;
} else {
*sstr = num;
if (m > INT_MAX) {
#if JSON_LONG_LONG_SUPPORT
vnum->vlint = sign == 1 ? m : -m;
return JSON_LINT;
#else
vnum->vdbl = sign == 1 ? m : -m;
return JSON_DOUBLE;
#endif
} else {
vnum->vint = sign == 1 ? m : -m;
return JSON_INT;
}
}
}
return JSON_NULL;
}
static json_type_t _json_parse_number(char **sstr, json_number_t *vnum)
{
int ret = JSON_NULL;
const char *num = *sstr;
#if JSON_STRICT_PARSE_MODE == 2
if (*num == '0' && (*(num+1) == 'x' || *(num+1) == 'X' || _dec_char_check(*(num+1)))) {
JsonErr("leading zero can't be parsed in strict mode!\n");
return JSON_NULL;
}
#endif
ret = _parse_num(sstr, vnum);
switch (ret) {
case JSON_HEX:
#if JSON_LONG_LONG_SUPPORT
case JSON_LHEX:
#endif
return ret;
case JSON_INT:
#if JSON_LONG_LONG_SUPPORT
case JSON_LINT:
#endif
case JSON_DOUBLE:
switch (**sstr) {
case 'e': case 'E':
vnum->vdbl = strtod(num, sstr);
return JSON_DOUBLE;
default:
return ret;
}
break;
case 0xff:
vnum->vdbl = strtod(num, sstr);
return JSON_DOUBLE;
default:
return JSON_NULL;
}
}
static inline unsigned int _parse_hex4(const unsigned char *str)
{
int i = 0;
unsigned int 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;
}
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 (*str <= ' ') {
if (likely(*str)) {
++str;
++cnt;
} else {
goto next;
}
}
break;
next:
continue;
}
_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 (1) {
switch ((*str++)) {
case '\"':
size = str - last - 1;
memcpy(ptr, last, size);
ptr += size;
*ptr = '\0';
return (ptr - bak);
case '\0':
return -1;
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 '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;
break;
default:
break;
}
}
return -1;
}
static int _parse_strlen(json_parse_t *parse_ptr, bool *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 '\"':
total += str - bak;
return total;
case '\\':
if (likely(rsize != (str - bak))) {
++str;
*escaped = true;
} 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_STRICT_PARSE_MODE == 2
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in strict mode!\n");
goto err;
#endif
default:
break;
}
}
err:
JsonPareseErr("str format err!");
return -1;
}
static int _json_parse_string(json_parse_t *parse_ptr, json_string_t *jstr, json_mem_mgr_t *mgr)
{
char *ptr = NULL, *str = NULL;
bool escaped = false;
int len = 0, total = 0;
memset(jstr, 0, sizeof(json_string_t));
if (unlikely((total = _parse_strlen(parse_ptr, &escaped)) < 0)) {
return -1;
}
len = total - 2;
_get_parse_ptr(parse_ptr, 0, total, &str);
++str;
if (unlikely((ptr = _parse_alloc(parse_ptr, len + 1, mgr)) == NULL)) {
JsonErr("malloc failed!\n");
return -1;
}
if (likely(!escaped)) {
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;
jstr->len = len;
jstr->str = ptr;
return len;
err:
JsonPareseErr("parse string failed!");
return -1;
}
static int _json_parse_value(json_parse_t *parse_ptr, json_object **root)
{
json_string_t jkey = {0};
char *str = NULL, *bak = 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:
_skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 2, &str);
if (unlikely(str[0] != '\"')) {
JsonPareseErr("key is not started with quote!");
goto err;
}
if (unlikely(str[1] == '\"')) {
#if !JSON_STRICT_PARSE_MODE
JsonPareseErr("key is space!");
goto err;
#else
_UPDATE_PARSE_OFFSET(2);
#endif
} else {
if (unlikely(parse_ptr->parse_string(parse_ptr, &jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
}
_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);
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(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 128, &str);
switch (*str) {
case '\"':
item->type_member = JSON_STRING;
if (unlikely(str[1] == '\"')) {
memset(&item->value.vstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(2);
} else {
if (unlikely(parse_ptr->parse_string(parse_ptr, &item->value.vstr, &parse_ptr->mem->str_mgr) < 0)) {
goto err;
}
}
break;
case '-': case '+':
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(&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(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);
_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 '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;
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(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (parent->type_member == JSON_OBJECT) {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
goto next2;
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);
goto next3;
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;
}
static inline void _skip_blank_rapid(json_parse_t *parse_ptr)
{
unsigned char *str = (unsigned char *)(parse_ptr->str + parse_ptr->offset);
int cnt = 0;
while (*str <= ' ' && *str) {
++str;
++cnt;
}
_UPDATE_PARSE_OFFSET(cnt);
}
static int _json_parse_string_reuse(json_parse_t *parse_ptr, 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 ch = '\0';
memset(jstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(1);
end = parse_ptr->str + parse_ptr->size;
str = parse_ptr->str + parse_ptr->offset;
bak = str;
ptr = str;
jstr->str = str;
while (1) {
switch ((*str++)) {
case '\"':
len = str - bak;
_UPDATE_PARSE_OFFSET(len);
--len;
ptr[len] = '\0';
jstr->len = len;
return len;
case '\0':
goto err;
case '\\':
--str;
last = str;
ptr += str - bak;
goto next;
#if JSON_STRICT_PARSE_MODE == 2
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in strict mode!\n");
goto err;
#endif
default:
break;
}
}
next:
while (1) {
switch ((*str++)) {
case '\"':
size = str - last - 1;
memmove(ptr, last, size);
ptr += size;
*ptr = '\0';
len = str - bak;
_UPDATE_PARSE_OFFSET(len);
jstr->escaped = 1;
jstr->len = ptr - bak;
return jstr->len;
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 '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;
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, json_string_t *jstr, json_mem_mgr_t *mgr)
{
char *str = NULL, *bak = NULL, *ptr= NULL;
int len = 0, total = 0;
bool escaped = false;
memset(jstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(1);
str = parse_ptr->str + parse_ptr->offset;
bak = str;
while (1) {
switch ((*str++)) {
case '\"':
goto next;
case '\0':
goto err;
case '\\':
++str;
escaped = true;
break;
#if JSON_STRICT_PARSE_MODE == 2
case '\b': case '\f': case '\n': case '\r': case '\t': case '\v':
JsonErr("tab and linebreak can't be existed in string in strict mode!\n");
goto err;
#endif
default:
break;
}
}
next:
total = str - bak;
len = total - 1;
if (unlikely((ptr = _parse_alloc(parse_ptr, len + 1, mgr)) == NULL)) {
JsonErr("malloc failed!\n");
goto err;
}
if (likely(!escaped)) {
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;
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;
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;
if (unlikely(str[0] != '\"')) {
JsonPareseErr("key is not started with quote!");
goto err;
}
if (unlikely(str[1] == '\"')) {
#if !JSON_STRICT_PARSE_MODE
JsonPareseErr("key is space!");
goto err;
#else
_UPDATE_PARSE_OFFSET(2);
#endif
} else {
if (unlikely(parse_ptr->parse_string(parse_ptr, &jkey, &parse_ptr->mem->key_mgr) < 0)) {
goto err;
}
}
_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);
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 '\"':
item->type_member = JSON_STRING;
if (unlikely(str[1] == '\"')) {
memset(&item->value.vstr, 0, sizeof(json_string_t));
_UPDATE_PARSE_OFFSET(2);
} else {
if (unlikely(parse_ptr->parse_string(parse_ptr, &item->value.vstr, &parse_ptr->mem->str_mgr) < 0)) {
goto err;
}
}
break;
case '-': case '+':
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(&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;
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);
goto next2;
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);
goto next3;
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.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;
}
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_STRICT_PARSE_MODE == 2
_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_STRICT_PARSE_MODE
_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, json_string_t *jstr, bool key_flag)
{
char *ptr = NULL, *str = NULL;
int len = 0, total = 0;
bool escaped = false;
memset(jstr, 0, sizeof(json_string_t));
if (unlikely((total = _parse_strlen(parse_ptr, &escaped)) < 0)) {
return -1;
}
len = total - 2;
_get_parse_ptr(parse_ptr, 0, total, &str);
++str;
if (likely(!escaped)) {
if (!(parse_ptr->fd >= 0 && key_flag)) {
jstr->escaped = escaped;
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;
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 = escaped;
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, *bak = 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;
_skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 2, &str);
if (unlikely(str[0] != '\"')) {
JsonPareseErr("key is not started with quote!");
goto err;
}
if (unlikely(str[1] == '\"')) {
#if !JSON_STRICT_PARSE_MODE
JsonPareseErr("key is space!");
goto err;
#else
_UPDATE_PARSE_OFFSET(2);
#endif
} else {
if (unlikely(_json_sax_parse_string(parse_ptr, jkey, true) < 0)) {
goto err;
}
}
_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);
next3:
jkey = parse_ptr->parser.array + parse_ptr->parser.index;
_skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 128, &str);
switch (*str) {
case '\"':
jkey->type = JSON_STRING;
if (unlikely(str[1] == '\"')) {
memset(value, 0, sizeof(*value));
_UPDATE_PARSE_OFFSET(2);
} else {
if (unlikely(_json_sax_parse_string(parse_ptr, &value->vstr, false) < 0)) {
goto err;
}
}
break;
case '-': case '+':
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(&str, &value->vnum)) == JSON_NULL)) {
JsonPareseErr("Not number!");
goto err;
}
_UPDATE_PARSE_OFFSET(str - bak);
break;
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;
}
_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;
}
_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;
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;
default:
JsonPareseErr("invalid next ptr!");
goto err;
}
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)) {
_skip_blank(parse_ptr);
_get_parse_ptr(parse_ptr, 0, 1, &str);
if (parent->type == JSON_OBJECT) {
switch (*str) {
case ',':
_UPDATE_PARSE_OFFSET(1);
goto next2;
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);
goto next3;
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 = NULL;
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;
}
} else {
parse_val.str = choice->str;
parse_val.size = choice->str_len ? choice->str_len : strlen(choice->str);
}
parse_val.cb = choice->cb;
#if JSON_STRICT_PARSE_MODE == 2
_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_STRICT_PARSE_MODE
if (ret == 0) {
_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_STRICT_PARSE_MODE == 2
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 助手
尝试更多
代码解读
代码找茬
代码优化