| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846 |
- /*==============================================================================
- Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- *============================================================================*/
- /**
- @file yyjson.h
- @date 2019-03-09
- @author YaoYuan
- */
- #ifndef YYJSON_H
- #define YYJSON_H
- /*==============================================================================
- * Header Files
- *============================================================================*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <limits.h>
- #include <string.h>
- #include <float.h>
- /*==============================================================================
- * Compile-time Options
- *============================================================================*/
- /*
- Define as 1 to disable JSON reader if JSON parsing is not required.
-
- This will disable these functions at compile-time:
- - yyjson_read()
- - yyjson_read_opts()
- - yyjson_read_file()
- - yyjson_read_number()
- - yyjson_mut_read_number()
-
- This will reduce the binary size by about 60%.
- */
- #ifndef YYJSON_DISABLE_READER
- #endif
- /*
- Define as 1 to disable JSON writer if JSON serialization is not required.
-
- This will disable these functions at compile-time:
- - yyjson_write()
- - yyjson_write_file()
- - yyjson_write_opts()
- - yyjson_val_write()
- - yyjson_val_write_file()
- - yyjson_val_write_opts()
- - yyjson_mut_write()
- - yyjson_mut_write_file()
- - yyjson_mut_write_opts()
- - yyjson_mut_val_write()
- - yyjson_mut_val_write_file()
- - yyjson_mut_val_write_opts()
-
- This will reduce the binary size by about 30%.
- */
- #ifndef YYJSON_DISABLE_WRITER
- #endif
- /*
- Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports.
-
- This will disable these functions at compile-time:
- - yyjson_ptr_xxx()
- - yyjson_mut_ptr_xxx()
- - yyjson_doc_ptr_xxx()
- - yyjson_mut_doc_ptr_xxx()
- - yyjson_patch()
- - yyjson_mut_patch()
- - yyjson_merge_patch()
- - yyjson_mut_merge_patch()
- */
- #ifndef YYJSON_DISABLE_UTILS
- #endif
- /*
- Define as 1 to disable the fast floating-point number conversion in yyjson,
- and use libc's `strtod/snprintf` instead.
-
- This will reduce the binary size by about 30%, but significantly slow down the
- floating-point read/write speed.
- */
- #ifndef YYJSON_DISABLE_FAST_FP_CONV
- #endif
- /*
- Define as 1 to disable non-standard JSON support at compile-time:
- - Reading and writing inf/nan literal, such as `NaN`, `-Infinity`.
- - Single line and multiple line comments.
- - Single trailing comma at the end of an object or array.
- - Invalid unicode in string value.
-
- This will also invalidate these run-time options:
- - YYJSON_READ_ALLOW_INF_AND_NAN
- - YYJSON_READ_ALLOW_COMMENTS
- - YYJSON_READ_ALLOW_TRAILING_COMMAS
- - YYJSON_READ_ALLOW_INVALID_UNICODE
- - YYJSON_WRITE_ALLOW_INF_AND_NAN
- - YYJSON_WRITE_ALLOW_INVALID_UNICODE
-
- This will reduce the binary size by about 10%, and speed up the reading and
- writing speed by about 2% to 6%.
- */
- #ifndef YYJSON_DISABLE_NON_STANDARD
- #endif
- /*
- Define as 1 to disable UTF-8 validation at compile time.
-
- If all input strings are guaranteed to be valid UTF-8 encoding (for example,
- some language's String object has already validated the encoding), using this
- flag can avoid redundant UTF-8 validation in yyjson.
-
- This flag can speed up the reading and writing speed of non-ASCII encoded
- strings by about 3% to 7%.
-
- Note: If this flag is used while passing in illegal UTF-8 strings, the
- following errors may occur:
- - Escaped characters may be ignored when parsing JSON strings.
- - Ending quotes may be ignored when parsing JSON strings, causing the string
- to be concatenated to the next value.
- - When accessing `yyjson_mut_val` for serialization, the string ending may be
- accessed out of bounds, causing a segmentation fault.
- */
- #ifndef YYJSON_DISABLE_UTF8_VALIDATION
- #endif
- /*
- Define as 1 to indicate that the target architecture does not support unaligned
- memory access. Please refer to the comments in the C file for details.
- */
- #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
- #endif
- /* Define as 1 to export symbols when building this library as Windows DLL. */
- #ifndef YYJSON_EXPORTS
- #endif
- /* Define as 1 to import symbols when using this library as Windows DLL. */
- #ifndef YYJSON_IMPORTS
- #endif
- /* Define as 1 to include <stdint.h> for compiler which doesn't support C99. */
- #ifndef YYJSON_HAS_STDINT_H
- #endif
- /* Define as 1 to include <stdbool.h> for compiler which doesn't support C99. */
- #ifndef YYJSON_HAS_STDBOOL_H
- #endif
- /*==============================================================================
- * Compiler Macros
- *============================================================================*/
- /** compiler version (MSVC) */
- #ifdef _MSC_VER
- # define YYJSON_MSC_VER _MSC_VER
- #else
- # define YYJSON_MSC_VER 0
- #endif
- /** compiler version (GCC) */
- #ifdef __GNUC__
- # define YYJSON_GCC_VER __GNUC__
- # if defined(__GNUC_PATCHLEVEL__)
- # define yyjson_gcc_available(major, minor, patch) \
- ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
- >= (major * 10000 + minor * 100 + patch))
- # else
- # define yyjson_gcc_available(major, minor, patch) \
- ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \
- >= (major * 10000 + minor * 100 + patch))
- # endif
- #else
- # define YYJSON_GCC_VER 0
- # define yyjson_gcc_available(major, minor, patch) 0
- #endif
- /** real gcc check */
- #if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \
- defined(__GNUC__)
- # define YYJSON_IS_REAL_GCC 1
- #else
- # define YYJSON_IS_REAL_GCC 0
- #endif
- /** C version (STDC) */
- #if defined(__STDC__) && (__STDC__ >= 1) && defined(__STDC_VERSION__)
- # define YYJSON_STDC_VER __STDC_VERSION__
- #else
- # define YYJSON_STDC_VER 0
- #endif
- /** C++ version */
- #if defined(__cplusplus)
- # define YYJSON_CPP_VER __cplusplus
- #else
- # define YYJSON_CPP_VER 0
- #endif
- /** compiler builtin check (since gcc 10.0, clang 2.6, icc 2021) */
- #ifndef yyjson_has_builtin
- # ifdef __has_builtin
- # define yyjson_has_builtin(x) __has_builtin(x)
- # else
- # define yyjson_has_builtin(x) 0
- # endif
- #endif
- /** compiler attribute check (since gcc 5.0, clang 2.9, icc 17) */
- #ifndef yyjson_has_attribute
- # ifdef __has_attribute
- # define yyjson_has_attribute(x) __has_attribute(x)
- # else
- # define yyjson_has_attribute(x) 0
- # endif
- #endif
- /** compiler feature check (since clang 2.6, icc 17) */
- #ifndef yyjson_has_feature
- # ifdef __has_feature
- # define yyjson_has_feature(x) __has_feature(x)
- # else
- # define yyjson_has_feature(x) 0
- # endif
- #endif
- /** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */
- #ifndef yyjson_has_include
- # ifdef __has_include
- # define yyjson_has_include(x) __has_include(x)
- # else
- # define yyjson_has_include(x) 0
- # endif
- #endif
- /** inline for compiler */
- #ifndef yyjson_inline
- # if YYJSON_MSC_VER >= 1200
- # define yyjson_inline __forceinline
- # elif defined(_MSC_VER)
- # define yyjson_inline __inline
- # elif yyjson_has_attribute(always_inline) || YYJSON_GCC_VER >= 4
- # define yyjson_inline __inline__ __attribute__((always_inline))
- # elif defined(__clang__) || defined(__GNUC__)
- # define yyjson_inline __inline__
- # elif defined(__cplusplus) || YYJSON_STDC_VER >= 199901L
- # define yyjson_inline inline
- # else
- # define yyjson_inline
- # endif
- #endif
- /** noinline for compiler */
- #ifndef yyjson_noinline
- # if YYJSON_MSC_VER >= 1400
- # define yyjson_noinline __declspec(noinline)
- # elif yyjson_has_attribute(noinline) || YYJSON_GCC_VER >= 4
- # define yyjson_noinline __attribute__((noinline))
- # else
- # define yyjson_noinline
- # endif
- #endif
- /** align for compiler */
- #ifndef yyjson_align
- # if YYJSON_MSC_VER >= 1300
- # define yyjson_align(x) __declspec(align(x))
- # elif yyjson_has_attribute(aligned) || defined(__GNUC__)
- # define yyjson_align(x) __attribute__((aligned(x)))
- # elif YYJSON_CPP_VER >= 201103L
- # define yyjson_align(x) alignas(x)
- # else
- # define yyjson_align(x)
- # endif
- #endif
- /** likely for compiler */
- #ifndef yyjson_likely
- # if yyjson_has_builtin(__builtin_expect) || \
- (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
- # define yyjson_likely(expr) __builtin_expect(!!(expr), 1)
- # else
- # define yyjson_likely(expr) (expr)
- # endif
- #endif
- /** unlikely for compiler */
- #ifndef yyjson_unlikely
- # if yyjson_has_builtin(__builtin_expect) || \
- (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
- # define yyjson_unlikely(expr) __builtin_expect(!!(expr), 0)
- # else
- # define yyjson_unlikely(expr) (expr)
- # endif
- #endif
- /** compile-time constant check for compiler */
- #ifndef yyjson_constant_p
- # if yyjson_has_builtin(__builtin_constant_p) || (YYJSON_GCC_VER >= 3)
- # define YYJSON_HAS_CONSTANT_P 1
- # define yyjson_constant_p(value) __builtin_constant_p(value)
- # else
- # define YYJSON_HAS_CONSTANT_P 0
- # define yyjson_constant_p(value) 0
- # endif
- #endif
- /** deprecate warning */
- #ifndef yyjson_deprecated
- # if YYJSON_MSC_VER >= 1400
- # define yyjson_deprecated(msg) __declspec(deprecated(msg))
- # elif yyjson_has_feature(attribute_deprecated_with_message) || \
- (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5))
- # define yyjson_deprecated(msg) __attribute__((deprecated(msg)))
- # elif YYJSON_GCC_VER >= 3
- # define yyjson_deprecated(msg) __attribute__((deprecated))
- # else
- # define yyjson_deprecated(msg)
- # endif
- #endif
- /** function export */
- #ifndef yyjson_api
- # if defined(_WIN32)
- # if defined(YYJSON_EXPORTS) && YYJSON_EXPORTS
- # define yyjson_api __declspec(dllexport)
- # elif defined(YYJSON_IMPORTS) && YYJSON_IMPORTS
- # define yyjson_api __declspec(dllimport)
- # else
- # define yyjson_api
- # endif
- # elif yyjson_has_attribute(visibility) || YYJSON_GCC_VER >= 4
- # define yyjson_api __attribute__((visibility("default")))
- # else
- # define yyjson_api
- # endif
- #endif
- /** inline function export */
- #ifndef yyjson_api_inline
- # define yyjson_api_inline static yyjson_inline
- #endif
- /** stdint (C89 compatible) */
- #if (defined(YYJSON_HAS_STDINT_H) && YYJSON_HAS_STDINT_H) || \
- YYJSON_MSC_VER >= 1600 || YYJSON_STDC_VER >= 199901L || \
- defined(_STDINT_H) || defined(_STDINT_H_) || \
- defined(__CLANG_STDINT_H) || defined(_STDINT_H_INCLUDED) || \
- yyjson_has_include(<stdint.h>)
- # include <stdint.h>
- #elif defined(_MSC_VER)
- # if _MSC_VER < 1300
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
- typedef signed __int64 int64_t;
- typedef unsigned __int64 uint64_t;
- # else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
- typedef signed __int64 int64_t;
- typedef unsigned __int64 uint64_t;
- # endif
- #else
- # if UCHAR_MAX == 0xFFU
- typedef signed char int8_t;
- typedef unsigned char uint8_t;
- # else
- # error cannot find 8-bit integer type
- # endif
- # if USHRT_MAX == 0xFFFFU
- typedef unsigned short uint16_t;
- typedef signed short int16_t;
- # elif UINT_MAX == 0xFFFFU
- typedef unsigned int uint16_t;
- typedef signed int int16_t;
- # else
- # error cannot find 16-bit integer type
- # endif
- # if UINT_MAX == 0xFFFFFFFFUL
- typedef unsigned int uint32_t;
- typedef signed int int32_t;
- # elif ULONG_MAX == 0xFFFFFFFFUL
- typedef unsigned long uint32_t;
- typedef signed long int32_t;
- # elif USHRT_MAX == 0xFFFFFFFFUL
- typedef unsigned short uint32_t;
- typedef signed short int32_t;
- # else
- # error cannot find 32-bit integer type
- # endif
- # if defined(__INT64_TYPE__) && defined(__UINT64_TYPE__)
- typedef __INT64_TYPE__ int64_t;
- typedef __UINT64_TYPE__ uint64_t;
- # elif defined(__GNUC__) || defined(__clang__)
- # if !defined(_SYS_TYPES_H) && !defined(__int8_t_defined)
- __extension__ typedef long long int64_t;
- # endif
- __extension__ typedef unsigned long long uint64_t;
- # elif defined(_LONG_LONG) || defined(__MWERKS__) || defined(_CRAYC) || \
- defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- typedef long long int64_t;
- typedef unsigned long long uint64_t;
- # elif (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || \
- defined(__WATCOM_INT64__) || defined (__alpha) || defined (__DECC)
- typedef __int64 int64_t;
- typedef unsigned __int64 uint64_t;
- # else
- # error cannot find 64-bit integer type
- # endif
- #endif
- /** stdbool (C89 compatible) */
- #if (defined(YYJSON_HAS_STDBOOL_H) && YYJSON_HAS_STDBOOL_H) || \
- (yyjson_has_include(<stdbool.h>) && !defined(__STRICT_ANSI__)) || \
- YYJSON_MSC_VER >= 1800 || YYJSON_STDC_VER >= 199901L
- # include <stdbool.h>
- #elif !defined(__bool_true_false_are_defined)
- # define __bool_true_false_are_defined 1
- # if defined(__cplusplus)
- # if defined(__GNUC__) && !defined(__STRICT_ANSI__)
- # define _Bool bool
- # if __cplusplus < 201103L
- # define bool bool
- # define false false
- # define true true
- # endif
- # endif
- # else
- # define bool unsigned char
- # define true 1
- # define false 0
- # endif
- #endif
- /** char bit check */
- #if defined(CHAR_BIT)
- # if CHAR_BIT != 8
- # error non 8-bit char is not supported
- # endif
- #endif
- /**
- Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64:
- error C2520: conversion from unsigned __int64 to double not implemented.
- */
- #ifndef YYJSON_U64_TO_F64_NO_IMPL
- # if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200)
- # define YYJSON_U64_TO_F64_NO_IMPL 1
- # else
- # define YYJSON_U64_TO_F64_NO_IMPL 0
- # endif
- #endif
- /*==============================================================================
- * Compile Hint Begin
- *============================================================================*/
- /* extern "C" begin */
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* warning suppress begin */
- #if defined(__clang__)
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wunused-function"
- # pragma clang diagnostic ignored "-Wunused-parameter"
- #elif defined(__GNUC__)
- # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
- # pragma GCC diagnostic push
- # endif
- # pragma GCC diagnostic ignored "-Wunused-function"
- # pragma GCC diagnostic ignored "-Wunused-parameter"
- #elif defined(_MSC_VER)
- # pragma warning(push)
- # pragma warning(disable:4800) /* 'int': forcing value to 'true' or 'false' */
- #endif
- /*==============================================================================
- * Version
- *============================================================================*/
- /** The major version of yyjson. */
- #define YYJSON_VERSION_MAJOR 0
- /** The minor version of yyjson. */
- #define YYJSON_VERSION_MINOR 7
- /** The patch version of yyjson. */
- #define YYJSON_VERSION_PATCH 0
- /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
- #define YYJSON_VERSION_HEX 0x000700
- /** The version string of yyjson. */
- #define YYJSON_VERSION_STRING "0.7.0"
- /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
- yyjson_api uint32_t yyjson_version(void);
- /*==============================================================================
- * JSON Types
- *============================================================================*/
- /** Type of a JSON value (3 bit). */
- typedef uint8_t yyjson_type;
- /** No type, invalid. */
- #define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */
- /** Raw string type, no subtype. */
- #define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */
- /** Null type: `null` literal, no subtype. */
- #define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */
- /** Boolean type, subtype: TRUE, FALSE. */
- #define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */
- /** Number type, subtype: UINT, SINT, REAL. */
- #define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */
- /** String type, subtype: NONE, NOESC. */
- #define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */
- /** Array type, no subtype. */
- #define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */
- /** Object type, no subtype. */
- #define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */
- /** Subtype of a JSON value (2 bit). */
- typedef uint8_t yyjson_subtype;
- /** No subtype. */
- #define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */
- /** False subtype: `false` literal. */
- #define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */
- /** True subtype: `true` literal. */
- #define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */
- /** Unsigned integer subtype: `uint64_t`. */
- #define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */
- /** Signed integer subtype: `int64_t`. */
- #define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */
- /** Real number subtype: `double`. */
- #define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */
- /** String that do not need to be escaped for writing (internal use). */
- #define YYJSON_SUBTYPE_NOESC ((uint8_t)(1 << 3)) /* ___01___ */
- /** The mask used to extract the type of a JSON value. */
- #define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */
- /** The number of bits used by the type. */
- #define YYJSON_TYPE_BIT ((uint8_t)3)
- /** The mask used to extract the subtype of a JSON value. */
- #define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */
- /** The number of bits used by the subtype. */
- #define YYJSON_SUBTYPE_BIT ((uint8_t)2)
- /** The mask used to extract the reserved bits of a JSON value. */
- #define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */
- /** The number of reserved bits. */
- #define YYJSON_RESERVED_BIT ((uint8_t)3)
- /** The mask used to extract the tag of a JSON value. */
- #define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */
- /** The number of bits used by the tag. */
- #define YYJSON_TAG_BIT ((uint8_t)8)
- /** Padding size for JSON reader. */
- #define YYJSON_PADDING_SIZE 4
- /*==============================================================================
- * Allocator
- *============================================================================*/
- /**
- A memory allocator.
-
- Typically you don't need to use it, unless you want to customize your own
- memory allocator.
- */
- typedef struct yyjson_alc {
- /** Same as libc's malloc(size), should not be NULL. */
- void *(*malloc)(void *ctx, size_t size);
- /** Same as libc's realloc(ptr, size), should not be NULL. */
- void *(*realloc)(void *ctx, void *ptr, size_t old_size, size_t size);
- /** Same as libc's free(ptr), should not be NULL. */
- void (*free)(void *ctx, void *ptr);
- /** A context for malloc/realloc/free, can be NULL. */
- void *ctx;
- } yyjson_alc;
- /**
- A pool allocator uses fixed length pre-allocated memory.
-
- This allocator may be used to avoid malloc/realloc calls. The pre-allocated
- memory should be held by the caller. The maximum amount of memory required to
- read a JSON can be calculated using the `yyjson_read_max_memory_usage()`
- function, but the amount of memory required to write a JSON cannot be directly
- calculated.
-
- This is not a general-purpose allocator. If used to read multiple JSON
- documents and only some of them are released, it may cause memory
- fragmentation, leading to performance degradation and memory waste. Therefore,
- it is recommended to use this allocator only for reading or writing a single
- JSON document.
-
- @param alc The allocator to be initialized.
- If this parameter is NULL, the function will fail and return false.
- If `buf` or `size` is invalid, this will be set to an empty allocator.
- @param buf The buffer memory for this allocator.
- If this parameter is NULL, the function will fail and return false.
- @param size The size of `buf`, in bytes.
- If this parameter is less than 8 words (32/64 bytes on 32/64-bit OS), the
- function will fail and return false.
- @return true if the `alc` has been successfully initialized.
-
- @par Example
- @code
- // parse JSON with stack memory
- char buf[1024];
- yyjson_alc alc;
- yyjson_alc_pool_init(&alc, buf, 1024);
-
- const char *json = "{\"name\":\"Helvetica\",\"size\":16}"
- yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL);
- // the memory of `doc` is on the stack
- @endcode
- */
- yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size);
- /*==============================================================================
- * JSON Structure
- *============================================================================*/
- /**
- An immutable document for reading JSON.
- This document holds memory for all its JSON values and strings. When it is no
- longer used, the user should call `yyjson_doc_free()` to free its memory.
- */
- typedef struct yyjson_doc yyjson_doc;
- /**
- An immutable value for reading JSON.
- A JSON Value has the same lifetime as its document. The memory is held by its
- document and and cannot be freed alone.
- */
- typedef struct yyjson_val yyjson_val;
- /**
- A mutable document for building JSON.
- This document holds memory for all its JSON values and strings. When it is no
- longer used, the user should call `yyjson_mut_doc_free()` to free its memory.
- */
- typedef struct yyjson_mut_doc yyjson_mut_doc;
- /**
- A mutable value for building JSON.
- A JSON Value has the same lifetime as its document. The memory is held by its
- document and and cannot be freed alone.
- */
- typedef struct yyjson_mut_val yyjson_mut_val;
- /*==============================================================================
- * JSON Reader API
- *============================================================================*/
- /** Run-time options for JSON reader. */
- typedef uint32_t yyjson_read_flag;
- /** Default option (RFC 8259 compliant):
- - Read positive integer as uint64_t.
- - Read negative integer as int64_t.
- - Read floating-point number as double with round-to-nearest mode.
- - Read integer which cannot fit in uint64_t or int64_t as double.
- - Report error if double number is infinity.
- - Report error if string contains invalid UTF-8 character or BOM.
- - Report error on trailing commas, comments, inf and nan literals. */
- static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0;
- /** Read the input data in-situ.
- This option allows the reader to modify and use input data to store string
- values, which can increase reading speed slightly.
- The caller should hold the input data before free the document.
- The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes.
- For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */
- static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0;
- /** Stop when done instead of issuing an error if there's additional content
- after a JSON document. This option may be used to parse small pieces of JSON
- in larger data, such as `NDJSON`. */
- static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1;
- /** Allow single trailing comma at the end of an object or array,
- such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */
- static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2;
- /** Allow C-style single line and multiple line comments (non-standard). */
- static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3;
- /** Allow inf/nan number and literal, case-insensitive,
- such as 1e999, NaN, inf, -Infinity (non-standard). */
- static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4;
- /** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type),
- inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */
- static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5;
- /** Allow reading invalid unicode when parsing string values (non-standard).
- Invalid characters will be allowed to appear in the string values, but
- invalid escape sequences will still be reported as errors.
- This flag does not affect the performance of correctly encoded strings.
-
- @warning Strings in JSON values may contain incorrect encoding when this
- option is used, you need to handle these strings carefully to avoid security
- risks. */
- static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6;
- /** Read big numbers as raw strings. These big numbers include integers that
- cannot be represented by `int64_t` and `uint64_t`, and floating-point
- numbers that cannot be represented by finite `double`.
- The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */
- static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7;
- /** Result code for JSON reader. */
- typedef uint32_t yyjson_read_code;
- /** Success, no error. */
- static const yyjson_read_code YYJSON_READ_SUCCESS = 0;
- /** Invalid parameter, such as NULL input string or 0 input length. */
- static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1;
- /** Memory allocation failure occurs. */
- static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2;
- /** Input JSON string is empty. */
- static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3;
- /** Unexpected content after document, such as `[123]abc`. */
- static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4;
- /** Unexpected ending, such as `[123`. */
- static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5;
- /** Unexpected character inside the document, such as `[abc]`. */
- static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6;
- /** Invalid JSON structure, such as `[1,]`. */
- static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7;
- /** Invalid comment, such as unclosed multi-line comment. */
- static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8;
- /** Invalid number, such as `123.e12`, `000`. */
- static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9;
- /** Invalid string, such as invalid escaped character inside a string. */
- static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10;
- /** Invalid JSON literal, such as `truu`. */
- static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11;
- /** Failed to open a file. */
- static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12;
- /** Failed to read a file. */
- static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13;
- /** Error information for JSON reader. */
- typedef struct yyjson_read_err {
- /** Error code, see `yyjson_read_code` for all possible values. */
- yyjson_read_code code;
- /** Error message, constant, no need to free (NULL if success). */
- const char *msg;
- /** Error byte position for input data (0 if success). */
- size_t pos;
- } yyjson_read_err;
- /**
- Read JSON with options.
-
- This function is thread-safe when:
- 1. The `dat` is not modified by other threads.
- 2. The `alc` is thread-safe or NULL.
-
- @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
- If this parameter is NULL, the function will fail and return NULL.
- The `dat` will not be modified without the flag `YYJSON_READ_INSITU`, so you
- can pass a `const char *` string and case it to `char *` if you don't use
- the `YYJSON_READ_INSITU` flag.
- @param len The length of JSON data in bytes.
- If this parameter is 0, the function will fail and return NULL.
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON reader.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON document, or NULL if an error occurs.
- When it's no longer needed, it should be freed with `yyjson_doc_free()`.
- */
- yyjson_api yyjson_doc *yyjson_read_opts(char *dat,
- size_t len,
- yyjson_read_flag flg,
- const yyjson_alc *alc,
- yyjson_read_err *err);
- /**
- Read a JSON file.
-
- This function is thread-safe when:
- 1. The file is not modified by other threads.
- 2. The `alc` is thread-safe or NULL.
-
- @param path The JSON file's path.
- If this path is NULL or invalid, the function will fail and return NULL.
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON reader.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON document, or NULL if an error occurs.
- When it's no longer needed, it should be freed with `yyjson_doc_free()`.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to read.
- */
- yyjson_api yyjson_doc *yyjson_read_file(const char *path,
- yyjson_read_flag flg,
- const yyjson_alc *alc,
- yyjson_read_err *err);
- /**
- Read JSON from a file pointer.
-
- @param fp The file pointer.
- The data will be read from the current position of the FILE to the end.
- If this fp is NULL or invalid, the function will fail and return NULL.
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON reader.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON document, or NULL if an error occurs.
- When it's no longer needed, it should be freed with `yyjson_doc_free()`.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to read.
- */
- yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp,
- yyjson_read_flag flg,
- const yyjson_alc *alc,
- yyjson_read_err *err);
- /**
- Read a JSON string.
-
- This function is thread-safe.
-
- @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
- If this parameter is NULL, the function will fail and return NULL.
- @param len The length of JSON data in bytes.
- If this parameter is 0, the function will fail and return NULL.
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @return A new JSON document, or NULL if an error occurs.
- When it's no longer needed, it should be freed with `yyjson_doc_free()`.
- */
- yyjson_api_inline yyjson_doc *yyjson_read(const char *dat,
- size_t len,
- yyjson_read_flag flg) {
- flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */
- return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat,
- len, flg, NULL, NULL);
- }
- /**
- Returns the size of maximum memory usage to read a JSON data.
-
- You may use this value to avoid malloc() or calloc() call inside the reader
- to get better performance, or read multiple JSON with one piece of memory.
-
- @param len The length of JSON data in bytes.
- @param flg The JSON read options.
- @return The maximum memory size to read this JSON, or 0 if overflow.
-
- @par Example
- @code
- // read multiple JSON with same pre-allocated memory
-
- char *dat1, *dat2, *dat3; // JSON data
- size_t len1, len2, len3; // JSON length
- size_t max_len = MAX(len1, MAX(len2, len3));
- yyjson_doc *doc;
-
- // use one allocator for multiple JSON
- size_t size = yyjson_read_max_memory_usage(max_len, 0);
- void *buf = malloc(size);
- yyjson_alc alc;
- yyjson_alc_pool_init(&alc, buf, size);
-
- // no more alloc() or realloc() call during reading
- doc = yyjson_read_opts(dat1, len1, 0, &alc, NULL);
- yyjson_doc_free(doc);
- doc = yyjson_read_opts(dat2, len2, 0, &alc, NULL);
- yyjson_doc_free(doc);
- doc = yyjson_read_opts(dat3, len3, 0, &alc, NULL);
- yyjson_doc_free(doc);
-
- free(buf);
- @endcode
- @see yyjson_alc_pool_init()
- */
- yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len,
- yyjson_read_flag flg) {
- /*
- 1. The max value count is (json_size / 2 + 1),
- for example: "[1,2,3,4]" size is 9, value count is 5.
- 2. Some broken JSON may cost more memory during reading, but fail at end,
- for example: "[[[[[[[[".
- 3. yyjson use 16 bytes per value, see struct yyjson_val.
- 4. yyjson use dynamic memory with a growth factor of 1.5.
-
- The max memory size is (json_size / 2 * 16 * 1.5 + padding).
- */
- size_t mul = (size_t)12 + !(flg & YYJSON_READ_INSITU);
- size_t pad = 256;
- size_t max = (size_t)(~(size_t)0);
- if (flg & YYJSON_READ_STOP_WHEN_DONE) len = len < 256 ? 256 : len;
- if (len >= (max - pad - mul) / mul) return 0;
- return len * mul + pad;
- }
- /**
- Read a JSON number.
- This function is thread-safe when data is not modified by other threads.
- @param dat The JSON data (UTF-8 without BOM), null-terminator is required.
- If this parameter is NULL, the function will fail and return NULL.
- @param val The output value where result is stored.
- If this parameter is NULL, the function will fail and return NULL.
- The value will hold either UINT or SINT or REAL number;
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`.
- @param alc The memory allocator used for long number.
- It is only used when the built-in floating point reader is disabled.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return If successful, a pointer to the character after the last character
- used in the conversion, NULL if an error occurs.
- */
- yyjson_api const char *yyjson_read_number(const char *dat,
- yyjson_val *val,
- yyjson_read_flag flg,
- const yyjson_alc *alc,
- yyjson_read_err *err);
- /**
- Read a JSON number.
- This function is thread-safe when data is not modified by other threads.
- @param dat The JSON data (UTF-8 without BOM), null-terminator is required.
- If this parameter is NULL, the function will fail and return NULL.
- @param val The output value where result is stored.
- If this parameter is NULL, the function will fail and return NULL.
- The value will hold either UINT or SINT or REAL number;
- @param flg The JSON read options.
- Multiple options can be combined with `|` operator. 0 means no options.
- Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`.
- @param alc The memory allocator used for long number.
- It is only used when the built-in floating point reader is disabled.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return If successful, a pointer to the character after the last character
- used in the conversion, NULL if an error occurs.
- */
- yyjson_api_inline const char *yyjson_mut_read_number(const char *dat,
- yyjson_mut_val *val,
- yyjson_read_flag flg,
- const yyjson_alc *alc,
- yyjson_read_err *err) {
- return yyjson_read_number(dat, (yyjson_val *)val, flg, alc, err);
- }
- /*==============================================================================
- * JSON Writer API
- *============================================================================*/
- /** Run-time options for JSON writer. */
- typedef uint32_t yyjson_write_flag;
- /** Default option:
- - Write JSON minify.
- - Report error on inf or nan number.
- - Report error on invalid UTF-8 string.
- - Do not escape unicode or slash. */
- static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0;
- /** Write JSON pretty with 4 space indent. */
- static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0;
- /** Escape unicode as `uXXXX`, make the output ASCII only. */
- static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1;
- /** Escape '/' as '\/'. */
- static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2;
- /** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */
- static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3;
- /** Write inf and nan number as null literal.
- This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */
- static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4;
- /** Allow invalid unicode when encoding string values (non-standard).
- Invalid characters in string value will be copied byte by byte.
- If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be
- escaped as `U+FFFD` (replacement character).
- This flag does not affect the performance of correctly encoded strings. */
- static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5;
- /** Write JSON pretty with 2 space indent.
- This flag will override `YYJSON_WRITE_PRETTY` flag. */
- static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6;
- /** Result code for JSON writer */
- typedef uint32_t yyjson_write_code;
- /** Success, no error. */
- static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0;
- /** Invalid parameter, such as NULL document. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1;
- /** Memory allocation failure occurs. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2;
- /** Invalid value type in JSON document. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3;
- /** NaN or Infinity number occurs. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4;
- /** Failed to open a file. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5;
- /** Failed to write a file. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6;
- /** Invalid unicode in string. */
- static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7;
- /** Error information for JSON writer. */
- typedef struct yyjson_write_err {
- /** Error code, see `yyjson_write_code` for all possible values. */
- yyjson_write_code code;
- /** Error message, constant, no need to free (NULL if success). */
- const char *msg;
- } yyjson_write_err;
- /*==============================================================================
- * JSON Document Writer API
- *============================================================================*/
- /**
- Write a document to JSON string with options.
-
- This function is thread-safe when:
- The `alc` is thread-safe or NULL.
-
- @param doc The JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free() or alc->free().
- */
- yyjson_api char *yyjson_write_opts(const yyjson_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- size_t *len,
- yyjson_write_err *err);
- /**
- Write a document to JSON file with options.
-
- This function is thread-safe when:
- 1. The file is not accessed by other threads.
- 2. The `alc` is thread-safe or NULL.
- @param path The JSON file's path.
- If this path is NULL or invalid, the function will fail and return false.
- If this file is not empty, the content will be discarded.
- @param doc The JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_write_file(const char *path,
- const yyjson_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a document to file pointer with options.
-
- @param fp The file pointer.
- The data will be written to the current position of the file.
- If this fp is NULL or invalid, the function will fail and return false.
- @param doc The JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_write_fp(FILE *fp,
- const yyjson_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a document to JSON string.
-
- This function is thread-safe.
-
- @param doc The JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free().
- */
- yyjson_api_inline char *yyjson_write(const yyjson_doc *doc,
- yyjson_write_flag flg,
- size_t *len) {
- return yyjson_write_opts(doc, flg, NULL, len, NULL);
- }
- /**
- Write a document to JSON string with options.
-
- This function is thread-safe when:
- 1. The `doc` is not modified by other threads.
- 2. The `alc` is thread-safe or NULL.
- @param doc The mutable JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free() or alc->free().
- */
- yyjson_api char *yyjson_mut_write_opts(const yyjson_mut_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- size_t *len,
- yyjson_write_err *err);
- /**
- Write a document to JSON file with options.
-
- This function is thread-safe when:
- 1. The file is not accessed by other threads.
- 2. The `doc` is not modified by other threads.
- 3. The `alc` is thread-safe or NULL.
-
- @param path The JSON file's path.
- If this path is NULL or invalid, the function will fail and return false.
- If this file is not empty, the content will be discarded.
- @param doc The mutable JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_mut_write_file(const char *path,
- const yyjson_mut_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a document to file pointer with options.
-
- @param fp The file pointer.
- The data will be written to the current position of the file.
- If this fp is NULL or invalid, the function will fail and return false.
- @param doc The mutable JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_mut_write_fp(FILE *fp,
- const yyjson_mut_doc *doc,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a document to JSON string.
-
- This function is thread-safe when:
- The `doc` is not modified by other threads.
-
- @param doc The JSON document.
- If this doc is NULL or has no root, the function will fail and return false.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free().
- */
- yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc,
- yyjson_write_flag flg,
- size_t *len) {
- return yyjson_mut_write_opts(doc, flg, NULL, len, NULL);
- }
- /*==============================================================================
- * JSON Value Writer API
- *============================================================================*/
- /**
- Write a value to JSON string with options.
-
- This function is thread-safe when:
- The `alc` is thread-safe or NULL.
-
- @param val The JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free() or alc->free().
- */
- yyjson_api char *yyjson_val_write_opts(const yyjson_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- size_t *len,
- yyjson_write_err *err);
- /**
- Write a value to JSON file with options.
-
- This function is thread-safe when:
- 1. The file is not accessed by other threads.
- 2. The `alc` is thread-safe or NULL.
-
- @param path The JSON file's path.
- If this path is NULL or invalid, the function will fail and return false.
- If this file is not empty, the content will be discarded.
- @param val The JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_val_write_file(const char *path,
- const yyjson_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a value to file pointer with options.
-
- @param fp The file pointer.
- The data will be written to the current position of the file.
- If this path is NULL or invalid, the function will fail and return false.
- @param val The JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_val_write_fp(FILE *fp,
- const yyjson_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a value to JSON string.
-
- This function is thread-safe.
-
- @param val The JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free().
- */
- yyjson_api_inline char *yyjson_val_write(const yyjson_val *val,
- yyjson_write_flag flg,
- size_t *len) {
- return yyjson_val_write_opts(val, flg, NULL, len, NULL);
- }
- /**
- Write a value to JSON string with options.
-
- This function is thread-safe when:
- 1. The `val` is not modified by other threads.
- 2. The `alc` is thread-safe or NULL.
-
- @param val The mutable JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free() or alc->free().
- */
- yyjson_api char *yyjson_mut_val_write_opts(const yyjson_mut_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- size_t *len,
- yyjson_write_err *err);
- /**
- Write a value to JSON file with options.
-
- This function is thread-safe when:
- 1. The file is not accessed by other threads.
- 2. The `val` is not modified by other threads.
- 3. The `alc` is thread-safe or NULL.
-
- @param path The JSON file's path.
- If this path is NULL or invalid, the function will fail and return false.
- If this file is not empty, the content will be discarded.
- @param val The mutable JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_mut_val_write_file(const char *path,
- const yyjson_mut_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a value to JSON file with options.
-
- @param fp The file pointer.
- The data will be written to the current position of the file.
- If this path is NULL or invalid, the function will fail and return false.
- @param val The mutable JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param alc The memory allocator used by JSON writer.
- Pass NULL to use the libc's default allocator.
- @param err A pointer to receive error information.
- Pass NULL if you don't need error information.
- @return true if successful, false if an error occurs.
-
- @warning On 32-bit operating system, files larger than 2GB may fail to write.
- */
- yyjson_api bool yyjson_mut_val_write_fp(FILE *fp,
- const yyjson_mut_val *val,
- yyjson_write_flag flg,
- const yyjson_alc *alc,
- yyjson_write_err *err);
- /**
- Write a value to JSON string.
-
- This function is thread-safe when:
- The `val` is not modified by other threads.
-
- @param val The JSON root value.
- If this parameter is NULL, the function will fail and return NULL.
- @param flg The JSON write options.
- Multiple options can be combined with `|` operator. 0 means no options.
- @param len A pointer to receive output length in bytes (not including the
- null-terminator). Pass NULL if you don't need length information.
- @return A new JSON string, or NULL if an error occurs.
- This string is encoded as UTF-8 with a null-terminator.
- When it's no longer needed, it should be freed with free().
- */
- yyjson_api_inline char *yyjson_mut_val_write(const yyjson_mut_val *val,
- yyjson_write_flag flg,
- size_t *len) {
- return yyjson_mut_val_write_opts(val, flg, NULL, len, NULL);
- }
- /*==============================================================================
- * JSON Document API
- *============================================================================*/
- /** Returns the root value of this JSON document.
- Returns NULL if `doc` is NULL. */
- yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc);
- /** Returns read size of input JSON data.
- Returns 0 if `doc` is NULL.
- For example: the read size of `[1,2,3]` is 7 bytes. */
- yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc);
- /** Returns total value count in this JSON document.
- Returns 0 if `doc` is NULL.
- For example: the value count of `[1,2,3]` is 4. */
- yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc);
- /** Release the JSON document and free the memory.
- After calling this function, the `doc` and all values from the `doc` are no
- longer available. This function will do nothing if the `doc` is NULL. */
- yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc);
- /*==============================================================================
- * JSON Value Type API
- *============================================================================*/
- /** Returns whether the JSON value is raw.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_raw(yyjson_val *val);
- /** Returns whether the JSON value is `null`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_null(yyjson_val *val);
- /** Returns whether the JSON value is `true`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_true(yyjson_val *val);
- /** Returns whether the JSON value is `false`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_false(yyjson_val *val);
- /** Returns whether the JSON value is bool (true/false).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_bool(yyjson_val *val);
- /** Returns whether the JSON value is unsigned integer (uint64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_uint(yyjson_val *val);
- /** Returns whether the JSON value is signed integer (int64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_sint(yyjson_val *val);
- /** Returns whether the JSON value is integer (uint64_t/int64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_int(yyjson_val *val);
- /** Returns whether the JSON value is real number (double).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_real(yyjson_val *val);
- /** Returns whether the JSON value is number (uint64_t/int64_t/double).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_num(yyjson_val *val);
- /** Returns whether the JSON value is string.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_str(yyjson_val *val);
- /** Returns whether the JSON value is array.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_arr(yyjson_val *val);
- /** Returns whether the JSON value is object.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_obj(yyjson_val *val);
- /** Returns whether the JSON value is container (array/object).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val);
- /*==============================================================================
- * JSON Value Content API
- *============================================================================*/
- /** Returns the JSON value's type.
- Returns YYJSON_TYPE_NONE if `val` is NULL. */
- yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val);
- /** Returns the JSON value's subtype.
- Returns YYJSON_SUBTYPE_NONE if `val` is NULL. */
- yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val);
- /** Returns the JSON value's tag.
- Returns 0 if `val` is NULL. */
- yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val);
- /** Returns the JSON value's type description.
- The return value should be one of these strings: "raw", "null", "string",
- "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
- yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val);
- /** Returns the content if the value is raw.
- Returns NULL if `val` is NULL or type is not raw. */
- yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val);
- /** Returns the content if the value is bool.
- Returns NULL if `val` is NULL or type is not bool. */
- yyjson_api_inline bool yyjson_get_bool(yyjson_val *val);
- /** Returns the content and cast to uint64_t.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val);
- /** Returns the content and cast to int64_t.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val);
- /** Returns the content and cast to int.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline int yyjson_get_int(yyjson_val *val);
- /** Returns the content if the value is real number, or 0.0 on error.
- Returns 0.0 if `val` is NULL or type is not real(double). */
- yyjson_api_inline double yyjson_get_real(yyjson_val *val);
- /** Returns the content and typecast to `double` if the value is number.
- Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
- yyjson_api_inline double yyjson_get_num(yyjson_val *val);
- /** Returns the content if the value is string.
- Returns NULL if `val` is NULL or type is not string. */
- yyjson_api_inline const char *yyjson_get_str(yyjson_val *val);
- /** Returns the content length (string length, array size, object size.
- Returns 0 if `val` is NULL or type is not string/array/object. */
- yyjson_api_inline size_t yyjson_get_len(yyjson_val *val);
- /** Returns whether the JSON value is equals to a string.
- Returns false if input is NULL or type is not string. */
- yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str);
- /** Returns whether the JSON value is equals to a string.
- The `str` should be a UTF-8 string, null-terminator is not required.
- Returns false if input is NULL or type is not string. */
- yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
- size_t len);
- /** Returns whether two JSON values are equal (deep compare).
- Returns false if input is NULL.
- @note the result may be inaccurate if object has duplicate keys.
- @warning This function is recursive and may cause a stack overflow
- if the object level is too deep. */
- yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
- /** Set the value to raw.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
- const char *raw, size_t len);
- /** Set the value to null.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_null(yyjson_val *val);
- /** Set the value to bool.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num);
- /** Set the value to uint.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num);
- /** Set the value to sint.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num);
- /** Set the value to int.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num);
- /** Set the value to real.
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num);
- /** Set the value to string (null-terminated).
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str);
- /** Set the value to string (with length).
- Returns false if input is NULL or `val` is object or array.
- @warning This will modify the `immutable` value, use with caution. */
- yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
- const char *str, size_t len);
- /*==============================================================================
- * JSON Array API
- *============================================================================*/
- /** Returns the number of elements in this array.
- Returns 0 if `arr` is NULL or type is not array. */
- yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr);
- /** Returns the element at the specified position in this array.
- Returns NULL if array is NULL/empty or the index is out of bounds.
- @warning This function takes a linear search time if array is not flat.
- For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat. */
- yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx);
- /** Returns the first element of this array.
- Returns NULL if `arr` is NULL/empty or type is not array. */
- yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr);
- /** Returns the last element of this array.
- Returns NULL if `arr` is NULL/empty or type is not array.
- @warning This function takes a linear search time if array is not flat.
- For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat.*/
- yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr);
- /*==============================================================================
- * JSON Array Iterator API
- *============================================================================*/
- /**
- A JSON array iterator.
-
- @par Example
- @code
- yyjson_val *val;
- yyjson_arr_iter iter = yyjson_arr_iter_with(arr);
- while ((val = yyjson_arr_iter_next(&iter))) {
- your_func(val);
- }
- @endcode
- */
- typedef struct yyjson_arr_iter {
- size_t idx; /**< next value's index */
- size_t max; /**< maximum index (arr.size) */
- yyjson_val *cur; /**< next value */
- } yyjson_arr_iter;
- /**
- Initialize an iterator for this array.
-
- @param arr The array to be iterated over.
- If this parameter is NULL or not an array, `iter` will be set to empty.
- @param iter The iterator to be initialized.
- If this parameter is NULL, the function will fail and return false.
- @return true if the `iter` has been successfully initialized.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
- yyjson_arr_iter *iter);
- /**
- Create an iterator with an array , same as `yyjson_arr_iter_init()`.
-
- @param arr The array to be iterated over.
- If this parameter is NULL or not an array, an empty iterator will returned.
- @return A new iterator for the array.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr);
- /**
- Returns whether the iteration has more elements.
- If `iter` is NULL, this function will return false.
- */
- yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter);
- /**
- Returns the next element in the iteration, or NULL on end.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter);
- /**
- Macro for iterating over an array.
- It works like iterator, but with a more intuitive API.
-
- @par Example
- @code
- size_t idx, max;
- yyjson_val *val;
- yyjson_arr_foreach(arr, idx, max, val) {
- your_func(idx, val);
- }
- @endcode
- */
- #define yyjson_arr_foreach(arr, idx, max, val) \
- for ((idx) = 0, \
- (max) = yyjson_arr_size(arr), \
- (val) = yyjson_arr_get_first(arr); \
- (idx) < (max); \
- (idx)++, \
- (val) = unsafe_yyjson_get_next(val))
- /*==============================================================================
- * JSON Object API
- *============================================================================*/
- /** Returns the number of key-value pairs in this object.
- Returns 0 if `obj` is NULL or type is not object. */
- yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj);
- /** Returns the value to which the specified key is mapped.
- Returns NULL if this object contains no mapping for the key.
- Returns NULL if `obj/key` is NULL, or type is not object.
-
- The `key` should be a null-terminated UTF-8 string.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key);
- /** Returns the value to which the specified key is mapped.
- Returns NULL if this object contains no mapping for the key.
- Returns NULL if `obj/key` is NULL, or type is not object.
-
- The `key` should be a UTF-8 string, null-terminator is not required.
- The `key_len` should be the length of the key, in bytes.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key,
- size_t key_len);
- /*==============================================================================
- * JSON Object Iterator API
- *============================================================================*/
- /**
- A JSON object iterator.
-
- @par Example
- @code
- yyjson_val *key, *val;
- yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
- while ((key = yyjson_obj_iter_next(&iter))) {
- val = yyjson_obj_iter_get_val(key);
- your_func(key, val);
- }
- @endcode
-
- If the ordering of the keys is known at compile-time, you can use this method
- to speed up value lookups:
- @code
- // {"k1":1, "k2": 3, "k3": 3}
- yyjson_val *key, *val;
- yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
- yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1");
- yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3");
- @endcode
- @see yyjson_obj_iter_get() and yyjson_obj_iter_getn()
- */
- typedef struct yyjson_obj_iter {
- size_t idx; /**< next key's index */
- size_t max; /**< maximum key index (obj.size) */
- yyjson_val *cur; /**< next key */
- yyjson_val *obj; /**< the object being iterated */
- } yyjson_obj_iter;
- /**
- Initialize an iterator for this object.
-
- @param obj The object to be iterated over.
- If this parameter is NULL or not an object, `iter` will be set to empty.
- @param iter The iterator to be initialized.
- If this parameter is NULL, the function will fail and return false.
- @return true if the `iter` has been successfully initialized.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
- yyjson_obj_iter *iter);
- /**
- Create an iterator with an object, same as `yyjson_obj_iter_init()`.
-
- @param obj The object to be iterated over.
- If this parameter is NULL or not an object, an empty iterator will returned.
- @return A new iterator for the object.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj);
- /**
- Returns whether the iteration has more elements.
- If `iter` is NULL, this function will return false.
- */
- yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter);
- /**
- Returns the next key in the iteration, or NULL on end.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter);
- /**
- Returns the value for key inside the iteration.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key);
- /**
- Iterates to a specified key and returns the value.
-
- This function does the same thing as `yyjson_obj_get()`, but is much faster
- if the ordering of the keys is known at compile-time and you are using the same
- order to look up the values. If the key exists in this object, then the
- iterator will stop at the next key, otherwise the iterator will not change and
- NULL is returned.
-
- @param iter The object iterator, should not be NULL.
- @param key The key, should be a UTF-8 string with null-terminator.
- @return The value to which the specified key is mapped.
- NULL if this object contains no mapping for the key or input is invalid.
-
- @warning This function takes a linear search time if the key is not nearby.
- */
- yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
- const char *key);
- /**
- Iterates to a specified key and returns the value.
- This function does the same thing as `yyjson_obj_getn()`, but is much faster
- if the ordering of the keys is known at compile-time and you are using the same
- order to look up the values. If the key exists in this object, then the
- iterator will stop at the next key, otherwise the iterator will not change and
- NULL is returned.
-
- @param iter The object iterator, should not be NULL.
- @param key The key, should be a UTF-8 string, null-terminator is not required.
- @param key_len The the length of `key`, in bytes.
- @return The value to which the specified key is mapped.
- NULL if this object contains no mapping for the key or input is invalid.
-
- @warning This function takes a linear search time if the key is not nearby.
- */
- yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
- const char *key,
- size_t key_len);
- /**
- Macro for iterating over an object.
- It works like iterator, but with a more intuitive API.
-
- @par Example
- @code
- size_t idx, max;
- yyjson_val *key, *val;
- yyjson_obj_foreach(obj, idx, max, key, val) {
- your_func(key, val);
- }
- @endcode
- */
- #define yyjson_obj_foreach(obj, idx, max, key, val) \
- for ((idx) = 0, \
- (max) = yyjson_obj_size(obj), \
- (key) = (obj) ? unsafe_yyjson_get_first(obj) : NULL, \
- (val) = (key) + 1; \
- (idx) < (max); \
- (idx)++, \
- (key) = unsafe_yyjson_get_next(val), \
- (val) = (key) + 1)
- /*==============================================================================
- * Mutable JSON Document API
- *============================================================================*/
- /** Returns the root value of this JSON document.
- Returns NULL if `doc` is NULL. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc);
- /** Sets the root value of this JSON document.
- Pass NULL to clear root value of the document. */
- yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
- yyjson_mut_val *root);
- /**
- Set the string pool size for a mutable document.
- This function does not allocate memory immediately, but uses the size when
- the next memory allocation is needed.
-
- If the caller knows the approximate bytes of strings that the document needs to
- store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger
- size can avoid multiple memory allocations and improve performance.
-
- @param doc The mutable document.
- @param len The desired string pool size in bytes (total string length).
- @return true if successful, false if size is 0 or overflow.
- */
- yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc,
- size_t len);
- /**
- Set the value pool size for a mutable document.
- This function does not allocate memory immediately, but uses the size when
- the next memory allocation is needed.
-
- If the caller knows the approximate number of values that the document needs to
- store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger
- size can avoid multiple memory allocations and improve performance.
-
- @param doc The mutable document.
- @param count The desired value pool size (number of `yyjson_mut_val`).
- @return true if successful, false if size is 0 or overflow.
- */
- yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc,
- size_t count);
- /** Release the JSON document and free the memory.
- After calling this function, the `doc` and all values from the `doc` are no
- longer available. This function will do nothing if the `doc` is NULL. */
- yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc);
- /** Creates and returns a new mutable JSON document, returns NULL on error.
- If allocator is NULL, the default allocator will be used. */
- yyjson_api yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc);
- /** Copies and returns a new mutable document from input, returns NULL on error.
- This makes a `deep-copy` on the immutable document.
- If allocator is NULL, the default allocator will be used.
- @note `imut_doc` -> `mut_doc`. */
- yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc,
- const yyjson_alc *alc);
- /** Copies and returns a new mutable document from input, returns NULL on error.
- This makes a `deep-copy` on the mutable document.
- If allocator is NULL, the default allocator will be used.
- @note `mut_doc` -> `mut_doc`. */
- yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc,
- const yyjson_alc *alc);
- /** Copies and returns a new mutable value from input, returns NULL on error.
- This makes a `deep-copy` on the immutable value.
- The memory was managed by mutable document.
- @note `imut_val` -> `mut_val`. */
- yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *doc,
- yyjson_val *val);
- /** Copies and returns a new mutable value from input, returns NULL on error.
- This makes a `deep-copy` on the mutable value.
- The memory was managed by mutable document.
- @note `mut_val` -> `mut_val`.
- @warning This function is recursive and may cause a stack overflow
- if the object level is too deep. */
- yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc,
- yyjson_mut_val *val);
- /** Copies and returns a new immutable document from input,
- returns NULL on error. This makes a `deep-copy` on the mutable document.
- The returned document should be freed with `yyjson_doc_free()`.
- @note `mut_doc` -> `imut_doc`.
- @warning This function is recursive and may cause a stack overflow
- if the object level is too deep. */
- yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *doc,
- const yyjson_alc *alc);
- /** Copies and returns a new immutable document from input,
- returns NULL on error. This makes a `deep-copy` on the mutable value.
- The returned document should be freed with `yyjson_doc_free()`.
- @note `mut_val` -> `imut_doc`.
- @warning This function is recursive and may cause a stack overflow
- if the object level is too deep. */
- yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *val,
- const yyjson_alc *alc);
- /*==============================================================================
- * Mutable JSON Value Type API
- *============================================================================*/
- /** Returns whether the JSON value is raw.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val);
- /** Returns whether the JSON value is `null`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val);
- /** Returns whether the JSON value is `true`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val);
- /** Returns whether the JSON value is `false`.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val);
- /** Returns whether the JSON value is bool (true/false).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val);
- /** Returns whether the JSON value is unsigned integer (uint64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val);
- /** Returns whether the JSON value is signed integer (int64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val);
- /** Returns whether the JSON value is integer (uint64_t/int64_t).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val);
- /** Returns whether the JSON value is real number (double).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val);
- /** Returns whether the JSON value is number (uint/sint/real).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val);
- /** Returns whether the JSON value is string.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val);
- /** Returns whether the JSON value is array.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val);
- /** Returns whether the JSON value is object.
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val);
- /** Returns whether the JSON value is container (array/object).
- Returns false if `val` is NULL. */
- yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val);
- /*==============================================================================
- * Mutable JSON Value Content API
- *============================================================================*/
- /** Returns the JSON value's type.
- Returns `YYJSON_TYPE_NONE` if `val` is NULL. */
- yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val);
- /** Returns the JSON value's subtype.
- Returns `YYJSON_SUBTYPE_NONE` if `val` is NULL. */
- yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val);
- /** Returns the JSON value's tag.
- Returns 0 if `val` is NULL. */
- yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val);
- /** Returns the JSON value's type description.
- The return value should be one of these strings: "raw", "null", "string",
- "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
- yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val);
- /** Returns the content if the value is raw.
- Returns NULL if `val` is NULL or type is not raw. */
- yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val);
- /** Returns the content if the value is bool.
- Returns NULL if `val` is NULL or type is not bool. */
- yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val);
- /** Returns the content and cast to uint64_t.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val);
- /** Returns the content and cast to int64_t.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val);
- /** Returns the content and cast to int.
- Returns 0 if `val` is NULL or type is not integer(sint/uint). */
- yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val);
- /** Returns the content if the value is real number.
- Returns 0.0 if `val` is NULL or type is not real(double). */
- yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val);
- /** Returns the content and typecast to `double` if the value is number.
- Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
- yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val);
- /** Returns the content if the value is string.
- Returns NULL if `val` is NULL or type is not string. */
- yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val);
- /** Returns the content length (string length, array size, object size.
- Returns 0 if `val` is NULL or type is not string/array/object. */
- yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val);
- /** Returns whether the JSON value is equals to a string.
- The `str` should be a null-terminated UTF-8 string.
- Returns false if input is NULL or type is not string. */
- yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
- const char *str);
- /** Returns whether the JSON value is equals to a string.
- The `str` should be a UTF-8 string, null-terminator is not required.
- Returns false if input is NULL or type is not string. */
- yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
- const char *str, size_t len);
- /** Returns whether two JSON values are equal (deep compare).
- Returns false if input is NULL.
- @note the result may be inaccurate if object has duplicate keys.
- @warning This function is recursive and may cause a stack overflow
- if the object level is too deep. */
- yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
- yyjson_mut_val *rhs);
- /** Set the value to raw.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
- const char *raw, size_t len);
- /** Set the value to null.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val);
- /** Set the value to bool.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num);
- /** Set the value to uint.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num);
- /** Set the value to sint.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num);
- /** Set the value to int.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num);
- /** Set the value to real.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num);
- /** Set the value to string (null-terminated).
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str);
- /** Set the value to string (with length).
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
- const char *str, size_t len);
- /** Set the value to array.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val);
- /** Set the value to array.
- Returns false if input is NULL.
- @warning This function should not be used on an existing object or array. */
- yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val);
- /*==============================================================================
- * Mutable JSON Value Creation API
- *============================================================================*/
- /** Creates and returns a raw value, returns NULL on error.
- The `str` should be a null-terminated UTF-8 string.
-
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
- const char *str);
- /** Creates and returns a raw value, returns NULL on error.
- The `str` should be a UTF-8 string, null-terminator is not required.
-
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
- const char *str,
- size_t len);
- /** Creates and returns a raw value, returns NULL on error.
- The `str` should be a null-terminated UTF-8 string.
- The input string is copied and held by the document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
- const char *str);
- /** Creates and returns a raw value, returns NULL on error.
- The `str` should be a UTF-8 string, null-terminator is not required.
- The input string is copied and held by the document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
- const char *str,
- size_t len);
- /** Creates and returns a null value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc);
- /** Creates and returns a true value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc);
- /** Creates and returns a false value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc);
- /** Creates and returns a bool value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
- bool val);
- /** Creates and returns an unsigned integer value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
- uint64_t num);
- /** Creates and returns a signed integer value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
- int64_t num);
- /** Creates and returns a signed integer value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
- int64_t num);
- /** Creates and returns an real number value, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
- double num);
- /** Creates and returns a string value, returns NULL on error.
- The `str` should be a null-terminated UTF-8 string.
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
- const char *str);
- /** Creates and returns a string value, returns NULL on error.
- The `str` should be a UTF-8 string, null-terminator is not required.
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
- const char *str,
- size_t len);
- /** Creates and returns a string value, returns NULL on error.
- The `str` should be a null-terminated UTF-8 string.
- The input string is copied and held by the document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
- const char *str);
- /** Creates and returns a string value, returns NULL on error.
- The `str` should be a UTF-8 string, null-terminator is not required.
- The input string is copied and held by the document. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
- const char *str,
- size_t len);
- /*==============================================================================
- * Mutable JSON Array API
- *============================================================================*/
- /** Returns the number of elements in this array.
- Returns 0 if `arr` is NULL or type is not array. */
- yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr);
- /** Returns the element at the specified position in this array.
- Returns NULL if array is NULL/empty or the index is out of bounds.
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
- size_t idx);
- /** Returns the first element of this array.
- Returns NULL if `arr` is NULL/empty or type is not array. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(yyjson_mut_val *arr);
- /** Returns the last element of this array.
- Returns NULL if `arr` is NULL/empty or type is not array. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr);
- /*==============================================================================
- * Mutable JSON Array Iterator API
- *============================================================================*/
- /**
- A mutable JSON array iterator.
-
- @warning You should not modify the array while iterating over it, but you can
- use `yyjson_mut_arr_iter_remove()` to remove current value.
-
- @par Example
- @code
- yyjson_mut_val *val;
- yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr);
- while ((val = yyjson_mut_arr_iter_next(&iter))) {
- your_func(val);
- if (your_val_is_unused(val)) {
- yyjson_mut_arr_iter_remove(&iter);
- }
- }
- @endcode
- */
- typedef struct yyjson_mut_arr_iter {
- size_t idx; /**< next value's index */
- size_t max; /**< maximum index (arr.size) */
- yyjson_mut_val *cur; /**< current value */
- yyjson_mut_val *pre; /**< previous value */
- yyjson_mut_val *arr; /**< the array being iterated */
- } yyjson_mut_arr_iter;
- /**
- Initialize an iterator for this array.
-
- @param arr The array to be iterated over.
- If this parameter is NULL or not an array, `iter` will be set to empty.
- @param iter The iterator to be initialized.
- If this parameter is NULL, the function will fail and return false.
- @return true if the `iter` has been successfully initialized.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
- yyjson_mut_arr_iter *iter);
- /**
- Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`.
-
- @param arr The array to be iterated over.
- If this parameter is NULL or not an array, an empty iterator will returned.
- @return A new iterator for the array.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
- yyjson_mut_val *arr);
- /**
- Returns whether the iteration has more elements.
- If `iter` is NULL, this function will return false.
- */
- yyjson_api_inline bool yyjson_mut_arr_iter_has_next(
- yyjson_mut_arr_iter *iter);
- /**
- Returns the next element in the iteration, or NULL on end.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
- yyjson_mut_arr_iter *iter);
- /**
- Removes and returns current element in the iteration.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
- yyjson_mut_arr_iter *iter);
- /**
- Macro for iterating over an array.
- It works like iterator, but with a more intuitive API.
-
- @warning You should not modify the array while iterating over it.
-
- @par Example
- @code
- size_t idx, max;
- yyjson_mut_val *val;
- yyjson_mut_arr_foreach(arr, idx, max, val) {
- your_func(idx, val);
- }
- @endcode
- */
- #define yyjson_mut_arr_foreach(arr, idx, max, val) \
- for ((idx) = 0, \
- (max) = yyjson_mut_arr_size(arr), \
- (val) = yyjson_mut_arr_get_first(arr); \
- (idx) < (max); \
- (idx)++, \
- (val) = (val)->next)
- /*==============================================================================
- * Mutable JSON Array Creation API
- *============================================================================*/
- /**
- Creates and returns an empty mutable array.
- @param doc A mutable document, used for memory allocation only.
- @return The new array. NULL if input is NULL or memory allocation failed.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc);
- /**
- Creates and returns a new mutable array with the given boolean values.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of boolean values.
- @param count The value count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const bool vals[3] = { true, false, true };
- yyjson_mut_val *arr = yyjson_mut_arr_with_bool(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
- yyjson_mut_doc *doc, const bool *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given sint numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of sint numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const int64_t vals[3] = { -1, 0, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
- yyjson_mut_doc *doc, const int64_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given uint numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of uint numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const uint64_t vals[3] = { 0, 1, 0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_uint(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
- yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given real numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of real numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const double vals[3] = { 0.1, 0.2, 0.3 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_real(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
- yyjson_mut_doc *doc, const double *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given int8 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of int8 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const int8_t vals[3] = { -1, 0, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_sint8(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
- yyjson_mut_doc *doc, const int8_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given int16 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of int16 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const int16_t vals[3] = { -1, 0, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_sint16(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
- yyjson_mut_doc *doc, const int16_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given int32 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of int32 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const int32_t vals[3] = { -1, 0, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_sint32(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
- yyjson_mut_doc *doc, const int32_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given int64 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of int64 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const int64_t vals[3] = { -1, 0, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
- yyjson_mut_doc *doc, const int64_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given uint8 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of uint8 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const uint8_t vals[3] = { 0, 1, 0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_uint8(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
- yyjson_mut_doc *doc, const uint8_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given uint16 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of uint16 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const uint16_t vals[3] = { 0, 1, 0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_uint16(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
- yyjson_mut_doc *doc, const uint16_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given uint32 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of uint32 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const uint32_t vals[3] = { 0, 1, 0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_uint32(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
- yyjson_mut_doc *doc, const uint32_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given uint64 numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of uint64 numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const uint64_t vals[3] = { 0, 1, 0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_uint64(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
- yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given float numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of float numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const float vals[3] = { -1.0f, 0.0f, 1.0f };
- yyjson_mut_val *arr = yyjson_mut_arr_with_float(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
- yyjson_mut_doc *doc, const float *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given double numbers.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of double numbers.
- @param count The number count. If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const double vals[3] = { -1.0, 0.0, 1.0 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_double(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
- yyjson_mut_doc *doc, const double *vals, size_t count);
- /**
- Creates and returns a new mutable array with the given strings, these strings
- will not be copied.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of UTF-8 null-terminator strings.
- If this array contains NULL, the function will fail and return NULL.
- @param count The number of values in `vals`.
- If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @warning The input strings are not copied, you should keep these strings
- unmodified for the lifetime of this JSON document. If these strings will be
- modified, you should use `yyjson_mut_arr_with_strcpy()` instead.
-
- @par Example
- @code
- const char *vals[3] = { "a", "b", "c" };
- yyjson_mut_val *arr = yyjson_mut_arr_with_str(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
- yyjson_mut_doc *doc, const char **vals, size_t count);
- /**
- Creates and returns a new mutable array with the given strings and string
- lengths, these strings will not be copied.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of UTF-8 strings, null-terminator is not required.
- If this array contains NULL, the function will fail and return NULL.
- @param lens A C array of string lengths, in bytes.
- @param count The number of strings in `vals`.
- If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @warning The input strings are not copied, you should keep these strings
- unmodified for the lifetime of this JSON document. If these strings will be
- modified, you should use `yyjson_mut_arr_with_strncpy()` instead.
-
- @par Example
- @code
- const char *vals[3] = { "a", "bb", "c" };
- const size_t lens[3] = { 1, 2, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
- yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
- /**
- Creates and returns a new mutable array with the given strings, these strings
- will be copied.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of UTF-8 null-terminator strings.
- If this array contains NULL, the function will fail and return NULL.
- @param count The number of values in `vals`.
- If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const char *vals[3] = { "a", "b", "c" };
- yyjson_mut_val *arr = yyjson_mut_arr_with_strcpy(doc, vals, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
- yyjson_mut_doc *doc, const char **vals, size_t count);
- /**
- Creates and returns a new mutable array with the given strings and string
- lengths, these strings will be copied.
-
- @param doc A mutable document, used for memory allocation only.
- If this parameter is NULL, the function will fail and return NULL.
- @param vals A C array of UTF-8 strings, null-terminator is not required.
- If this array contains NULL, the function will fail and return NULL.
- @param lens A C array of string lengths, in bytes.
- @param count The number of strings in `vals`.
- If this value is 0, an empty array will return.
- @return The new array. NULL if input is invalid or memory allocation failed.
-
- @par Example
- @code
- const char *vals[3] = { "a", "bb", "c" };
- const size_t lens[3] = { 1, 2, 1 };
- yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
- yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
- /*==============================================================================
- * Mutable JSON Array Modification API
- *============================================================================*/
- /**
- Inserts a value into an array at a given index.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param val The value to be inserted. Returns false if it is NULL.
- @param idx The index to which to insert the new value.
- Returns false if the index is out of range.
- @return Whether successful.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
- yyjson_mut_val *val, size_t idx);
- /**
- Inserts a value at the end of the array.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param val The value to be inserted. Returns false if it is NULL.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
- yyjson_mut_val *val);
- /**
- Inserts a value at the head of the array.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param val The value to be inserted. Returns false if it is NULL.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
- yyjson_mut_val *val);
- /**
- Replaces a value at index and returns old value.
- @param arr The array to which the value is to be replaced.
- Returns false if it is NULL or not an array.
- @param idx The index to which to replace the value.
- Returns false if the index is out of range.
- @param val The new value to replace. Returns false if it is NULL.
- @return Old value, or NULL on error.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
- size_t idx,
- yyjson_mut_val *val);
- /**
- Removes and returns a value at index.
- @param arr The array from which the value is to be removed.
- Returns false if it is NULL or not an array.
- @param idx The index from which to remove the value.
- Returns false if the index is out of range.
- @return Old value, or NULL on error.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
- size_t idx);
- /**
- Removes and returns the first value in this array.
- @param arr The array from which the value is to be removed.
- Returns false if it is NULL or not an array.
- @return The first value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
- yyjson_mut_val *arr);
- /**
- Removes and returns the last value in this array.
- @param arr The array from which the value is to be removed.
- Returns false if it is NULL or not an array.
- @return The last value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
- yyjson_mut_val *arr);
- /**
- Removes all values within a specified range in the array.
- @param arr The array from which the value is to be removed.
- Returns false if it is NULL or not an array.
- @param idx The start index of the range (0 is the first).
- @param len The number of items in the range (can be 0).
- @return Whether successful.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
- size_t idx, size_t len);
- /**
- Removes all values in this array.
- @param arr The array from which all of the values are to be removed.
- Returns false if it is NULL or not an array.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr);
- /**
- Rotates values in this array for the given number of times.
- For example: `[1,2,3,4,5]` rotate 2 is `[3,4,5,1,2]`.
- @param arr The array to be rotated.
- @param idx Index (or times) to rotate.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
- size_t idx);
- /*==============================================================================
- * Mutable JSON Array Modification Convenience API
- *============================================================================*/
- /**
- Adds a value at the end of the array.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param val The value to be inserted. Returns false if it is NULL.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
- yyjson_mut_val *val);
- /**
- Adds a `null` value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
- yyjson_mut_val *arr);
- /**
- Adds a `true` value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
- yyjson_mut_val *arr);
- /**
- Adds a `false` value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
- yyjson_mut_val *arr);
- /**
- Adds a bool value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param val The bool value to be added.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- bool val);
- /**
- Adds an unsigned integer value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param num The number to be added.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- uint64_t num);
- /**
- Adds a signed integer value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param num The number to be added.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- int64_t num);
- /**
- Adds a integer value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param num The number to be added.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- int64_t num);
- /**
- Adds a double value at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param num The number to be added.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- double num);
- /**
- Adds a string value at the end of the array (no copy).
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param str A null-terminated UTF-8 string.
- @return Whether successful.
- @warning The input string is not copied, you should keep this string unmodified
- for the lifetime of this JSON document.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str);
- /**
- Adds a string value at the end of the array (no copy).
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param str A UTF-8 string, null-terminator is not required.
- @param len The length of the string, in bytes.
- @return Whether successful.
- @warning The input string is not copied, you should keep this string unmodified
- for the lifetime of this JSON document.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str,
- size_t len);
- /**
- Adds a string value at the end of the array (copied).
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param str A null-terminated UTF-8 string.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str);
- /**
- Adds a string value at the end of the array (copied).
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @param str A UTF-8 string, null-terminator is not required.
- @param len The length of the string, in bytes.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str,
- size_t len);
- /**
- Creates and adds a new array at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @return The new array, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
- yyjson_mut_val *arr);
- /**
- Creates and adds a new object at the end of the array.
- @param doc The `doc` is only used for memory allocation.
- @param arr The array to which the value is to be inserted.
- Returns false if it is NULL or not an array.
- @return The new object, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
- yyjson_mut_val *arr);
- /*==============================================================================
- * Mutable JSON Object API
- *============================================================================*/
- /** Returns the number of key-value pairs in this object.
- Returns 0 if `obj` is NULL or type is not object. */
- yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj);
- /** Returns the value to which the specified key is mapped.
- Returns NULL if this object contains no mapping for the key.
- Returns NULL if `obj/key` is NULL, or type is not object.
-
- The `key` should be a null-terminated UTF-8 string.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
- const char *key);
- /** Returns the value to which the specified key is mapped.
- Returns NULL if this object contains no mapping for the key.
- Returns NULL if `obj/key` is NULL, or type is not object.
-
- The `key` should be a UTF-8 string, null-terminator is not required.
- The `key_len` should be the length of the key, in bytes.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
- const char *key,
- size_t key_len);
- /*==============================================================================
- * Mutable JSON Object Iterator API
- *============================================================================*/
- /**
- A mutable JSON object iterator.
-
- @warning You should not modify the object while iterating over it, but you can
- use `yyjson_mut_obj_iter_remove()` to remove current value.
-
- @par Example
- @code
- yyjson_mut_val *key, *val;
- yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
- while ((key = yyjson_mut_obj_iter_next(&iter))) {
- val = yyjson_mut_obj_iter_get_val(key);
- your_func(key, val);
- if (your_val_is_unused(key, val)) {
- yyjson_mut_obj_iter_remove(&iter);
- }
- }
- @endcode
-
- If the ordering of the keys is known at compile-time, you can use this method
- to speed up value lookups:
- @code
- // {"k1":1, "k2": 3, "k3": 3}
- yyjson_mut_val *key, *val;
- yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
- yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1");
- yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3");
- @endcode
- @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()`
- */
- typedef struct yyjson_mut_obj_iter {
- size_t idx; /**< next key's index */
- size_t max; /**< maximum key index (obj.size) */
- yyjson_mut_val *cur; /**< current key */
- yyjson_mut_val *pre; /**< previous key */
- yyjson_mut_val *obj; /**< the object being iterated */
- } yyjson_mut_obj_iter;
- /**
- Initialize an iterator for this object.
-
- @param obj The object to be iterated over.
- If this parameter is NULL or not an array, `iter` will be set to empty.
- @param iter The iterator to be initialized.
- If this parameter is NULL, the function will fail and return false.
- @return true if the `iter` has been successfully initialized.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
- yyjson_mut_obj_iter *iter);
- /**
- Create an iterator with an object, same as `yyjson_obj_iter_init()`.
-
- @param obj The object to be iterated over.
- If this parameter is NULL or not an object, an empty iterator will returned.
- @return A new iterator for the object.
-
- @note The iterator does not need to be destroyed.
- */
- yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
- yyjson_mut_val *obj);
- /**
- Returns whether the iteration has more elements.
- If `iter` is NULL, this function will return false.
- */
- yyjson_api_inline bool yyjson_mut_obj_iter_has_next(
- yyjson_mut_obj_iter *iter);
- /**
- Returns the next key in the iteration, or NULL on end.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
- yyjson_mut_obj_iter *iter);
- /**
- Returns the value for key inside the iteration.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
- yyjson_mut_val *key);
- /**
- Removes current key-value pair in the iteration, returns the removed value.
- If `iter` is NULL, this function will return NULL.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
- yyjson_mut_obj_iter *iter);
- /**
- Iterates to a specified key and returns the value.
-
- This function does the same thing as `yyjson_mut_obj_get()`, but is much faster
- if the ordering of the keys is known at compile-time and you are using the same
- order to look up the values. If the key exists in this object, then the
- iterator will stop at the next key, otherwise the iterator will not change and
- NULL is returned.
-
- @param iter The object iterator, should not be NULL.
- @param key The key, should be a UTF-8 string with null-terminator.
- @return The value to which the specified key is mapped.
- NULL if this object contains no mapping for the key or input is invalid.
-
- @warning This function takes a linear search time if the key is not nearby.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
- yyjson_mut_obj_iter *iter, const char *key);
- /**
- Iterates to a specified key and returns the value.
-
- This function does the same thing as `yyjson_mut_obj_getn()` but is much faster
- if the ordering of the keys is known at compile-time and you are using the same
- order to look up the values. If the key exists in this object, then the
- iterator will stop at the next key, otherwise the iterator will not change and
- NULL is returned.
-
- @param iter The object iterator, should not be NULL.
- @param key The key, should be a UTF-8 string, null-terminator is not required.
- @param key_len The the length of `key`, in bytes.
- @return The value to which the specified key is mapped.
- NULL if this object contains no mapping for the key or input is invalid.
-
- @warning This function takes a linear search time if the key is not nearby.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
- yyjson_mut_obj_iter *iter, const char *key, size_t key_len);
- /**
- Macro for iterating over an object.
- It works like iterator, but with a more intuitive API.
-
- @warning You should not modify the object while iterating over it.
-
- @par Example
- @code
- size_t idx, max;
- yyjson_val *key, *val;
- yyjson_obj_foreach(obj, idx, max, key, val) {
- your_func(key, val);
- }
- @endcode
- */
- #define yyjson_mut_obj_foreach(obj, idx, max, key, val) \
- for ((idx) = 0, \
- (max) = yyjson_mut_obj_size(obj), \
- (key) = (max) ? ((yyjson_mut_val *)(obj)->uni.ptr)->next->next : NULL, \
- (val) = (key) ? (key)->next : NULL; \
- (idx) < (max); \
- (idx)++, \
- (key) = (val)->next, \
- (val) = (key)->next)
- /*==============================================================================
- * Mutable JSON Object Creation API
- *============================================================================*/
- /** Creates and returns a mutable object, returns NULL on error. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc);
- /**
- Creates and returns a mutable object with keys and values, returns NULL on
- error. The keys and values are not copied. The strings should be a
- null-terminated UTF-8 string.
-
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document.
-
- @par Example
- @code
- const char *keys[2] = { "id", "name" };
- const char *vals[2] = { "01", "Harry" };
- yyjson_mut_val *obj = yyjson_mut_obj_with_str(doc, keys, vals, 2);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
- const char **keys,
- const char **vals,
- size_t count);
- /**
- Creates and returns a mutable object with key-value pairs and pair count,
- returns NULL on error. The keys and values are not copied. The strings should
- be a null-terminated UTF-8 string.
-
- @warning The input string is not copied, you should keep this string
- unmodified for the lifetime of this JSON document.
-
- @par Example
- @code
- const char *kv_pairs[4] = { "id", "01", "name", "Harry" };
- yyjson_mut_val *obj = yyjson_mut_obj_with_kv(doc, kv_pairs, 2);
- @endcode
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
- const char **kv_pairs,
- size_t pair_count);
- /*==============================================================================
- * Mutable JSON Object Modification API
- *============================================================================*/
- /**
- Adds a key-value pair at the end of the object.
- This function allows duplicated key in one object.
- @param obj The object to which the new key-value pair is to be added.
- @param key The key, should be a string which is created by `yyjson_mut_str()`,
- `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
- @param val The value to add to the object.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val);
- /**
- Sets a key-value pair at the end of the object.
- This function may remove all key-value pairs for the given key before add.
- @param obj The object to which the new key-value pair is to be added.
- @param key The key, should be a string which is created by `yyjson_mut_str()`,
- `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
- @param val The value to add to the object. If this value is null, the behavior
- is same as `yyjson_mut_obj_remove()`.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val);
- /**
- Inserts a key-value pair to the object at the given position.
- This function allows duplicated key in one object.
- @param obj The object to which the new key-value pair is to be added.
- @param key The key, should be a string which is created by `yyjson_mut_str()`,
- `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
- @param val The value to add to the object.
- @param idx The index to which to insert the new pair.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val,
- size_t idx);
- /**
- Removes all key-value pair from the object with given key.
- @param obj The object from which the key-value pair is to be removed.
- @param key The key, should be a string value.
- @return The first matched value, or NULL if no matched value.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
- yyjson_mut_val *key);
- /**
- Removes all key-value pair from the object with given key.
- @param obj The object from which the key-value pair is to be removed.
- @param key The key, should be a UTF-8 string with null-terminator.
- @return The first matched value, or NULL if no matched value.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
- yyjson_mut_val *obj, const char *key);
- /**
- Removes all key-value pair from the object with given key.
- @param obj The object from which the key-value pair is to be removed.
- @param key The key, should be a UTF-8 string, null-terminator is not required.
- @param key_len The length of the key.
- @return The first matched value, or NULL if no matched value.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
- yyjson_mut_val *obj, const char *key, size_t key_len);
- /**
- Removes all key-value pairs in this object.
- @param obj The object from which all of the values are to be removed.
- @return Whether successful.
- */
- yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj);
- /**
- Replaces value from the object with given key.
- If the key is not exist, or the value is NULL, it will fail.
- @param obj The object to which the value is to be replaced.
- @param key The key, should be a string value.
- @param val The value to replace into the object.
- @return Whether successful.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val);
- /**
- Rotates key-value pairs in the object for the given number of times.
- For example: `{"a":1,"b":2,"c":3,"d":4}` rotate 1 is
- `{"b":2,"c":3,"d":4,"a":1}`.
- @param obj The object to be rotated.
- @param idx Index (or times) to rotate.
- @return Whether successful.
- @warning This function takes a linear search time.
- */
- yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
- size_t idx);
- /*==============================================================================
- * Mutable JSON Object Modification Convenience API
- *============================================================================*/
- /** Adds a `null` value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key);
- /** Adds a `true` value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key);
- /** Adds a `false` value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key);
- /** Adds a bool value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, bool val);
- /** Adds an unsigned integer value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, uint64_t val);
- /** Adds a signed integer value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, int64_t val);
- /** Adds an int value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, int64_t val);
- /** Adds a double value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, double val);
- /** Adds a string value at the end of the object.
- The `key` and `val` should be null-terminated UTF-8 strings.
- This function allows duplicated key in one object.
-
- @warning The key/value string are not copied, you should keep these strings
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key, const char *val);
- /** Adds a string value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- The `val` should be a UTF-8 string, null-terminator is not required.
- The `len` should be the length of the `val`, in bytes.
- This function allows duplicated key in one object.
-
- @warning The key/value string are not copied, you should keep these strings
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- const char *val, size_t len);
- /** Adds a string value at the end of the object.
- The `key` and `val` should be null-terminated UTF-8 strings.
- The value string is copied.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- const char *val);
- /** Adds a string value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- The `val` should be a UTF-8 string, null-terminator is not required.
- The `len` should be the length of the `val`, in bytes.
- This function allows duplicated key in one object.
-
- @warning The key/value string are not copied, you should keep these strings
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- const char *val, size_t len);
- /** Adds a JSON value at the end of the object.
- The `key` should be a null-terminated UTF-8 string.
- This function allows duplicated key in one object.
-
- @warning The key string are not copied, you should keep the string
- unmodified for the lifetime of this JSON document. */
- yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- yyjson_mut_val *val);
- /** Removes all key-value pairs for the given key.
- Returns the first value to which the specified key is mapped or NULL if this
- object contains no mapping for the key.
- The `key` should be a null-terminated UTF-8 string.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(
- yyjson_mut_val *obj, const char *key);
- /** Removes all key-value pairs for the given key.
- Returns the first value to which the specified key is mapped or NULL if this
- object contains no mapping for the key.
- The `key` should be a UTF-8 string, null-terminator is not required.
- The `len` should be the length of the key, in bytes.
-
- @warning This function takes a linear search time. */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
- yyjson_mut_val *obj, const char *key, size_t len);
- /** Replaces all matching keys with the new key.
- Returns true if at least one key was renamed.
- The `key` and `new_key` should be a null-terminated UTF-8 string.
- The `new_key` is copied and held by doc.
-
- @warning This function takes a linear search time.
- If `new_key` already exists, it will cause duplicate keys.
- */
- yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- const char *new_key);
- /** Replaces all matching keys with the new key.
- Returns true if at least one key was renamed.
- The `key` and `new_key` should be a UTF-8 string,
- null-terminator is not required. The `new_key` is copied and held by doc.
-
- @warning This function takes a linear search time.
- If `new_key` already exists, it will cause duplicate keys.
- */
- yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- size_t len,
- const char *new_key,
- size_t new_len);
- /*==============================================================================
- * JSON Pointer API (RFC 6901)
- * https://tools.ietf.org/html/rfc6901
- *============================================================================*/
- /** JSON Pointer error code. */
- typedef uint32_t yyjson_ptr_code;
- /** No JSON pointer error. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0;
- /** Invalid input parameter, such as NULL input. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1;
- /** JSON pointer syntax error, such as invalid escape, token no prefix. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2;
- /** JSON pointer resolve failed, such as index out of range, key not found. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3;
- /** Document's root is NULL, but it is required for the function call. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4;
- /** Cannot set root as the target is not a document. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5;
- /** The memory allocation failed and a new value could not be created. */
- static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6;
- /** Error information for JSON pointer. */
- typedef struct yyjson_ptr_err {
- /** Error code, see `yyjson_ptr_code` for all possible values. */
- yyjson_ptr_code code;
- /** Error message, constant, no need to free (NULL if no error). */
- const char *msg;
- /** Error byte position for input JSON pointer (0 if no error). */
- size_t pos;
- } yyjson_ptr_err;
- /**
- A context for JSON pointer operation.
-
- This struct stores the context of JSON Pointer operation result. The struct
- can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and
- `ctx_remove()`, which perform the corresponding operations on the container
- without re-parsing the JSON Pointer.
-
- For example:
- @code
- // doc before: {"a":[0,1,null]}
- // ptr: "/a/2"
- val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err);
- if (yyjson_is_null(val)) {
- yyjson_ptr_ctx_remove(&ctx);
- }
- // doc after: {"a":[0,1]}
- @endcode
- */
- typedef struct yyjson_ptr_ctx {
- /**
- The container (parent) of the target value. It can be either an array or
- an object. If the target location has no value, but all its parent
- containers exist, and the target location can be used to insert a new
- value, then `ctn` is the parent container of the target location.
- Otherwise, `ctn` is NULL.
- */
- yyjson_mut_val *ctn;
- /**
- The previous sibling of the target value. It can be either a value in an
- array or a key in an object. As the container is a `circular linked list`
- of elements, `pre` is the previous node of the target value. If the
- operation is `add` or `set`, then `pre` is the previous node of the new
- value, not the original target value. If the target value does not exist,
- `pre` is NULL.
- */
- yyjson_mut_val *pre;
- /**
- The removed value if the operation is `set`, `replace` or `remove`. It can
- be used to restore the original state of the document if needed.
- */
- yyjson_mut_val *old;
- } yyjson_ptr_ctx;
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
- const char *ptr);
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
- const char *ptr, size_t len);
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
- const char *ptr, size_t len,
- yyjson_ptr_err *err);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
- const char *ptr);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
- const char *ptr, size_t len);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
- const char *ptr, size_t len,
- yyjson_ptr_err *err);
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
- const char *ptr);
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
- const char *ptr,
- size_t len);
- /**
- Get value by a JSON Pointer.
- @param doc The JSON document to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The value referenced by the JSON pointer.
- NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
- const char *ptr);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
- const char *ptr,
- size_t len);
- /**
- Get value by a JSON Pointer.
- @param val The JSON value to be queried.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The value referenced by the JSON pointer.
- NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Add (insert) value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param new_val The value to be added.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- @note The parent nodes will be created if they do not exist.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
- const char *ptr,
- yyjson_mut_val *new_val);
- /**
- Add (insert) value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be added.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- @note The parent nodes will be created if they do not exist.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val);
- /**
- Add (insert) value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be added.
- @param create_parent Whether to create parent nodes if not exist.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Add (insert) value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param doc Only used to create new values when needed.
- @param new_val The value to be added.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- @note The parent nodes will be created if they do not exist.
- */
- yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
- const char *ptr,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc);
- /**
- Add (insert) value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param doc Only used to create new values when needed.
- @param new_val The value to be added.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- @note The parent nodes will be created if they do not exist.
- */
- yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc);
- /**
- Add (insert) value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param doc Only used to create new values when needed.
- @param new_val The value to be added.
- @param create_parent Whether to create parent nodes if not exist.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return true if JSON pointer is valid and new value is added, false otherwise.
- */
- yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Set value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param new_val The value to be set, pass NULL to remove.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note The parent nodes will be created if they do not exist.
- If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
- const char *ptr,
- yyjson_mut_val *new_val);
- /**
- Set value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be set, pass NULL to remove.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note The parent nodes will be created if they do not exist.
- If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val);
- /**
- Set value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be set, pass NULL to remove.
- @param create_parent Whether to create parent nodes if not exist.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Set value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param new_val The value to be set, pass NULL to remove.
- @param doc Only used to create new values when needed.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note The parent nodes will be created if they do not exist.
- If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
- const char *ptr,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc);
- /**
- Set value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be set, pass NULL to remove.
- @param doc Only used to create new values when needed.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note The parent nodes will be created if they do not exist.
- If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc);
- /**
- Set value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The value to be set, pass NULL to remove.
- @param doc Only used to create new values when needed.
- @param create_parent Whether to create parent nodes if not exist.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return true if JSON pointer is valid and new value is set, false otherwise.
- @note If the target value already exists, it will be replaced by the new value.
- */
- yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Replace value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param new_val The new value to replace the old one.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
- yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val);
- /**
- Replace value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The new value to replace the old one.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
- yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val);
- /**
- Replace value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The new value to replace the old one.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
- yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
- /**
- Replace value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @param new_val The new value to replace the old one.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
- yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val);
- /**
- Replace value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The new value to replace the old one.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
- yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val);
- /**
- Replace value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param new_val The new value to replace the old one.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The old value that was replaced, or NULL if not found.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
- yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
- /**
- Remove value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
- yyjson_mut_doc *doc, const char *ptr);
- /**
- Remove value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
- yyjson_mut_doc *doc, const char *ptr, size_t len);
- /**
- Remove value by a JSON pointer.
- @param doc The target JSON document.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
- yyjson_mut_doc *doc, const char *ptr, size_t len,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
- /**
- Remove value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8 with null-terminator).
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
- const char *ptr);
- /**
- Remove value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
- const char *ptr,
- size_t len);
- /**
- Remove value by a JSON pointer.
- @param val The target JSON value.
- @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
- @param len The length of `ptr` in bytes.
- @param ctx A pointer to store the result context, or NULL if not needed.
- @param err A pointer to store the error information, or NULL if not needed.
- @return The removed value, or NULL on error.
- */
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /**
- Append value by JSON pointer context.
- @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
- @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array.
- @param val New value to be added.
- @return true on success or false on fail.
- */
- yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
- yyjson_mut_val *key,
- yyjson_mut_val *val);
- /**
- Replace value by JSON pointer context.
- @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
- @param val New value to be replaced.
- @return true on success or false on fail.
- @note If success, the old value will be returned via `ctx->old`.
- */
- yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
- yyjson_mut_val *val);
- /**
- Remove value by JSON pointer context.
- @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
- @return true on success or false on fail.
- @note If success, the old value will be returned via `ctx->old`.
- */
- yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx);
- /*==============================================================================
- * JSON Patch API (RFC 6902)
- * https://tools.ietf.org/html/rfc6902
- *============================================================================*/
- /** Result code for JSON patch. */
- typedef uint32_t yyjson_patch_code;
- /** Success, no error. */
- static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0;
- /** Invalid parameter, such as NULL input or non-array patch. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1;
- /** Memory allocation failure occurs. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2;
- /** JSON patch operation is not object type. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3;
- /** JSON patch operation is missing a required key. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4;
- /** JSON patch operation member is invalid. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5;
- /** JSON patch operation `test` not equal. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6;
- /** JSON patch operation failed on JSON pointer. */
- static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7;
- /** Error information for JSON patch. */
- typedef struct yyjson_patch_err {
- /** Error code, see `yyjson_patch_code` for all possible values. */
- yyjson_patch_code code;
- /** Index of the error operation (0 if no error). */
- size_t idx;
- /** Error message, constant, no need to free (NULL if no error). */
- const char *msg;
- /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */
- yyjson_ptr_err ptr;
- } yyjson_patch_err;
- /**
- Creates and returns a patched JSON value (RFC 6902).
- The memory of the returned value is allocated by the `doc`.
- The `err` is used to receive error information, pass NULL if not needed.
- Returns NULL if the patch could not be applied.
- */
- yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc,
- yyjson_val *orig,
- yyjson_val *patch,
- yyjson_patch_err *err);
- /**
- Creates and returns a patched JSON value (RFC 6902).
- The memory of the returned value is allocated by the `doc`.
- The `err` is used to receive error information, pass NULL if not needed.
- Returns NULL if the patch could not be applied.
- */
- yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc,
- yyjson_mut_val *orig,
- yyjson_mut_val *patch,
- yyjson_patch_err *err);
- /*==============================================================================
- * JSON Merge-Patch API (RFC 7386)
- * https://tools.ietf.org/html/rfc7386
- *============================================================================*/
- /**
- Creates and returns a merge-patched JSON value (RFC 7386).
- The memory of the returned value is allocated by the `doc`.
- Returns NULL if the patch could not be applied.
- @warning This function is recursive and may cause a stack overflow if the
- object level is too deep.
- */
- yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
- yyjson_val *orig,
- yyjson_val *patch);
- /**
- Creates and returns a merge-patched JSON value (RFC 7386).
- The memory of the returned value is allocated by the `doc`.
- Returns NULL if the patch could not be applied.
- @warning This function is recursive and may cause a stack overflow if the
- object level is too deep.
- */
- yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
- yyjson_mut_val *orig,
- yyjson_mut_val *patch);
- /*==============================================================================
- * JSON Structure (Implementation)
- *============================================================================*/
- /** Payload of a JSON value (8 bytes). */
- typedef union yyjson_val_uni {
- uint64_t u64;
- int64_t i64;
- double f64;
- const char *str;
- void *ptr;
- size_t ofs;
- } yyjson_val_uni;
- /**
- Immutable JSON value, 16 bytes.
- */
- struct yyjson_val {
- uint64_t tag; /**< type, subtype and length */
- yyjson_val_uni uni; /**< payload */
- };
- struct yyjson_doc {
- /** Root value of the document (nonnull). */
- yyjson_val *root;
- /** Allocator used by document (nonnull). */
- yyjson_alc alc;
- /** The total number of bytes read when parsing JSON (nonzero). */
- size_t dat_read;
- /** The total number of value read when parsing JSON (nonzero). */
- size_t val_read;
- /** The string pool used by JSON values (nullable). */
- char *str_pool;
- };
- /*==============================================================================
- * Unsafe JSON Value API (Implementation)
- *============================================================================*/
- /*
- Whether the string does not need to be escaped for serialization.
- This function is used to optimize the writing speed of small constant strings.
- This function works only if the compiler can evaluate it at compile time.
-
- Clang supports it since v8.0,
- earlier versions do not support constant_p(strlen) and return false.
- GCC supports it since at least v4.4,
- earlier versions may compile it as run-time instructions.
- ICC supports it since at least v16,
- earlier versions are uncertain.
-
- @param str The C string.
- @param len The returnd value from strlen(str).
- */
- yyjson_api_inline bool unsafe_yyjson_is_str_noesc(const char *str, size_t len) {
- #if YYJSON_HAS_CONSTANT_P && \
- (!YYJSON_IS_REAL_GCC || yyjson_gcc_available(4, 4, 0))
- if (yyjson_constant_p(len) && len <= 32) {
- /*
- Same as the following loop:
-
- for (size_t i = 0; i < len; i++) {
- char c = str[i];
- if (c < ' ' || c > '~' || c == '"' || c == '\\') return false;
- }
-
- GCC evaluates it at compile time only if the string length is within 17
- and -O3 (which turns on the -fpeel-loops flag) is used.
- So the loop is unrolled for GCC.
- */
- # define yyjson_repeat32_incr(x) \
- x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \
- x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \
- x(16) x(17) x(18) x(19) x(20) x(21) x(22) x(23) \
- x(24) x(25) x(26) x(27) x(28) x(29) x(30) x(31)
- # define yyjson_check_char_noesc(i) \
- if (i < len) { \
- char c = str[i]; \
- if (c < ' ' || c > '~' || c == '"' || c == '\\') return false; }
- yyjson_repeat32_incr(yyjson_check_char_noesc)
- # undef yyjson_repeat32_incr
- # undef yyjson_check_char_noesc
- return true;
- }
- #else
- (void)str;
- (void)len;
- #endif
- return false;
- }
- yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) {
- uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
- return (yyjson_type)(tag & YYJSON_TYPE_MASK);
- }
- yyjson_api_inline yyjson_subtype unsafe_yyjson_get_subtype(void *val) {
- uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
- return (yyjson_subtype)(tag & YYJSON_SUBTYPE_MASK);
- }
- yyjson_api_inline uint8_t unsafe_yyjson_get_tag(void *val) {
- uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
- return (uint8_t)(tag & YYJSON_TAG_MASK);
- }
- yyjson_api_inline bool unsafe_yyjson_is_raw(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_RAW;
- }
- yyjson_api_inline bool unsafe_yyjson_is_null(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NULL;
- }
- yyjson_api_inline bool unsafe_yyjson_is_bool(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_BOOL;
- }
- yyjson_api_inline bool unsafe_yyjson_is_num(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NUM;
- }
- yyjson_api_inline bool unsafe_yyjson_is_str(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_STR;
- }
- yyjson_api_inline bool unsafe_yyjson_is_arr(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_ARR;
- }
- yyjson_api_inline bool unsafe_yyjson_is_obj(void *val) {
- return unsafe_yyjson_get_type(val) == YYJSON_TYPE_OBJ;
- }
- yyjson_api_inline bool unsafe_yyjson_is_ctn(void *val) {
- uint8_t mask = YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ;
- return (unsafe_yyjson_get_tag(val) & mask) == mask;
- }
- yyjson_api_inline bool unsafe_yyjson_is_uint(void *val) {
- const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- return unsafe_yyjson_get_tag(val) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_is_sint(void *val) {
- const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- return unsafe_yyjson_get_tag(val) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_is_int(void *val) {
- const uint8_t mask = YYJSON_TAG_MASK & (~YYJSON_SUBTYPE_SINT);
- const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- return (unsafe_yyjson_get_tag(val) & mask) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_is_real(void *val) {
- const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
- return unsafe_yyjson_get_tag(val) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_is_true(void *val) {
- const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
- return unsafe_yyjson_get_tag(val) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_is_false(void *val) {
- const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
- return unsafe_yyjson_get_tag(val) == patt;
- }
- yyjson_api_inline bool unsafe_yyjson_arr_is_flat(yyjson_val *val) {
- size_t ofs = val->uni.ofs;
- size_t len = (size_t)(val->tag >> YYJSON_TAG_BIT);
- return len * sizeof(yyjson_val) + sizeof(yyjson_val) == ofs;
- }
- yyjson_api_inline const char *unsafe_yyjson_get_raw(void *val) {
- return ((yyjson_val *)val)->uni.str;
- }
- yyjson_api_inline bool unsafe_yyjson_get_bool(void *val) {
- uint8_t tag = unsafe_yyjson_get_tag(val);
- return (bool)((tag & YYJSON_SUBTYPE_MASK) >> YYJSON_TYPE_BIT);
- }
- yyjson_api_inline uint64_t unsafe_yyjson_get_uint(void *val) {
- return ((yyjson_val *)val)->uni.u64;
- }
- yyjson_api_inline int64_t unsafe_yyjson_get_sint(void *val) {
- return ((yyjson_val *)val)->uni.i64;
- }
- yyjson_api_inline int unsafe_yyjson_get_int(void *val) {
- return (int)((yyjson_val *)val)->uni.i64;
- }
- yyjson_api_inline double unsafe_yyjson_get_real(void *val) {
- return ((yyjson_val *)val)->uni.f64;
- }
- yyjson_api_inline double unsafe_yyjson_get_num(void *val) {
- uint8_t tag = unsafe_yyjson_get_tag(val);
- if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) {
- return ((yyjson_val *)val)->uni.f64;
- } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) {
- return (double)((yyjson_val *)val)->uni.i64;
- } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) {
- #if YYJSON_U64_TO_F64_NO_IMPL
- uint64_t msb = ((uint64_t)1) << 63;
- uint64_t num = ((yyjson_val *)val)->uni.u64;
- if ((num & msb) == 0) {
- return (double)(int64_t)num;
- } else {
- return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0;
- }
- #else
- return (double)((yyjson_val *)val)->uni.u64;
- #endif
- }
- return 0.0;
- }
- yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) {
- return ((yyjson_val *)val)->uni.str;
- }
- yyjson_api_inline size_t unsafe_yyjson_get_len(void *val) {
- return (size_t)(((yyjson_val *)val)->tag >> YYJSON_TAG_BIT);
- }
- yyjson_api_inline yyjson_val *unsafe_yyjson_get_first(yyjson_val *ctn) {
- return ctn + 1;
- }
- yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) {
- bool is_ctn = unsafe_yyjson_is_ctn(val);
- size_t ctn_ofs = val->uni.ofs;
- size_t ofs = (is_ctn ? ctn_ofs : sizeof(yyjson_val));
- return (yyjson_val *)(void *)((uint8_t *)val + ofs);
- }
- yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str,
- size_t len) {
- return unsafe_yyjson_get_len(val) == len &&
- memcmp(((yyjson_val *)val)->uni.str, str, len) == 0;
- }
- yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) {
- return unsafe_yyjson_equals_strn(val, str, strlen(str));
- }
- yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type,
- yyjson_subtype subtype) {
- uint8_t tag = (type | subtype);
- uint64_t new_tag = ((yyjson_val *)val)->tag;
- new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag;
- ((yyjson_val *)val)->tag = new_tag;
- }
- yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) {
- uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK;
- tag |= (uint64_t)len << YYJSON_TAG_BIT;
- ((yyjson_val *)val)->tag = tag;
- }
- yyjson_api_inline void unsafe_yyjson_inc_len(void *val) {
- uint64_t tag = ((yyjson_val *)val)->tag;
- tag += (uint64_t)(1 << YYJSON_TAG_BIT);
- ((yyjson_val *)val)->tag = tag;
- }
- yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw,
- size_t len) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE);
- unsafe_yyjson_set_len(val, len);
- ((yyjson_val *)val)->uni.str = raw;
- }
- yyjson_api_inline void unsafe_yyjson_set_null(void *val) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_NULL, YYJSON_SUBTYPE_NONE);
- unsafe_yyjson_set_len(val, 0);
- }
- yyjson_api_inline void unsafe_yyjson_set_bool(void *val, bool num) {
- yyjson_subtype subtype = num ? YYJSON_SUBTYPE_TRUE : YYJSON_SUBTYPE_FALSE;
- unsafe_yyjson_set_type(val, YYJSON_TYPE_BOOL, subtype);
- unsafe_yyjson_set_len(val, 0);
- }
- yyjson_api_inline void unsafe_yyjson_set_uint(void *val, uint64_t num) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_UINT);
- unsafe_yyjson_set_len(val, 0);
- ((yyjson_val *)val)->uni.u64 = num;
- }
- yyjson_api_inline void unsafe_yyjson_set_sint(void *val, int64_t num) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_SINT);
- unsafe_yyjson_set_len(val, 0);
- ((yyjson_val *)val)->uni.i64 = num;
- }
- yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL);
- unsafe_yyjson_set_len(val, 0);
- ((yyjson_val *)val)->uni.f64 = num;
- }
- yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) {
- size_t len = strlen(str);
- bool noesc = unsafe_yyjson_is_str_noesc(str, len);
- yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
- unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, sub);
- unsafe_yyjson_set_len(val, len);
- ((yyjson_val *)val)->uni.str = str;
- }
- yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str,
- size_t len) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE);
- unsafe_yyjson_set_len(val, len);
- ((yyjson_val *)val)->uni.str = str;
- }
- yyjson_api_inline void unsafe_yyjson_set_arr(void *val, size_t size) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_ARR, YYJSON_SUBTYPE_NONE);
- unsafe_yyjson_set_len(val, size);
- }
- yyjson_api_inline void unsafe_yyjson_set_obj(void *val, size_t size) {
- unsafe_yyjson_set_type(val, YYJSON_TYPE_OBJ, YYJSON_SUBTYPE_NONE);
- unsafe_yyjson_set_len(val, size);
- }
- /*==============================================================================
- * JSON Document API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc) {
- return doc ? doc->root : NULL;
- }
- yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc) {
- return doc ? doc->dat_read : 0;
- }
- yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) {
- return doc ? doc->val_read : 0;
- }
- yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) {
- if (doc) {
- yyjson_alc alc = doc->alc;
- if (doc->str_pool) alc.free(alc.ctx, doc->str_pool);
- alc.free(alc.ctx, doc);
- }
- }
- /*==============================================================================
- * JSON Value Type API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_is_raw(yyjson_val *val) {
- return val ? unsafe_yyjson_is_raw(val) : false;
- }
- yyjson_api_inline bool yyjson_is_null(yyjson_val *val) {
- return val ? unsafe_yyjson_is_null(val) : false;
- }
- yyjson_api_inline bool yyjson_is_true(yyjson_val *val) {
- return val ? unsafe_yyjson_is_true(val) : false;
- }
- yyjson_api_inline bool yyjson_is_false(yyjson_val *val) {
- return val ? unsafe_yyjson_is_false(val) : false;
- }
- yyjson_api_inline bool yyjson_is_bool(yyjson_val *val) {
- return val ? unsafe_yyjson_is_bool(val) : false;
- }
- yyjson_api_inline bool yyjson_is_uint(yyjson_val *val) {
- return val ? unsafe_yyjson_is_uint(val) : false;
- }
- yyjson_api_inline bool yyjson_is_sint(yyjson_val *val) {
- return val ? unsafe_yyjson_is_sint(val) : false;
- }
- yyjson_api_inline bool yyjson_is_int(yyjson_val *val) {
- return val ? unsafe_yyjson_is_int(val) : false;
- }
- yyjson_api_inline bool yyjson_is_real(yyjson_val *val) {
- return val ? unsafe_yyjson_is_real(val) : false;
- }
- yyjson_api_inline bool yyjson_is_num(yyjson_val *val) {
- return val ? unsafe_yyjson_is_num(val) : false;
- }
- yyjson_api_inline bool yyjson_is_str(yyjson_val *val) {
- return val ? unsafe_yyjson_is_str(val) : false;
- }
- yyjson_api_inline bool yyjson_is_arr(yyjson_val *val) {
- return val ? unsafe_yyjson_is_arr(val) : false;
- }
- yyjson_api_inline bool yyjson_is_obj(yyjson_val *val) {
- return val ? unsafe_yyjson_is_obj(val) : false;
- }
- yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val) {
- return val ? unsafe_yyjson_is_ctn(val) : false;
- }
- /*==============================================================================
- * JSON Value Content API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val) {
- return val ? unsafe_yyjson_get_type(val) : YYJSON_TYPE_NONE;
- }
- yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val) {
- return val ? unsafe_yyjson_get_subtype(val) : YYJSON_SUBTYPE_NONE;
- }
- yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val) {
- return val ? unsafe_yyjson_get_tag(val) : 0;
- }
- yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) {
- switch (yyjson_get_tag(val)) {
- case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw";
- case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null";
- case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string";
- case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: return "string";
- case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array";
- case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object";
- case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true";
- case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE: return "false";
- case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: return "uint";
- case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: return "sint";
- case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: return "real";
- default: return "unknown";
- }
- }
- yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val) {
- return yyjson_is_raw(val) ? unsafe_yyjson_get_raw(val) : NULL;
- }
- yyjson_api_inline bool yyjson_get_bool(yyjson_val *val) {
- return yyjson_is_bool(val) ? unsafe_yyjson_get_bool(val) : false;
- }
- yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val) {
- return yyjson_is_int(val) ? unsafe_yyjson_get_uint(val) : 0;
- }
- yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val) {
- return yyjson_is_int(val) ? unsafe_yyjson_get_sint(val) : 0;
- }
- yyjson_api_inline int yyjson_get_int(yyjson_val *val) {
- return yyjson_is_int(val) ? unsafe_yyjson_get_int(val) : 0;
- }
- yyjson_api_inline double yyjson_get_real(yyjson_val *val) {
- return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0;
- }
- yyjson_api_inline double yyjson_get_num(yyjson_val *val) {
- return val ? unsafe_yyjson_get_num(val) : 0.0;
- }
- yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) {
- return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL;
- }
- yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) {
- return val ? unsafe_yyjson_get_len(val) : 0;
- }
- yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) {
- if (yyjson_likely(val && str)) {
- return unsafe_yyjson_is_str(val) &&
- unsafe_yyjson_equals_str(val, str);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
- size_t len) {
- if (yyjson_likely(val && str)) {
- return unsafe_yyjson_is_str(val) &&
- unsafe_yyjson_equals_strn(val, str, len);
- }
- return false;
- }
- yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
- yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
- if (yyjson_unlikely(!lhs || !rhs)) return false;
- return unsafe_yyjson_equals(lhs, rhs);
- }
- yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
- const char *raw, size_t len) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_raw(val, raw, len);
- return true;
- }
- yyjson_api_inline bool yyjson_set_null(yyjson_val *val) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_null(val);
- return true;
- }
- yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_bool(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_uint(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_sint(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_sint(val, (int64_t)num);
- return true;
- }
- yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- unsafe_yyjson_set_real(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- if (yyjson_unlikely(!str)) return false;
- unsafe_yyjson_set_str(val, str);
- return true;
- }
- yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
- const char *str, size_t len) {
- if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
- if (yyjson_unlikely(!str)) return false;
- unsafe_yyjson_set_strn(val, str, len);
- return true;
- }
- /*==============================================================================
- * JSON Array API (Implementation)
- *============================================================================*/
- yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr) {
- return yyjson_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
- }
- yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx) {
- if (yyjson_likely(yyjson_is_arr(arr))) {
- if (yyjson_likely(unsafe_yyjson_get_len(arr) > idx)) {
- yyjson_val *val = unsafe_yyjson_get_first(arr);
- if (unsafe_yyjson_arr_is_flat(arr)) {
- return val + idx;
- } else {
- while (idx-- > 0) val = unsafe_yyjson_get_next(val);
- return val;
- }
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr) {
- if (yyjson_likely(yyjson_is_arr(arr))) {
- if (yyjson_likely(unsafe_yyjson_get_len(arr) > 0)) {
- return unsafe_yyjson_get_first(arr);
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) {
- if (yyjson_likely(yyjson_is_arr(arr))) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_likely(len > 0)) {
- yyjson_val *val = unsafe_yyjson_get_first(arr);
- if (unsafe_yyjson_arr_is_flat(arr)) {
- return val + (len - 1);
- } else {
- while (len-- > 1) val = unsafe_yyjson_get_next(val);
- return val;
- }
- }
- }
- return NULL;
- }
- /*==============================================================================
- * JSON Array Iterator API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
- yyjson_arr_iter *iter) {
- if (yyjson_likely(yyjson_is_arr(arr) && iter)) {
- iter->idx = 0;
- iter->max = unsafe_yyjson_get_len(arr);
- iter->cur = unsafe_yyjson_get_first(arr);
- return true;
- }
- if (iter) memset(iter, 0, sizeof(yyjson_arr_iter));
- return false;
- }
- yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) {
- yyjson_arr_iter iter;
- yyjson_arr_iter_init(arr, &iter);
- return iter;
- }
- yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) {
- return iter ? iter->idx < iter->max : false;
- }
- yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter) {
- yyjson_val *val;
- if (iter && iter->idx < iter->max) {
- val = iter->cur;
- iter->cur = unsafe_yyjson_get_next(val);
- iter->idx++;
- return val;
- }
- return NULL;
- }
- /*==============================================================================
- * JSON Object API (Implementation)
- *============================================================================*/
- yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj) {
- return yyjson_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
- }
- yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj,
- const char *key) {
- return yyjson_obj_getn(obj, key, key ? strlen(key) : 0);
- }
- yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj,
- const char *_key,
- size_t key_len) {
- if (yyjson_likely(yyjson_is_obj(obj) && _key)) {
- size_t len = unsafe_yyjson_get_len(obj);
- yyjson_val *key = unsafe_yyjson_get_first(obj);
- while (len-- > 0) {
- if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key + 1;
- key = unsafe_yyjson_get_next(key + 1);
- }
- }
- return NULL;
- }
- /*==============================================================================
- * JSON Object Iterator API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
- yyjson_obj_iter *iter) {
- if (yyjson_likely(yyjson_is_obj(obj) && iter)) {
- iter->idx = 0;
- iter->max = unsafe_yyjson_get_len(obj);
- iter->cur = unsafe_yyjson_get_first(obj);
- iter->obj = obj;
- return true;
- }
- if (iter) memset(iter, 0, sizeof(yyjson_obj_iter));
- return false;
- }
- yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) {
- yyjson_obj_iter iter;
- yyjson_obj_iter_init(obj, &iter);
- return iter;
- }
- yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) {
- return iter ? iter->idx < iter->max : false;
- }
- yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter) {
- if (iter && iter->idx < iter->max) {
- yyjson_val *key = iter->cur;
- iter->idx++;
- iter->cur = unsafe_yyjson_get_next(key + 1);
- return key;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key) {
- return key ? key + 1 : NULL;
- }
- yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
- const char *key) {
- return yyjson_obj_iter_getn(iter, key, key ? strlen(key) : 0);
- }
- yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
- const char *key,
- size_t key_len) {
- if (iter && key) {
- size_t idx = iter->idx;
- size_t max = iter->max;
- yyjson_val *cur = iter->cur;
- if (yyjson_unlikely(idx == max)) {
- idx = 0;
- cur = unsafe_yyjson_get_first(iter->obj);
- }
- while (idx++ < max) {
- yyjson_val *next = unsafe_yyjson_get_next(cur + 1);
- if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
- iter->idx = idx;
- iter->cur = next;
- return cur + 1;
- }
- cur = next;
- if (idx == iter->max && iter->idx < iter->max) {
- idx = 0;
- max = iter->idx;
- cur = unsafe_yyjson_get_first(iter->obj);
- }
- }
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Structure (Implementation)
- *============================================================================*/
- /**
- Mutable JSON value, 24 bytes.
- The 'tag' and 'uni' field is same as immutable value.
- The 'next' field links all elements inside the container to be a cycle.
- */
- struct yyjson_mut_val {
- uint64_t tag; /**< type, subtype and length */
- yyjson_val_uni uni; /**< payload */
- yyjson_mut_val *next; /**< the next value in circular linked list */
- };
- /**
- A memory chunk in string memory pool.
- */
- typedef struct yyjson_str_chunk {
- struct yyjson_str_chunk *next; /* next chunk linked list */
- size_t chunk_size; /* chunk size in bytes */
- /* char str[]; flexible array member */
- } yyjson_str_chunk;
- /**
- A memory pool to hold all strings in a mutable document.
- */
- typedef struct yyjson_str_pool {
- char *cur; /* cursor inside current chunk */
- char *end; /* the end of current chunk */
- size_t chunk_size; /* chunk size in bytes while creating new chunk */
- size_t chunk_size_max; /* maximum chunk size in bytes */
- yyjson_str_chunk *chunks; /* a linked list of chunks, nullable */
- } yyjson_str_pool;
- /**
- A memory chunk in value memory pool.
- `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`.
- */
- typedef struct yyjson_val_chunk {
- struct yyjson_val_chunk *next; /* next chunk linked list */
- size_t chunk_size; /* chunk size in bytes */
- /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */
- /* yyjson_mut_val vals[]; flexible array member */
- } yyjson_val_chunk;
- /**
- A memory pool to hold all values in a mutable document.
- */
- typedef struct yyjson_val_pool {
- yyjson_mut_val *cur; /* cursor inside current chunk */
- yyjson_mut_val *end; /* the end of current chunk */
- size_t chunk_size; /* chunk size in bytes while creating new chunk */
- size_t chunk_size_max; /* maximum chunk size in bytes */
- yyjson_val_chunk *chunks; /* a linked list of chunks, nullable */
- } yyjson_val_pool;
- struct yyjson_mut_doc {
- yyjson_mut_val *root; /**< root value of the JSON document, nullable */
- yyjson_alc alc; /**< a valid allocator, nonnull */
- yyjson_str_pool str_pool; /**< string memory pool */
- yyjson_val_pool val_pool; /**< value memory pool */
- };
- /* Ensures the capacity to at least equal to the specified byte length. */
- yyjson_api bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool,
- const yyjson_alc *alc,
- size_t len);
- /* Ensures the capacity to at least equal to the specified value count. */
- yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool,
- const yyjson_alc *alc,
- size_t count);
- /* Allocate memory for string. */
- yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc,
- size_t len) {
- char *mem;
- const yyjson_alc *alc = &doc->alc;
- yyjson_str_pool *pool = &doc->str_pool;
- if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) {
- if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) {
- return NULL;
- }
- }
- mem = pool->cur;
- pool->cur = mem + len + 1;
- return mem;
- }
- yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc,
- const char *str, size_t len) {
- char *mem = unsafe_yyjson_mut_str_alc(doc, len);
- if (yyjson_unlikely(!mem)) return NULL;
- memcpy((void *)mem, (const void *)str, len);
- mem[len] = '\0';
- return mem;
- }
- yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc,
- size_t count) {
- yyjson_mut_val *val;
- yyjson_alc *alc = &doc->alc;
- yyjson_val_pool *pool = &doc->val_pool;
- if (yyjson_unlikely((size_t)(pool->end - pool->cur) < count)) {
- if (yyjson_unlikely(!unsafe_yyjson_val_pool_grow(pool, alc, count))) {
- return NULL;
- }
- }
- val = pool->cur;
- pool->cur += count;
- return val;
- }
- /*==============================================================================
- * Mutable JSON Document API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc) {
- return doc ? doc->root : NULL;
- }
- yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
- yyjson_mut_val *root) {
- if (doc) doc->root = root;
- }
- /*==============================================================================
- * Mutable JSON Value Type API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_raw(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_null(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_true(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_false(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_bool(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_uint(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_sint(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_int(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_real(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_num(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_str(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_arr(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_obj(val) : false;
- }
- yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val) {
- return val ? unsafe_yyjson_is_ctn(val) : false;
- }
- /*==============================================================================
- * Mutable JSON Value Content API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val) {
- return yyjson_get_type((yyjson_val *)val);
- }
- yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val) {
- return yyjson_get_subtype((yyjson_val *)val);
- }
- yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val) {
- return yyjson_get_tag((yyjson_val *)val);
- }
- yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val) {
- return yyjson_get_type_desc((yyjson_val *)val);
- }
- yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val) {
- return yyjson_get_raw((yyjson_val *)val);
- }
- yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val) {
- return yyjson_get_bool((yyjson_val *)val);
- }
- yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val) {
- return yyjson_get_uint((yyjson_val *)val);
- }
- yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val) {
- return yyjson_get_sint((yyjson_val *)val);
- }
- yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val) {
- return yyjson_get_int((yyjson_val *)val);
- }
- yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) {
- return yyjson_get_real((yyjson_val *)val);
- }
- yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) {
- return yyjson_get_num((yyjson_val *)val);
- }
- yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) {
- return yyjson_get_str((yyjson_val *)val);
- }
- yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val) {
- return yyjson_get_len((yyjson_val *)val);
- }
- yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
- const char *str) {
- return yyjson_equals_str((yyjson_val *)val, str);
- }
- yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
- const char *str, size_t len) {
- return yyjson_equals_strn((yyjson_val *)val, str, len);
- }
- yyjson_api bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs,
- yyjson_mut_val *rhs);
- yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
- yyjson_mut_val *rhs) {
- if (yyjson_unlikely(!lhs || !rhs)) return false;
- return unsafe_yyjson_mut_equals(lhs, rhs);
- }
- yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
- const char *raw, size_t len) {
- if (yyjson_unlikely(!val || !raw)) return false;
- unsafe_yyjson_set_raw(val, raw, len);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_null(val);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_bool(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_uint(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_sint(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_sint(val, (int64_t)num);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_real(val, num);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val,
- const char *str) {
- if (yyjson_unlikely(!val || !str)) return false;
- unsafe_yyjson_set_str(val, str);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
- const char *str, size_t len) {
- if (yyjson_unlikely(!val || !str)) return false;
- unsafe_yyjson_set_strn(val, str, len);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_arr(val, 0);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val) {
- if (yyjson_unlikely(!val)) return false;
- unsafe_yyjson_set_obj(val, 0);
- return true;
- }
- /*==============================================================================
- * Mutable JSON Value Creation API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
- const char *str) {
- if (yyjson_likely(str)) return yyjson_mut_rawn(doc, str, strlen(str));
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
- const char *str,
- size_t len) {
- if (yyjson_likely(doc && str)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
- val->uni.str = str;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
- const char *str) {
- if (yyjson_likely(str)) return yyjson_mut_rawncpy(doc, str, strlen(str));
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
- const char *str,
- size_t len) {
- if (yyjson_likely(doc && str)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
- if (yyjson_likely(val && new_str)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
- val->uni.str = new_str;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
- bool _val) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
- uint64_t num) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = num;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
- int64_t num) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = num;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
- int64_t num) {
- return yyjson_mut_sint(doc, num);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
- double num) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
- val->uni.f64 = num;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
- const char *str) {
- if (yyjson_likely(doc && str)) {
- size_t len = strlen(str);
- bool noesc = unsafe_yyjson_is_str_noesc(str, len);
- yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) |
- (uint64_t)(YYJSON_TYPE_STR | sub);
- val->uni.str = str;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
- const char *str,
- size_t len) {
- if (yyjson_likely(doc && str)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = str;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
- const char *str) {
- if (yyjson_likely(doc && str)) {
- size_t len = strlen(str);
- bool noesc = unsafe_yyjson_is_str_noesc(str, len);
- yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
- if (yyjson_likely(val && new_str)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) |
- (uint64_t)(YYJSON_TYPE_STR | sub);
- val->uni.str = new_str;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
- const char *str,
- size_t len) {
- if (yyjson_likely(doc && str)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
- if (yyjson_likely(val && new_str)) {
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = new_str;
- return val;
- }
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Array API (Implementation)
- *============================================================================*/
- yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr) {
- return yyjson_mut_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
- size_t idx) {
- if (yyjson_likely(idx < yyjson_mut_arr_size(arr))) {
- yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
- while (idx-- > 0) val = val->next;
- return val->next;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(
- yyjson_mut_val *arr) {
- if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
- return ((yyjson_mut_val *)arr->uni.ptr)->next;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(
- yyjson_mut_val *arr) {
- if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
- return ((yyjson_mut_val *)arr->uni.ptr);
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Array Iterator API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
- yyjson_mut_arr_iter *iter) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) {
- iter->idx = 0;
- iter->max = unsafe_yyjson_get_len(arr);
- iter->cur = iter->max ? (yyjson_mut_val *)arr->uni.ptr : NULL;
- iter->pre = NULL;
- iter->arr = arr;
- return true;
- }
- if (iter) memset(iter, 0, sizeof(yyjson_mut_arr_iter));
- return false;
- }
- yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
- yyjson_mut_val *arr) {
- yyjson_mut_arr_iter iter;
- yyjson_mut_arr_iter_init(arr, &iter);
- return iter;
- }
- yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) {
- return iter ? iter->idx < iter->max : false;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
- yyjson_mut_arr_iter *iter) {
- if (iter && iter->idx < iter->max) {
- yyjson_mut_val *val = iter->cur;
- iter->pre = val;
- iter->cur = val->next;
- iter->idx++;
- return iter->cur;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
- yyjson_mut_arr_iter *iter) {
- if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
- yyjson_mut_val *prev = iter->pre;
- yyjson_mut_val *cur = iter->cur;
- yyjson_mut_val *next = cur->next;
- if (yyjson_unlikely(iter->idx == iter->max)) iter->arr->uni.ptr = prev;
- iter->idx--;
- iter->max--;
- unsafe_yyjson_set_len(iter->arr, iter->max);
- prev->next = next;
- iter->cur = next;
- return cur;
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Array Creation API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE;
- return val;
- }
- }
- return NULL;
- }
- #define yyjson_mut_arr_with_func(func) \
- if (yyjson_likely(doc && ((0 < count && count < \
- (~(size_t)0) / sizeof(yyjson_mut_val) && vals) || count == 0))) { \
- yyjson_mut_val *arr = unsafe_yyjson_mut_val(doc, 1 + count); \
- if (yyjson_likely(arr)) { \
- arr->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; \
- if (count > 0) { \
- size_t i; \
- for (i = 0; i < count; i++) { \
- yyjson_mut_val *val = arr + i + 1; \
- func \
- val->next = val + 1; \
- } \
- arr[count].next = arr + 1; \
- arr->uni.ptr = arr + count; \
- } \
- return arr; \
- } \
- } \
- return NULL
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
- yyjson_mut_doc *doc, const bool *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3);
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
- yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
- return yyjson_mut_arr_with_sint64(doc, vals, count);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
- yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
- return yyjson_mut_arr_with_uint64(doc, vals, count);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
- yyjson_mut_doc *doc, const double *vals, size_t count) {
- return yyjson_mut_arr_with_double(doc, vals, count);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
- yyjson_mut_doc *doc, const int8_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = (int64_t)vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
- yyjson_mut_doc *doc, const int16_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
- yyjson_mut_doc *doc, const int32_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
- yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
- yyjson_mut_doc *doc, const uint8_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
- yyjson_mut_doc *doc, const uint16_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
- yyjson_mut_doc *doc, const uint32_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
- yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
- yyjson_mut_doc *doc, const float *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
- val->uni.f64 = (double)vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
- yyjson_mut_doc *doc, const double *vals, size_t count) {
- yyjson_mut_arr_with_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
- val->uni.f64 = vals[i];
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
- yyjson_mut_doc *doc, const char **vals, size_t count) {
- yyjson_mut_arr_with_func({
- uint64_t len = (uint64_t)strlen(vals[i]);
- val->tag = (len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = vals[i];
- if (yyjson_unlikely(!val->uni.str)) return NULL;
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
- yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
- if (yyjson_unlikely(count > 0 && !lens)) return NULL;
- yyjson_mut_arr_with_func({
- val->tag = ((uint64_t)lens[i] << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = vals[i];
- if (yyjson_unlikely(!val->uni.str)) return NULL;
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
- yyjson_mut_doc *doc, const char **vals, size_t count) {
- size_t len;
- const char *str;
- yyjson_mut_arr_with_func({
- str = vals[i];
- if (!str) return NULL;
- len = strlen(str);
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len);
- if (yyjson_unlikely(!val->uni.str)) return NULL;
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
- yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
- size_t len;
- const char *str;
- if (yyjson_unlikely(count > 0 && !lens)) return NULL;
- yyjson_mut_arr_with_func({
- str = vals[i];
- len = lens[i];
- val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len);
- if (yyjson_unlikely(!val->uni.str)) return NULL;
- });
- }
- #undef yyjson_mut_arr_with_func
- /*==============================================================================
- * Mutable JSON Array Modification API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
- yyjson_mut_val *val, size_t idx) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_likely(idx <= len)) {
- unsafe_yyjson_set_len(arr, len + 1);
- if (len == 0) {
- val->next = val;
- arr->uni.ptr = val;
- } else {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- if (idx == len) {
- prev->next = val;
- val->next = next;
- arr->uni.ptr = val;
- } else {
- while (idx-- > 0) {
- prev = next;
- next = next->next;
- }
- prev->next = val;
- val->next = next;
- }
- }
- return true;
- }
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
- yyjson_mut_val *val) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
- size_t len = unsafe_yyjson_get_len(arr);
- unsafe_yyjson_set_len(arr, len + 1);
- if (len == 0) {
- val->next = val;
- } else {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- prev->next = val;
- val->next = next;
- }
- arr->uni.ptr = val;
- return true;
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
- yyjson_mut_val *val) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
- size_t len = unsafe_yyjson_get_len(arr);
- unsafe_yyjson_set_len(arr, len + 1);
- if (len == 0) {
- val->next = val;
- arr->uni.ptr = val;
- } else {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- prev->next = val;
- val->next = next;
- }
- return true;
- }
- return false;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
- size_t idx,
- yyjson_mut_val *val) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_likely(idx < len)) {
- if (yyjson_likely(len > 1)) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- while (idx-- > 0) {
- prev = next;
- next = next->next;
- }
- prev->next = val;
- val->next = next->next;
- if ((void *)next == arr->uni.ptr) arr->uni.ptr = val;
- return next;
- } else {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- val->next = val;
- arr->uni.ptr = val;
- return prev;
- }
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
- size_t idx) {
- if (yyjson_likely(yyjson_mut_is_arr(arr))) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_likely(idx < len)) {
- unsafe_yyjson_set_len(arr, len - 1);
- if (yyjson_likely(len > 1)) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- while (idx-- > 0) {
- prev = next;
- next = next->next;
- }
- prev->next = next->next;
- if ((void *)next == arr->uni.ptr) arr->uni.ptr = prev;
- return next;
- } else {
- return ((yyjson_mut_val *)arr->uni.ptr);
- }
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
- yyjson_mut_val *arr) {
- if (yyjson_likely(yyjson_mut_is_arr(arr))) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (len > 1) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- prev->next = next->next;
- unsafe_yyjson_set_len(arr, len - 1);
- return next;
- } else if (len == 1) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- unsafe_yyjson_set_len(arr, 0);
- return prev;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
- yyjson_mut_val *arr) {
- if (yyjson_likely(yyjson_mut_is_arr(arr))) {
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_likely(len > 1)) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- yyjson_mut_val *next = prev->next;
- unsafe_yyjson_set_len(arr, len - 1);
- while (--len > 0) prev = prev->next;
- prev->next = next;
- next = (yyjson_mut_val *)arr->uni.ptr;
- arr->uni.ptr = prev;
- return next;
- } else if (len == 1) {
- yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
- unsafe_yyjson_set_len(arr, 0);
- return prev;
- }
- }
- return NULL;
- }
- yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
- size_t _idx, size_t _len) {
- if (yyjson_likely(yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *prev, *next;
- bool tail_removed;
- size_t len = unsafe_yyjson_get_len(arr);
- if (yyjson_unlikely(_idx + _len > len)) return false;
- if (yyjson_unlikely(_len == 0)) return true;
- unsafe_yyjson_set_len(arr, len - _len);
- if (yyjson_unlikely(len == _len)) return true;
- tail_removed = (_idx + _len == len);
- prev = ((yyjson_mut_val *)arr->uni.ptr);
- while (_idx-- > 0) prev = prev->next;
- next = prev->next;
- while (_len-- > 0) next = next->next;
- prev->next = next;
- if (yyjson_unlikely(tail_removed)) arr->uni.ptr = prev;
- return true;
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr) {
- if (yyjson_likely(yyjson_mut_is_arr(arr))) {
- unsafe_yyjson_set_len(arr, 0);
- return true;
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
- size_t idx) {
- if (yyjson_likely(yyjson_mut_is_arr(arr) &&
- unsafe_yyjson_get_len(arr) > idx)) {
- yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
- while (idx-- > 0) val = val->next;
- arr->uni.ptr = (void *)val;
- return true;
- }
- return false;
- }
- /*==============================================================================
- * Mutable JSON Array Modification Convenience API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
- yyjson_mut_val *val) {
- return yyjson_mut_arr_append(arr, val);
- }
- yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
- yyjson_mut_val *arr) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_null(doc);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
- yyjson_mut_val *arr) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_true(doc);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
- yyjson_mut_val *arr) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_false(doc);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- bool _val) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_bool(doc, _val);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- uint64_t num) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_uint(doc, num);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- int64_t num) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_sint(doc, num);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- int64_t num) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_sint(doc, num);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- double num) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_real(doc, num);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_str(doc, str);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str, size_t len) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_strn(doc, str, len);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_strcpy(doc, str);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
- yyjson_mut_val *arr,
- const char *str, size_t len) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_strncpy(doc, str, len);
- return yyjson_mut_arr_append(arr, val);
- }
- return false;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
- yyjson_mut_val *arr) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_arr(doc);
- return yyjson_mut_arr_append(arr, val) ? val : NULL;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
- yyjson_mut_val *arr) {
- if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
- yyjson_mut_val *val = yyjson_mut_obj(doc);
- return yyjson_mut_arr_append(arr, val) ? val : NULL;
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Object API (Implementation)
- *============================================================================*/
- yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj) {
- return yyjson_mut_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
- const char *key) {
- return yyjson_mut_obj_getn(obj, key, key ? strlen(key) : 0);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
- const char *_key,
- size_t key_len) {
- size_t len = yyjson_mut_obj_size(obj);
- if (yyjson_likely(len && _key)) {
- yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next;
- while (len-- > 0) {
- if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key->next;
- key = key->next->next;
- }
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Object Iterator API (Implementation)
- *============================================================================*/
- yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
- yyjson_mut_obj_iter *iter) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) {
- iter->idx = 0;
- iter->max = unsafe_yyjson_get_len(obj);
- iter->cur = iter->max ? (yyjson_mut_val *)obj->uni.ptr : NULL;
- iter->pre = NULL;
- iter->obj = obj;
- return true;
- }
- if (iter) memset(iter, 0, sizeof(yyjson_mut_obj_iter));
- return false;
- }
- yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
- yyjson_mut_val *obj) {
- yyjson_mut_obj_iter iter;
- yyjson_mut_obj_iter_init(obj, &iter);
- return iter;
- }
- yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) {
- return iter ? iter->idx < iter->max : false;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
- yyjson_mut_obj_iter *iter) {
- if (iter && iter->idx < iter->max) {
- yyjson_mut_val *key = iter->cur;
- iter->pre = key;
- iter->cur = key->next->next;
- iter->idx++;
- return iter->cur;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
- yyjson_mut_val *key) {
- return key ? key->next : NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
- yyjson_mut_obj_iter *iter) {
- if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
- yyjson_mut_val *prev = iter->pre;
- yyjson_mut_val *cur = iter->cur;
- yyjson_mut_val *next = cur->next->next;
- if (yyjson_unlikely(iter->idx == iter->max)) iter->obj->uni.ptr = prev;
- iter->idx--;
- iter->max--;
- unsafe_yyjson_set_len(iter->obj, iter->max);
- prev->next->next = next;
- iter->cur = prev;
- return cur->next;
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
- yyjson_mut_obj_iter *iter, const char *key) {
- return yyjson_mut_obj_iter_getn(iter, key, key ? strlen(key) : 0);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
- yyjson_mut_obj_iter *iter, const char *key, size_t key_len) {
- if (iter && key) {
- size_t idx = 0;
- size_t max = iter->max;
- yyjson_mut_val *pre, *cur = iter->cur;
- while (idx++ < max) {
- pre = cur;
- cur = cur->next->next;
- if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
- iter->idx += idx;
- if (iter->idx > max) iter->idx -= max + 1;
- iter->pre = pre;
- iter->cur = cur;
- return cur->next;
- }
- }
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Object Creation API (Implementation)
- *============================================================================*/
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc) {
- if (yyjson_likely(doc)) {
- yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
- if (yyjson_likely(val)) {
- val->tag = YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE;
- return val;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
- const char **keys,
- const char **vals,
- size_t count) {
- if (yyjson_likely(doc && ((count > 0 && keys && vals) || (count == 0)))) {
- yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
- if (yyjson_likely(obj)) {
- obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
- if (count > 0) {
- size_t i;
- for (i = 0; i < count; i++) {
- yyjson_mut_val *key = obj + (i * 2 + 1);
- yyjson_mut_val *val = obj + (i * 2 + 2);
- uint64_t key_len = (uint64_t)strlen(keys[i]);
- uint64_t val_len = (uint64_t)strlen(vals[i]);
- key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- key->uni.str = keys[i];
- val->uni.str = vals[i];
- key->next = val;
- val->next = val + 1;
- }
- obj[count * 2].next = obj + 1;
- obj->uni.ptr = obj + (count * 2 - 1);
- }
- return obj;
- }
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
- const char **pairs,
- size_t count) {
- if (yyjson_likely(doc && ((count > 0 && pairs) || (count == 0)))) {
- yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
- if (yyjson_likely(obj)) {
- obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
- if (count > 0) {
- size_t i;
- for (i = 0; i < count; i++) {
- yyjson_mut_val *key = obj + (i * 2 + 1);
- yyjson_mut_val *val = obj + (i * 2 + 2);
- const char *key_str = pairs[i * 2 + 0];
- const char *val_str = pairs[i * 2 + 1];
- uint64_t key_len = (uint64_t)strlen(key_str);
- uint64_t val_len = (uint64_t)strlen(val_str);
- key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- key->uni.str = key_str;
- val->uni.str = val_str;
- key->next = val;
- val->next = val + 1;
- }
- obj[count * 2].next = obj + 1;
- obj->uni.ptr = obj + (count * 2 - 1);
- }
- return obj;
- }
- }
- return NULL;
- }
- /*==============================================================================
- * Mutable JSON Object Modification API (Implementation)
- *============================================================================*/
- yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val,
- size_t len) {
- if (yyjson_likely(len)) {
- yyjson_mut_val *prev_val = ((yyjson_mut_val *)obj->uni.ptr)->next;
- yyjson_mut_val *next_key = prev_val->next;
- prev_val->next = key;
- val->next = next_key;
- } else {
- val->next = key;
- }
- key->next = val;
- obj->uni.ptr = (void *)key;
- unsafe_yyjson_set_len(obj, len + 1);
- }
- yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove(
- yyjson_mut_val *obj, const char *key, size_t key_len) {
- size_t obj_len = unsafe_yyjson_get_len(obj);
- if (obj_len) {
- yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
- yyjson_mut_val *cur_key = pre_key->next->next;
- yyjson_mut_val *removed_item = NULL;
- size_t i;
- for (i = 0; i < obj_len; i++) {
- if (unsafe_yyjson_equals_strn(cur_key, key, key_len)) {
- if (!removed_item) removed_item = cur_key->next;
- cur_key = cur_key->next->next;
- pre_key->next->next = cur_key;
- if (i + 1 == obj_len) obj->uni.ptr = pre_key;
- i--;
- obj_len--;
- } else {
- pre_key = cur_key;
- cur_key = cur_key->next->next;
- }
- }
- unsafe_yyjson_set_len(obj, obj_len);
- return removed_item;
- } else {
- return NULL;
- }
- }
- yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val) {
- size_t key_len = unsafe_yyjson_get_len(key);
- size_t obj_len = unsafe_yyjson_get_len(obj);
- if (obj_len) {
- yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
- yyjson_mut_val *cur_key = pre_key->next->next;
- size_t i;
- for (i = 0; i < obj_len; i++) {
- if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
- cur_key->next->tag = val->tag;
- cur_key->next->uni.u64 = val->uni.u64;
- return true;
- } else {
- cur_key = cur_key->next->next;
- }
- }
- }
- return false;
- }
- yyjson_api_inline void unsafe_yyjson_mut_obj_rotate(yyjson_mut_val *obj,
- size_t idx) {
- yyjson_mut_val *key = (yyjson_mut_val *)obj->uni.ptr;
- while (idx-- > 0) key = key->next->next;
- obj->uni.ptr = (void *)key;
- }
- yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) &&
- yyjson_mut_is_str(key) && val)) {
- unsafe_yyjson_mut_obj_add(obj, key, val, unsafe_yyjson_get_len(obj));
- return true;
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val) {
- bool replaced = false;
- size_t key_len;
- yyjson_mut_obj_iter iter;
- yyjson_mut_val *cur_key;
- if (yyjson_unlikely(!yyjson_mut_is_obj(obj) ||
- !yyjson_mut_is_str(key))) return false;
- key_len = unsafe_yyjson_get_len(key);
- yyjson_mut_obj_iter_init(obj, &iter);
- while ((cur_key = yyjson_mut_obj_iter_next(&iter)) != 0) {
- if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
- if (!replaced && val) {
- replaced = true;
- val->next = cur_key->next->next;
- cur_key->next = val;
- } else {
- yyjson_mut_obj_iter_remove(&iter);
- }
- }
- }
- if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max);
- return true;
- }
- yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val,
- size_t idx) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) &&
- yyjson_mut_is_str(key) && val)) {
- size_t len = unsafe_yyjson_get_len(obj);
- if (yyjson_likely(len >= idx)) {
- if (len > idx) {
- void *ptr = obj->uni.ptr;
- unsafe_yyjson_mut_obj_rotate(obj, idx);
- unsafe_yyjson_mut_obj_add(obj, key, val, len);
- obj->uni.ptr = ptr;
- } else {
- unsafe_yyjson_mut_obj_add(obj, key, val, len);
- }
- return true;
- }
- }
- return false;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
- yyjson_mut_val *key) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) {
- return unsafe_yyjson_mut_obj_remove(obj, key->uni.str,
- unsafe_yyjson_get_len(key));
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
- yyjson_mut_val *obj, const char *key) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
- size_t key_len = strlen(key);
- return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
- }
- return NULL;
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
- yyjson_mut_val *obj, const char *key, size_t key_len) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
- return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
- }
- return NULL;
- }
- yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj) {
- if (yyjson_likely(yyjson_mut_is_obj(obj))) {
- unsafe_yyjson_set_len(obj, 0);
- return true;
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
- yyjson_mut_val *key,
- yyjson_mut_val *val) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) &&
- yyjson_mut_is_str(key) && val)) {
- return unsafe_yyjson_mut_obj_replace(obj, key, val);
- }
- return false;
- }
- yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
- size_t idx) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) &&
- unsafe_yyjson_get_len(obj) > idx)) {
- unsafe_yyjson_mut_obj_rotate(obj, idx);
- return true;
- }
- return false;
- }
- /*==============================================================================
- * Mutable JSON Object Modification Convenience API (Implementation)
- *============================================================================*/
- #define yyjson_mut_obj_add_func(func) \
- if (yyjson_likely(doc && yyjson_mut_is_obj(obj) && _key)) { \
- yyjson_mut_val *key = unsafe_yyjson_mut_val(doc, 2); \
- if (yyjson_likely(key)) { \
- size_t len = unsafe_yyjson_get_len(obj); \
- yyjson_mut_val *val = key + 1; \
- size_t key_len = strlen(_key); \
- bool noesc = unsafe_yyjson_is_str_noesc(_key, key_len); \
- key->tag = YYJSON_TYPE_STR; \
- key->tag |= noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; \
- key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \
- key->uni.str = _key; \
- func \
- unsafe_yyjson_mut_obj_add(obj, key, val, len); \
- return true; \
- } \
- } \
- return false
- yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- bool _val) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3);
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- uint64_t _val) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
- val->uni.u64 = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- int64_t _val) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- int64_t _val) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
- val->uni.i64 = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- double _val) {
- yyjson_mut_obj_add_func({
- val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
- val->uni.f64 = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- const char *_val) {
- if (yyjson_unlikely(!_val)) return false;
- yyjson_mut_obj_add_func({
- size_t val_len = strlen(_val);
- bool val_noesc = unsafe_yyjson_is_str_noesc(_val, val_len);
- val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->tag |= val_noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
- val->uni.str = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- const char *_val,
- size_t _len) {
- if (yyjson_unlikely(!_val)) return false;
- yyjson_mut_obj_add_func({
- val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- val->uni.str = _val;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- const char *_val) {
- if (yyjson_unlikely(!_val)) return false;
- yyjson_mut_obj_add_func({
- size_t _len = strlen(_val);
- val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
- if (yyjson_unlikely(!val->uni.str)) return false;
- val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- const char *_val,
- size_t _len) {
- if (yyjson_unlikely(!_val)) return false;
- yyjson_mut_obj_add_func({
- val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
- if (yyjson_unlikely(!val->uni.str)) return false;
- val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
- });
- }
- yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *_key,
- yyjson_mut_val *_val) {
- if (yyjson_unlikely(!_val)) return false;
- yyjson_mut_obj_add_func({
- val = _val;
- });
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(yyjson_mut_val *obj,
- const char *key) {
- return yyjson_mut_obj_remove_strn(obj, key, key ? strlen(key) : 0);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
- yyjson_mut_val *obj, const char *_key, size_t _len) {
- if (yyjson_likely(yyjson_mut_is_obj(obj) && _key)) {
- yyjson_mut_val *key;
- yyjson_mut_obj_iter iter;
- yyjson_mut_val *val_removed = NULL;
- yyjson_mut_obj_iter_init(obj, &iter);
- while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) {
- if (unsafe_yyjson_equals_strn(key, _key, _len)) {
- if (!val_removed) val_removed = key->next;
- yyjson_mut_obj_iter_remove(&iter);
- }
- }
- return val_removed;
- }
- return NULL;
- }
- yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- const char *new_key) {
- if (!key || !new_key) return false;
- return yyjson_mut_obj_rename_keyn(doc, obj, key, strlen(key),
- new_key, strlen(new_key));
- }
- yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
- yyjson_mut_val *obj,
- const char *key,
- size_t len,
- const char *new_key,
- size_t new_len) {
- char *cpy_key = NULL;
- yyjson_mut_val *old_key;
- yyjson_mut_obj_iter iter;
- if (!doc || !obj || !key || !new_key) return false;
- yyjson_mut_obj_iter_init(obj, &iter);
- while ((old_key = yyjson_mut_obj_iter_next(&iter))) {
- if (unsafe_yyjson_equals_strn((void *)old_key, key, len)) {
- if (!cpy_key) {
- cpy_key = unsafe_yyjson_mut_strncpy(doc, new_key, new_len);
- if (!cpy_key) return false;
- }
- yyjson_mut_set_strn(old_key, cpy_key, new_len);
- }
- }
- return cpy_key != NULL;
- }
- /*==============================================================================
- * JSON Pointer API (Implementation)
- *============================================================================*/
- #define yyjson_ptr_set_err(_code, _msg) do { \
- if (err) { \
- err->code = YYJSON_PTR_ERR_##_code; \
- err->msg = _msg; \
- err->pos = 0; \
- } \
- } while(false)
- /* require: val != NULL, *ptr == '/', len > 0 */
- yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val,
- const char *ptr, size_t len,
- yyjson_ptr_err *err);
- /* require: val != NULL, *ptr == '/', len > 0 */
- yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */
- yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc,
- bool create_parent, bool insert_new,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- /* require: val/err != NULL, *ptr == '/', len > 0 */
- yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex(
- yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
- /* require: val/err != NULL, *ptr == '/', len > 0 */
- yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err);
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
- const char *ptr) {
- if (yyjson_unlikely(!ptr)) return NULL;
- return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
- const char *ptr, size_t len) {
- return yyjson_doc_ptr_getx(doc, ptr, len, NULL);
- }
- yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
- const char *ptr, size_t len,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (yyjson_unlikely(!doc || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- return doc->root;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err);
- }
- yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
- const char *ptr) {
- if (yyjson_unlikely(!ptr)) return NULL;
- return yyjson_ptr_getn(val, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
- const char *ptr, size_t len) {
- return yyjson_ptr_getx(val, ptr, len, NULL);
- }
- yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
- const char *ptr, size_t len,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (yyjson_unlikely(!val || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- return val;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_ptr_getx(val, ptr, len, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
- const char *ptr) {
- if (!ptr) return NULL;
- return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
- const char *ptr,
- size_t len) {
- return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!doc || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- return doc->root;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
- const char *ptr) {
- if (!ptr) return NULL;
- return yyjson_mut_ptr_getn(val, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
- const char *ptr,
- size_t len) {
- return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!val || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- return val;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
- const char *ptr,
- yyjson_mut_val *new_val) {
- if (yyjson_unlikely(!ptr)) return false;
- return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
- const char *ptr,
- size_t len,
- yyjson_mut_val *new_val) {
- return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!doc || !ptr || !new_val)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return false;
- }
- if (yyjson_unlikely(len == 0)) {
- if (doc->root) {
- yyjson_ptr_set_err(SET_ROOT, "cannot set document's root");
- return false;
- } else {
- doc->root = new_val;
- return true;
- }
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return false;
- }
- if (yyjson_unlikely(!doc->root && !create_parent)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return false;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_mut_val *root = yyjson_mut_obj(doc);
- if (yyjson_unlikely(!root)) {
- yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
- return false;
- }
- if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
- create_parent, true, ctx, err)) {
- doc->root = root;
- return true;
- }
- return false;
- }
- return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
- create_parent, true, ctx, err);
- }
- yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
- const char *ptr,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc) {
- if (yyjson_unlikely(!ptr)) return false;
- return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc);
- }
- yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc) {
- return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL);
- }
- yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return false;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_ptr_set_err(SET_ROOT, "cannot set root");
- return false;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return false;
- }
- return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val,
- doc, create_parent, true, ctx, err);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
- const char *ptr,
- yyjson_mut_val *new_val) {
- if (yyjson_unlikely(!ptr)) return false;
- return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val) {
- return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL);
- }
- yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!doc || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return false;
- }
- if (yyjson_unlikely(len == 0)) {
- if (ctx) ctx->old = doc->root;
- doc->root = new_val;
- return true;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return false;
- }
- if (!new_val) {
- if (!doc->root) {
- yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
- return false;
- }
- return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
- }
- if (yyjson_unlikely(!doc->root && !create_parent)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return false;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_mut_val *root = yyjson_mut_obj(doc);
- if (yyjson_unlikely(!root)) {
- yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
- return false;
- }
- if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
- create_parent, false, ctx, err)) {
- doc->root = root;
- return true;
- }
- return false;
- }
- return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
- create_parent, false, ctx, err);
- }
- yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
- const char *ptr,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc) {
- if (yyjson_unlikely(!ptr)) return false;
- return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc);
- }
- yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc) {
- return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL);
- }
- yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
- const char *ptr, size_t len,
- yyjson_mut_val *new_val,
- yyjson_mut_doc *doc,
- bool create_parent,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!val || !ptr || !doc)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return false;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_ptr_set_err(SET_ROOT, "cannot set root");
- return false;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return false;
- }
- if (!new_val) {
- return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
- }
- return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc,
- create_parent, false, ctx, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
- yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) {
- if (!ptr) return NULL;
- return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
- yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) {
- return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
- yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
-
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!doc || !ptr || !new_val)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_mut_val *root = doc->root;
- if (yyjson_unlikely(!root)) {
- yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
- return NULL;
- }
- if (ctx) ctx->old = root;
- doc->root = new_val;
- return root;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return NULL;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val,
- ctx, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
- yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) {
- if (!ptr) return NULL;
- return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
- yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) {
- return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
- yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
-
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!val || !ptr || !new_val)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_ptr_set_err(SET_ROOT, "cannot set root");
- return NULL;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
- yyjson_mut_doc *doc, const char *ptr) {
- if (!ptr) return NULL;
- return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
- yyjson_mut_doc *doc, const char *ptr, size_t len) {
- return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
- yyjson_mut_doc *doc, const char *ptr, size_t len,
- yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
-
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!doc || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(!doc->root)) {
- yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_mut_val *root = doc->root;
- if (ctx) ctx->old = root;
- doc->root = NULL;
- return root;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
- const char *ptr) {
- if (!ptr) return NULL;
- return yyjson_mut_ptr_removen(val, ptr, strlen(ptr));
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
- const char *ptr,
- size_t len) {
- return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL);
- }
- yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
- const char *ptr,
- size_t len,
- yyjson_ptr_ctx *ctx,
- yyjson_ptr_err *err) {
- yyjson_ptr_set_err(NONE, NULL);
- if (ctx) memset(ctx, 0, sizeof(*ctx));
-
- if (yyjson_unlikely(!val || !ptr)) {
- yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
- return NULL;
- }
- if (yyjson_unlikely(len == 0)) {
- yyjson_ptr_set_err(SET_ROOT, "cannot set root");
- return NULL;
- }
- if (yyjson_unlikely(*ptr != '/')) {
- yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
- return NULL;
- }
- return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
- }
- yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
- yyjson_mut_val *key,
- yyjson_mut_val *val) {
- yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
- if (!ctx || !ctx->ctn || !val) return false;
- ctn = ctx->ctn;
-
- if (yyjson_mut_is_obj(ctn)) {
- if (!key) return false;
- key->next = val;
- pre_key = ctx->pre;
- if (unsafe_yyjson_get_len(ctn) == 0) {
- val->next = key;
- ctn->uni.ptr = key;
- ctx->pre = key;
- } else if (!pre_key) {
- pre_key = (yyjson_mut_val *)ctn->uni.ptr;
- pre_val = pre_key->next;
- val->next = pre_val->next;
- pre_val->next = key;
- ctn->uni.ptr = key;
- ctx->pre = pre_key;
- } else {
- cur_key = pre_key->next->next;
- cur_val = cur_key->next;
- val->next = cur_val->next;
- cur_val->next = key;
- if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key;
- ctx->pre = cur_key;
- }
- } else {
- pre_val = ctx->pre;
- if (unsafe_yyjson_get_len(ctn) == 0) {
- val->next = val;
- ctn->uni.ptr = val;
- ctx->pre = val;
- } else if (!pre_val) {
- pre_val = (yyjson_mut_val *)ctn->uni.ptr;
- val->next = pre_val->next;
- pre_val->next = val;
- ctn->uni.ptr = val;
- ctx->pre = pre_val;
- } else {
- cur_val = pre_val->next;
- val->next = cur_val->next;
- cur_val->next = val;
- if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
- ctx->pre = cur_val;
- }
- }
- unsafe_yyjson_inc_len(ctn);
- return true;
- }
- yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
- yyjson_mut_val *val) {
- yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val;
- if (!ctx || !ctx->ctn || !ctx->pre || !val) return false;
- ctn = ctx->ctn;
- if (yyjson_mut_is_obj(ctn)) {
- pre_key = ctx->pre;
- pre_val = pre_key->next;
- cur_key = pre_val->next;
- cur_val = cur_key->next;
- /* replace current value */
- cur_key->next = val;
- val->next = cur_val->next;
- ctx->old = cur_val;
- } else {
- pre_val = ctx->pre;
- cur_val = pre_val->next;
- /* replace current value */
- if (pre_val != cur_val) {
- val->next = cur_val->next;
- pre_val->next = val;
- if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
- } else {
- val->next = val;
- ctn->uni.ptr = val;
- ctx->pre = val;
- }
- ctx->old = cur_val;
- }
- return true;
- }
- yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) {
- yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
- size_t len;
- if (!ctx || !ctx->ctn || !ctx->pre) return false;
- ctn = ctx->ctn;
- if (yyjson_mut_is_obj(ctn)) {
- pre_key = ctx->pre;
- pre_val = pre_key->next;
- cur_key = pre_val->next;
- cur_val = cur_key->next;
- /* remove current key-value */
- pre_val->next = cur_val->next;
- if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key;
- ctx->pre = NULL;
- ctx->old = cur_val;
- } else {
- pre_val = ctx->pre;
- cur_val = pre_val->next;
- /* remove current key-value */
- pre_val->next = cur_val->next;
- if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val;
- ctx->pre = NULL;
- ctx->old = cur_val;
- }
- len = unsafe_yyjson_get_len(ctn) - 1;
- if (len == 0) ctn->uni.ptr = NULL;
- unsafe_yyjson_set_len(ctn, len);
- return true;
- }
- #undef yyjson_ptr_set_err
- /*==============================================================================
- * JSON Value at Pointer API (Implementation)
- *============================================================================*/
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_bool(
- yyjson_val *root, const char *ptr, bool *value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_bool(val)) {
- *value = unsafe_yyjson_get_bool(val);
- return true;
- } else {
- return false;
- }
- }
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_uint(
- yyjson_val *root, const char *ptr, uint64_t *value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_uint(val)) {
- *value = unsafe_yyjson_get_uint(val);
- return true;
- } else {
- return false;
- }
- }
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_sint(
- yyjson_val *root, const char *ptr, int64_t *value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_sint(val)) {
- *value = unsafe_yyjson_get_sint(val);
- return true;
- } else {
- return false;
- }
- }
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_real(
- yyjson_val *root, const char *ptr, double *value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_real(val)) {
- *value = unsafe_yyjson_get_real(val);
- return true;
- } else {
- return false;
- }
- }
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint,
- uint or real.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_num(
- yyjson_val *root, const char *ptr, double *value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_num(val)) {
- *value = unsafe_yyjson_get_num(val);
- return true;
- } else {
- return false;
- }
- }
- /**
- Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string.
- Returns true if value at `ptr` exists and is the correct type, otherwise false.
- */
- yyjson_api_inline bool yyjson_ptr_get_str(
- yyjson_val *root, const char *ptr, const char **value) {
- yyjson_val *val = yyjson_ptr_get(root, ptr);
- if (value && yyjson_is_str(val)) {
- *value = unsafe_yyjson_get_str(val);
- return true;
- } else {
- return false;
- }
- }
- /*==============================================================================
- * Deprecated
- *============================================================================*/
- /** @deprecated renamed to `yyjson_doc_ptr_get` */
- yyjson_deprecated("renamed to yyjson_doc_ptr_get")
- yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc,
- const char *ptr) {
- return yyjson_doc_ptr_get(doc, ptr);
- }
- /** @deprecated renamed to `yyjson_doc_ptr_getn` */
- yyjson_deprecated("renamed to yyjson_doc_ptr_getn")
- yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc,
- const char *ptr,
- size_t len) {
- return yyjson_doc_ptr_getn(doc, ptr, len);
- }
- /** @deprecated renamed to `yyjson_mut_doc_ptr_get` */
- yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get")
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer(
- yyjson_mut_doc *doc, const char *ptr) {
- return yyjson_mut_doc_ptr_get(doc, ptr);
- }
- /** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */
- yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn")
- yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern(
- yyjson_mut_doc *doc, const char *ptr, size_t len) {
- return yyjson_mut_doc_ptr_getn(doc, ptr, len);
- }
- /** @deprecated renamed to `yyjson_ptr_get` */
- yyjson_deprecated("renamed to yyjson_ptr_get")
- yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val,
- const char *ptr) {
- return yyjson_ptr_get(val, ptr);
- }
- /** @deprecated renamed to `yyjson_ptr_getn` */
- yyjson_deprecated("renamed to yyjson_ptr_getn")
- yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val,
- const char *ptr,
- size_t len) {
- return yyjson_ptr_getn(val, ptr, len);
- }
- /** @deprecated renamed to `yyjson_mut_ptr_get` */
- yyjson_deprecated("renamed to yyjson_mut_ptr_get")
- yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val,
- const char *ptr) {
- return yyjson_mut_ptr_get(val, ptr);
- }
- /** @deprecated renamed to `yyjson_mut_ptr_getn` */
- yyjson_deprecated("renamed to yyjson_mut_ptr_getn")
- yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val,
- const char *ptr,
- size_t len) {
- return yyjson_mut_ptr_getn(val, ptr, len);
- }
- /** @deprecated renamed to `yyjson_mut_ptr_getn` */
- yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn")
- yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val,
- const char *ptr,
- size_t len) {
- yyjson_ptr_err err;
- return unsafe_yyjson_ptr_getx(val, ptr, len, &err);
- }
- /** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */
- yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx")
- yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer(
- yyjson_mut_val *val, const char *ptr, size_t len) {
- yyjson_ptr_err err;
- return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err);
- }
- /*==============================================================================
- * Compiler Hint End
- *============================================================================*/
- #if defined(__clang__)
- # pragma clang diagnostic pop
- #elif defined(__GNUC__)
- # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
- # pragma GCC diagnostic pop
- # endif
- #elif defined(_MSC_VER)
- # pragma warning(pop)
- #endif /* warning suppress end */
- #ifdef __cplusplus
- }
- #endif /* extern "C" end */
- #endif /* YYJSON_H */
|