12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258 |
- // __ _____ _____ _____
- // __| | __| | | | JSON for Modern C++
- // | | |__ | | | | | | version 3.11.3
- // |_____|_____|_____|_|___| https://github.com/nlohmann/json
- //
- // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
- // SPDX-License-Identifier: MIT
- /****************************************************************************\
- * Note on documentation: The source files contain links to the online *
- * documentation of the public API at https://json.nlohmann.me. This URL *
- * contains the most recent documentation and should also be applicable to *
- * previous versions; documentation for deprecated functions is not *
- * removed, but marked deprecated. See "Generate documentation" section in *
- * file docs/README.md. *
- \****************************************************************************/
- #ifndef INCLUDE_NLOHMANN_JSON_HPP_
- #define INCLUDE_NLOHMANN_JSON_HPP_
- #include <algorithm> // all_of, find, for_each
- #include <cstddef> // nullptr_t, ptrdiff_t, size_t
- #include <functional> // hash, less
- #include <initializer_list> // initializer_list
- #ifndef JSON_NO_IO
- #include <iosfwd> // istream, ostream
- #endif // JSON_NO_IO
- #include <iterator> // random_access_iterator_tag
- #include <memory> // unique_ptr
- #include <string> // string, stoi, to_string
- #include <utility> // declval, forward, move, pair, swap
- #include <vector> // vector
- #include <nlohmann/adl_serializer.hpp>
- #include <nlohmann/byte_container_with_subtype.hpp>
- #include <nlohmann/detail/conversions/from_json.hpp>
- #include <nlohmann/detail/conversions/to_json.hpp>
- #include <nlohmann/detail/exceptions.hpp>
- #include <nlohmann/detail/hash.hpp>
- #include <nlohmann/detail/input/binary_reader.hpp>
- #include <nlohmann/detail/input/input_adapters.hpp>
- #include <nlohmann/detail/input/lexer.hpp>
- #include <nlohmann/detail/input/parser.hpp>
- #include <nlohmann/detail/iterators/internal_iterator.hpp>
- #include <nlohmann/detail/iterators/iter_impl.hpp>
- #include <nlohmann/detail/iterators/iteration_proxy.hpp>
- #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
- #include <nlohmann/detail/iterators/primitive_iterator.hpp>
- #include <nlohmann/detail/json_custom_base_class.hpp>
- #include <nlohmann/detail/json_pointer.hpp>
- #include <nlohmann/detail/json_ref.hpp>
- #include <nlohmann/detail/macro_scope.hpp>
- #include <nlohmann/detail/string_concat.hpp>
- #include <nlohmann/detail/string_escape.hpp>
- #include <nlohmann/detail/meta/cpp_future.hpp>
- #include <nlohmann/detail/meta/type_traits.hpp>
- #include <nlohmann/detail/output/binary_writer.hpp>
- #include <nlohmann/detail/output/output_adapters.hpp>
- #include <nlohmann/detail/output/serializer.hpp>
- #include <nlohmann/detail/value_t.hpp>
- #include <nlohmann/json_fwd.hpp>
- #include <nlohmann/ordered_map.hpp>
- #if defined(JSON_HAS_CPP_17)
- #if JSON_HAS_STATIC_RTTI
- #include <any>
- #endif
- #include <string_view>
- #endif
- /*!
- @brief namespace for Niels Lohmann
- @see https://github.com/nlohmann
- @since version 1.0.0
- */
- NLOHMANN_JSON_NAMESPACE_BEGIN
- /*!
- @brief a class to store JSON values
- @internal
- @invariant The member variables @a m_value and @a m_type have the following
- relationship:
- - If `m_type == value_t::object`, then `m_value.object != nullptr`.
- - If `m_type == value_t::array`, then `m_value.array != nullptr`.
- - If `m_type == value_t::string`, then `m_value.string != nullptr`.
- The invariants are checked by member function assert_invariant().
- @note ObjectType trick from https://stackoverflow.com/a/9860911
- @endinternal
- @since version 1.0.0
- @nosubgrouping
- */
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
- : public ::nlohmann::detail::json_base_class<CustomBaseClass>
- {
- private:
- template<detail::value_t> friend struct detail::external_constructor;
- template<typename>
- friend class ::nlohmann::json_pointer;
- // can be restored when json_pointer backwards compatibility is removed
- // friend ::nlohmann::json_pointer<StringType>;
- template<typename BasicJsonType, typename InputType>
- friend class ::nlohmann::detail::parser;
- friend ::nlohmann::detail::serializer<basic_json>;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::iter_impl;
- template<typename BasicJsonType, typename CharType>
- friend class ::nlohmann::detail::binary_writer;
- template<typename BasicJsonType, typename InputType, typename SAX>
- friend class ::nlohmann::detail::binary_reader;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::json_sax_dom_parser;
- template<typename BasicJsonType>
- friend class ::nlohmann::detail::json_sax_dom_callback_parser;
- friend class ::nlohmann::detail::exception;
- /// workaround type for MSVC
- using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
- using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
- JSON_PRIVATE_UNLESS_TESTED:
- // convenience aliases for types residing in namespace detail;
- using lexer = ::nlohmann::detail::lexer_base<basic_json>;
- template<typename InputAdapterType>
- static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
- InputAdapterType adapter,
- detail::parser_callback_t<basic_json>cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false
- )
- {
- return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
- std::move(cb), allow_exceptions, ignore_comments);
- }
- private:
- using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
- template<typename BasicJsonType>
- using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
- template<typename BasicJsonType>
- using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
- template<typename Iterator>
- using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
- template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
- template<typename CharType>
- using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
- template<typename InputType>
- using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
- template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
- JSON_PRIVATE_UNLESS_TESTED:
- using serializer = ::nlohmann::detail::serializer<basic_json>;
- public:
- using value_t = detail::value_t;
- /// JSON Pointer, see @ref nlohmann::json_pointer
- using json_pointer = ::nlohmann::json_pointer<StringType>;
- template<typename T, typename SFINAE>
- using json_serializer = JSONSerializer<T, SFINAE>;
- /// how to treat decoding errors
- using error_handler_t = detail::error_handler_t;
- /// how to treat CBOR tags
- using cbor_tag_handler_t = detail::cbor_tag_handler_t;
- /// helper type for initializer lists of basic_json values
- using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
- using input_format_t = detail::input_format_t;
- /// SAX interface type, see @ref nlohmann::json_sax
- using json_sax_t = json_sax<basic_json>;
- ////////////////
- // exceptions //
- ////////////////
- /// @name exceptions
- /// Classes to implement user-defined exceptions.
- /// @{
- using exception = detail::exception;
- using parse_error = detail::parse_error;
- using invalid_iterator = detail::invalid_iterator;
- using type_error = detail::type_error;
- using out_of_range = detail::out_of_range;
- using other_error = detail::other_error;
- /// @}
- /////////////////////
- // container types //
- /////////////////////
- /// @name container types
- /// The canonic container types to use @ref basic_json like any other STL
- /// container.
- /// @{
- /// the type of elements in a basic_json container
- using value_type = basic_json;
- /// the type of an element reference
- using reference = value_type&;
- /// the type of an element const reference
- using const_reference = const value_type&;
- /// a type to represent differences between iterators
- using difference_type = std::ptrdiff_t;
- /// a type to represent container sizes
- using size_type = std::size_t;
- /// the allocator type
- using allocator_type = AllocatorType<basic_json>;
- /// the type of an element pointer
- using pointer = typename std::allocator_traits<allocator_type>::pointer;
- /// the type of an element const pointer
- using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
- /// an iterator for a basic_json container
- using iterator = iter_impl<basic_json>;
- /// a const iterator for a basic_json container
- using const_iterator = iter_impl<const basic_json>;
- /// a reverse iterator for a basic_json container
- using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
- /// a const reverse iterator for a basic_json container
- using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
- /// @}
- /// @brief returns the allocator associated with the container
- /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
- static allocator_type get_allocator()
- {
- return allocator_type();
- }
- /// @brief returns version information on the library
- /// @sa https://json.nlohmann.me/api/basic_json/meta/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json meta()
- {
- basic_json result;
- result["copyright"] = "(C) 2013-2023 Niels Lohmann";
- result["name"] = "JSON for Modern C++";
- result["url"] = "https://github.com/nlohmann/json";
- result["version"]["string"] =
- detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
- std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
- std::to_string(NLOHMANN_JSON_VERSION_PATCH));
- result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
- result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
- result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
- #ifdef _WIN32
- result["platform"] = "win32";
- #elif defined __linux__
- result["platform"] = "linux";
- #elif defined __APPLE__
- result["platform"] = "apple";
- #elif defined __unix__
- result["platform"] = "unix";
- #else
- result["platform"] = "unknown";
- #endif
- #if defined(__ICC) || defined(__INTEL_COMPILER)
- result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
- #elif defined(__clang__)
- result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
- #elif defined(__GNUC__) || defined(__GNUG__)
- result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
- std::to_string(__GNUC__), '.',
- std::to_string(__GNUC_MINOR__), '.',
- std::to_string(__GNUC_PATCHLEVEL__))
- }
- };
- #elif defined(__HP_cc) || defined(__HP_aCC)
- result["compiler"] = "hp"
- #elif defined(__IBMCPP__)
- result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
- #elif defined(_MSC_VER)
- result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
- #elif defined(__PGI)
- result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
- #elif defined(__SUNPRO_CC)
- result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
- #else
- result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
- #endif
- #if defined(_MSVC_LANG)
- result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
- #elif defined(__cplusplus)
- result["compiler"]["c++"] = std::to_string(__cplusplus);
- #else
- result["compiler"]["c++"] = "unknown";
- #endif
- return result;
- }
- ///////////////////////////
- // JSON value data types //
- ///////////////////////////
- /// @name JSON value data types
- /// The data types to store a JSON value. These types are derived from
- /// the template arguments passed to class @ref basic_json.
- /// @{
- /// @brief default object key comparator type
- /// The actual object key comparator type (@ref object_comparator_t) may be
- /// different.
- /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
- #if defined(JSON_HAS_CPP_14)
- // use of transparent comparator avoids unnecessary repeated construction of temporaries
- // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
- using default_object_comparator_t = std::less<>;
- #else
- using default_object_comparator_t = std::less<StringType>;
- #endif
- /// @brief a type for an object
- /// @sa https://json.nlohmann.me/api/basic_json/object_t/
- using object_t = ObjectType<StringType,
- basic_json,
- default_object_comparator_t,
- AllocatorType<std::pair<const StringType,
- basic_json>>>;
- /// @brief a type for an array
- /// @sa https://json.nlohmann.me/api/basic_json/array_t/
- using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
- /// @brief a type for a string
- /// @sa https://json.nlohmann.me/api/basic_json/string_t/
- using string_t = StringType;
- /// @brief a type for a boolean
- /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
- using boolean_t = BooleanType;
- /// @brief a type for a number (integer)
- /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
- using number_integer_t = NumberIntegerType;
- /// @brief a type for a number (unsigned)
- /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
- using number_unsigned_t = NumberUnsignedType;
- /// @brief a type for a number (floating-point)
- /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
- using number_float_t = NumberFloatType;
- /// @brief a type for a packed binary type
- /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
- using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
- /// @brief object key comparator type
- /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
- using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
- /// @}
- private:
- /// helper for exception-safe object creation
- template<typename T, typename... Args>
- JSON_HEDLEY_RETURNS_NON_NULL
- static T* create(Args&& ... args)
- {
- AllocatorType<T> alloc;
- using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
- auto deleter = [&](T * obj)
- {
- AllocatorTraits::deallocate(alloc, obj, 1);
- };
- std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
- AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
- JSON_ASSERT(obj != nullptr);
- return obj.release();
- }
- ////////////////////////
- // JSON value storage //
- ////////////////////////
- JSON_PRIVATE_UNLESS_TESTED:
- /*!
- @brief a JSON value
- The actual storage for a JSON value of the @ref basic_json class. This
- union combines the different storage types for the JSON value types
- defined in @ref value_t.
- JSON type | value_t type | used type
- --------- | --------------- | ------------------------
- object | object | pointer to @ref object_t
- array | array | pointer to @ref array_t
- string | string | pointer to @ref string_t
- boolean | boolean | @ref boolean_t
- number | number_integer | @ref number_integer_t
- number | number_unsigned | @ref number_unsigned_t
- number | number_float | @ref number_float_t
- binary | binary | pointer to @ref binary_t
- null | null | *no value is stored*
- @note Variable-length types (objects, arrays, and strings) are stored as
- pointers. The size of the union should not exceed 64 bits if the default
- value types are used.
- @since version 1.0.0
- */
- union json_value
- {
- /// object (stored with pointer to save storage)
- object_t* object;
- /// array (stored with pointer to save storage)
- array_t* array;
- /// string (stored with pointer to save storage)
- string_t* string;
- /// binary (stored with pointer to save storage)
- binary_t* binary;
- /// boolean
- boolean_t boolean;
- /// number (integer)
- number_integer_t number_integer;
- /// number (unsigned integer)
- number_unsigned_t number_unsigned;
- /// number (floating-point)
- number_float_t number_float;
- /// default constructor (for null values)
- json_value() = default;
- /// constructor for booleans
- json_value(boolean_t v) noexcept : boolean(v) {}
- /// constructor for numbers (integer)
- json_value(number_integer_t v) noexcept : number_integer(v) {}
- /// constructor for numbers (unsigned)
- json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
- /// constructor for numbers (floating-point)
- json_value(number_float_t v) noexcept : number_float(v) {}
- /// constructor for empty values of a given type
- json_value(value_t t)
- {
- switch (t)
- {
- case value_t::object:
- {
- object = create<object_t>();
- break;
- }
- case value_t::array:
- {
- array = create<array_t>();
- break;
- }
- case value_t::string:
- {
- string = create<string_t>("");
- break;
- }
- case value_t::binary:
- {
- binary = create<binary_t>();
- break;
- }
- case value_t::boolean:
- {
- boolean = static_cast<boolean_t>(false);
- break;
- }
- case value_t::number_integer:
- {
- number_integer = static_cast<number_integer_t>(0);
- break;
- }
- case value_t::number_unsigned:
- {
- number_unsigned = static_cast<number_unsigned_t>(0);
- break;
- }
- case value_t::number_float:
- {
- number_float = static_cast<number_float_t>(0.0);
- break;
- }
- case value_t::null:
- {
- object = nullptr; // silence warning, see #821
- break;
- }
- case value_t::discarded:
- default:
- {
- object = nullptr; // silence warning, see #821
- if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
- {
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
- }
- break;
- }
- }
- }
- /// constructor for strings
- json_value(const string_t& value) : string(create<string_t>(value)) {}
- /// constructor for rvalue strings
- json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
- /// constructor for objects
- json_value(const object_t& value) : object(create<object_t>(value)) {}
- /// constructor for rvalue objects
- json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
- /// constructor for arrays
- json_value(const array_t& value) : array(create<array_t>(value)) {}
- /// constructor for rvalue arrays
- json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
- /// constructor for binary arrays
- json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
- /// constructor for rvalue binary arrays
- json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
- /// constructor for binary arrays (internal type)
- json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
- /// constructor for rvalue binary arrays (internal type)
- json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
- void destroy(value_t t)
- {
- if (
- (t == value_t::object && object == nullptr) ||
- (t == value_t::array && array == nullptr) ||
- (t == value_t::string && string == nullptr) ||
- (t == value_t::binary && binary == nullptr)
- )
- {
- //not initialized (e.g. due to exception in the ctor)
- return;
- }
- if (t == value_t::array || t == value_t::object)
- {
- // flatten the current json_value to a heap-allocated stack
- std::vector<basic_json> stack;
- // move the top-level items to stack
- if (t == value_t::array)
- {
- stack.reserve(array->size());
- std::move(array->begin(), array->end(), std::back_inserter(stack));
- }
- else
- {
- stack.reserve(object->size());
- for (auto&& it : *object)
- {
- stack.push_back(std::move(it.second));
- }
- }
- while (!stack.empty())
- {
- // move the last item to local variable to be processed
- basic_json current_item(std::move(stack.back()));
- stack.pop_back();
- // if current_item is array/object, move
- // its children to the stack to be processed later
- if (current_item.is_array())
- {
- std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
- current_item.m_data.m_value.array->clear();
- }
- else if (current_item.is_object())
- {
- for (auto&& it : *current_item.m_data.m_value.object)
- {
- stack.push_back(std::move(it.second));
- }
- current_item.m_data.m_value.object->clear();
- }
- // it's now safe that current_item get destructed
- // since it doesn't have any children
- }
- }
- switch (t)
- {
- case value_t::object:
- {
- AllocatorType<object_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
- break;
- }
- case value_t::array:
- {
- AllocatorType<array_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
- break;
- }
- case value_t::string:
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
- break;
- }
- case value_t::binary:
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
- break;
- }
- case value_t::null:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::discarded:
- default:
- {
- break;
- }
- }
- }
- };
- private:
- /*!
- @brief checks the class invariants
- This function asserts the class invariants. It needs to be called at the
- end of every constructor to make sure that created objects respect the
- invariant. Furthermore, it has to be called each time the type of a JSON
- value is changed, because the invariant expresses a relationship between
- @a m_type and @a m_value.
- Furthermore, the parent relation is checked for arrays and objects: If
- @a check_parents true and the value is an array or object, then the
- container's elements must have the current value as parent.
- @param[in] check_parents whether the parent relation should be checked.
- The value is true by default and should only be set to false
- during destruction of objects when the invariant does not
- need to hold.
- */
- void assert_invariant(bool check_parents = true) const noexcept
- {
- JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
- JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
- JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
- JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
- #if JSON_DIAGNOSTICS
- JSON_TRY
- {
- // cppcheck-suppress assertWithSideEffect
- JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
- {
- return j.m_parent == this;
- }));
- }
- JSON_CATCH(...) {} // LCOV_EXCL_LINE
- #endif
- static_cast<void>(check_parents);
- }
- void set_parents()
- {
- #if JSON_DIAGNOSTICS
- switch (m_data.m_type)
- {
- case value_t::array:
- {
- for (auto& element : *m_data.m_value.array)
- {
- element.m_parent = this;
- }
- break;
- }
- case value_t::object:
- {
- for (auto& element : *m_data.m_value.object)
- {
- element.second.m_parent = this;
- }
- break;
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- break;
- }
- #endif
- }
- iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
- {
- #if JSON_DIAGNOSTICS
- for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
- {
- (it + i)->m_parent = this;
- }
- #else
- static_cast<void>(count_set_parents);
- #endif
- return it;
- }
- reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
- {
- #if JSON_DIAGNOSTICS
- if (old_capacity != static_cast<std::size_t>(-1))
- {
- // see https://github.com/nlohmann/json/issues/2838
- JSON_ASSERT(type() == value_t::array);
- if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
- {
- // capacity has changed: update all parents
- set_parents();
- return j;
- }
- }
- // ordered_json uses a vector internally, so pointers could have
- // been invalidated; see https://github.com/nlohmann/json/issues/2962
- #ifdef JSON_HEDLEY_MSVC_VERSION
- #pragma warning(push )
- #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
- #endif
- if (detail::is_ordered_map<object_t>::value)
- {
- set_parents();
- return j;
- }
- #ifdef JSON_HEDLEY_MSVC_VERSION
- #pragma warning( pop )
- #endif
- j.m_parent = this;
- #else
- static_cast<void>(j);
- static_cast<void>(old_capacity);
- #endif
- return j;
- }
- public:
- //////////////////////////
- // JSON parser callback //
- //////////////////////////
- /// @brief parser event types
- /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
- using parse_event_t = detail::parse_event_t;
- /// @brief per-element parser callback type
- /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
- using parser_callback_t = detail::parser_callback_t<basic_json>;
- //////////////////
- // constructors //
- //////////////////
- /// @name constructors and destructors
- /// Constructors of class @ref basic_json, copy/move constructor, copy
- /// assignment, static functions creating objects, and the destructor.
- /// @{
- /// @brief create an empty value with a given type
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(const value_t v)
- : m_data(v)
- {
- assert_invariant();
- }
- /// @brief create a null object
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
- : basic_json(value_t::null)
- {
- assert_invariant();
- }
- /// @brief create a JSON value from compatible types
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < typename CompatibleType,
- typename U = detail::uncvref_t<CompatibleType>,
- detail::enable_if_t <
- !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
- basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
- JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
- std::forward<CompatibleType>(val))))
- {
- JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
- set_parents();
- assert_invariant();
- }
- /// @brief create a JSON value from an existing one
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < typename BasicJsonType,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
- basic_json(const BasicJsonType& val)
- {
- using other_boolean_t = typename BasicJsonType::boolean_t;
- using other_number_float_t = typename BasicJsonType::number_float_t;
- using other_number_integer_t = typename BasicJsonType::number_integer_t;
- using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
- using other_string_t = typename BasicJsonType::string_t;
- using other_object_t = typename BasicJsonType::object_t;
- using other_array_t = typename BasicJsonType::array_t;
- using other_binary_t = typename BasicJsonType::binary_t;
- switch (val.type())
- {
- case value_t::boolean:
- JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
- break;
- case value_t::number_float:
- JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
- break;
- case value_t::number_integer:
- JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
- break;
- case value_t::number_unsigned:
- JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
- break;
- case value_t::string:
- JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
- break;
- case value_t::object:
- JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
- break;
- case value_t::array:
- JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
- break;
- case value_t::binary:
- JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
- break;
- case value_t::null:
- *this = nullptr;
- break;
- case value_t::discarded:
- m_data.m_type = value_t::discarded;
- break;
- default: // LCOV_EXCL_LINE
- JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
- }
- JSON_ASSERT(m_data.m_type == val.type());
- set_parents();
- assert_invariant();
- }
- /// @brief create a container (array or object) from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(initializer_list_t init,
- bool type_deduction = true,
- value_t manual_type = value_t::array)
- {
- // check if each element is an array with two elements whose first
- // element is a string
- bool is_an_object = std::all_of(init.begin(), init.end(),
- [](const detail::json_ref<basic_json>& element_ref)
- {
- // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
- // (many string types can be constructed from 0 via its null-pointer guise, so we get a
- // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
- return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
- });
- // adjust type if type deduction is not wanted
- if (!type_deduction)
- {
- // if array is wanted, do not create an object though possible
- if (manual_type == value_t::array)
- {
- is_an_object = false;
- }
- // if object is wanted but impossible, throw an exception
- if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
- {
- JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
- }
- }
- if (is_an_object)
- {
- // the initializer list is a list of pairs -> create object
- m_data.m_type = value_t::object;
- m_data.m_value = value_t::object;
- for (auto& element_ref : init)
- {
- auto element = element_ref.moved_or_copied();
- m_data.m_value.object->emplace(
- std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
- std::move((*element.m_data.m_value.array)[1]));
- }
- }
- else
- {
- // the initializer list describes an array -> create array
- m_data.m_type = value_t::array;
- m_data.m_value.array = create<array_t>(init.begin(), init.end());
- }
- set_parents();
- assert_invariant();
- }
- /// @brief explicitly create a binary array (without subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(const typename binary_t::container_type& init)
- {
- auto res = basic_json();
- res.m_data.m_type = value_t::binary;
- res.m_data.m_value = init;
- return res;
- }
- /// @brief explicitly create a binary array (with subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
- {
- auto res = basic_json();
- res.m_data.m_type = value_t::binary;
- res.m_data.m_value = binary_t(init, subtype);
- return res;
- }
- /// @brief explicitly create a binary array
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(typename binary_t::container_type&& init)
- {
- auto res = basic_json();
- res.m_data.m_type = value_t::binary;
- res.m_data.m_value = std::move(init);
- return res;
- }
- /// @brief explicitly create a binary array (with subtype)
- /// @sa https://json.nlohmann.me/api/basic_json/binary/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
- {
- auto res = basic_json();
- res.m_data.m_type = value_t::binary;
- res.m_data.m_value = binary_t(std::move(init), subtype);
- return res;
- }
- /// @brief explicitly create an array from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/array/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json array(initializer_list_t init = {})
- {
- return basic_json(init, false, value_t::array);
- }
- /// @brief explicitly create an object from an initializer list
- /// @sa https://json.nlohmann.me/api/basic_json/object/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json object(initializer_list_t init = {})
- {
- return basic_json(init, false, value_t::object);
- }
- /// @brief construct an array with count copies of given value
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(size_type cnt, const basic_json& val):
- m_data{cnt, val}
- {
- set_parents();
- assert_invariant();
- }
- /// @brief construct a JSON container given an iterator range
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- template < class InputIT, typename std::enable_if <
- std::is_same<InputIT, typename basic_json_t::iterator>::value ||
- std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
- basic_json(InputIT first, InputIT last)
- {
- JSON_ASSERT(first.m_object != nullptr);
- JSON_ASSERT(last.m_object != nullptr);
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
- }
- // copy type from first iterator
- m_data.m_type = first.m_object->m_data.m_type;
- // check if iterator range is complete for primitive values
- switch (m_data.m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- {
- if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
- || !last.m_it.primitive_iterator.is_end()))
- {
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
- }
- break;
- }
- case value_t::null:
- case value_t::object:
- case value_t::array:
- case value_t::binary:
- case value_t::discarded:
- default:
- break;
- }
- switch (m_data.m_type)
- {
- case value_t::number_integer:
- {
- m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
- break;
- }
- case value_t::number_unsigned:
- {
- m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
- break;
- }
- case value_t::number_float:
- {
- m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
- break;
- }
- case value_t::boolean:
- {
- m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
- break;
- }
- case value_t::string:
- {
- m_data.m_value = *first.m_object->m_data.m_value.string;
- break;
- }
- case value_t::object:
- {
- m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
- last.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
- last.m_it.array_iterator);
- break;
- }
- case value_t::binary:
- {
- m_data.m_value = *first.m_object->m_data.m_value.binary;
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
- }
- set_parents();
- assert_invariant();
- }
- ///////////////////////////////////////
- // other constructors and destructor //
- ///////////////////////////////////////
- template<typename JsonRef,
- detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
- std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
- basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
- /// @brief copy constructor
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(const basic_json& other)
- : json_base_class_t(other)
- {
- m_data.m_type = other.m_data.m_type;
- // check of passed value is valid
- other.assert_invariant();
- switch (m_data.m_type)
- {
- case value_t::object:
- {
- m_data.m_value = *other.m_data.m_value.object;
- break;
- }
- case value_t::array:
- {
- m_data.m_value = *other.m_data.m_value.array;
- break;
- }
- case value_t::string:
- {
- m_data.m_value = *other.m_data.m_value.string;
- break;
- }
- case value_t::boolean:
- {
- m_data.m_value = other.m_data.m_value.boolean;
- break;
- }
- case value_t::number_integer:
- {
- m_data.m_value = other.m_data.m_value.number_integer;
- break;
- }
- case value_t::number_unsigned:
- {
- m_data.m_value = other.m_data.m_value.number_unsigned;
- break;
- }
- case value_t::number_float:
- {
- m_data.m_value = other.m_data.m_value.number_float;
- break;
- }
- case value_t::binary:
- {
- m_data.m_value = *other.m_data.m_value.binary;
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- break;
- }
- set_parents();
- assert_invariant();
- }
- /// @brief move constructor
- /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
- basic_json(basic_json&& other) noexcept
- : json_base_class_t(std::forward<json_base_class_t>(other)),
- m_data(std::move(other.m_data))
- {
- // check that passed value is valid
- other.assert_invariant(false);
- // invalidate payload
- other.m_data.m_type = value_t::null;
- other.m_data.m_value = {};
- set_parents();
- assert_invariant();
- }
- /// @brief copy assignment
- /// @sa https://json.nlohmann.me/api/basic_json/operator=/
- basic_json& operator=(basic_json other) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&&
- std::is_nothrow_move_assignable<json_value>::value&&
- std::is_nothrow_move_assignable<json_base_class_t>::value
- )
- {
- // check that passed value is valid
- other.assert_invariant();
- using std::swap;
- swap(m_data.m_type, other.m_data.m_type);
- swap(m_data.m_value, other.m_data.m_value);
- json_base_class_t::operator=(std::move(other));
- set_parents();
- assert_invariant();
- return *this;
- }
- /// @brief destructor
- /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
- ~basic_json() noexcept
- {
- assert_invariant(false);
- }
- /// @}
- public:
- ///////////////////////
- // object inspection //
- ///////////////////////
- /// @name object inspection
- /// Functions to inspect the type of a JSON value.
- /// @{
- /// @brief serialization
- /// @sa https://json.nlohmann.me/api/basic_json/dump/
- string_t dump(const int indent = -1,
- const char indent_char = ' ',
- const bool ensure_ascii = false,
- const error_handler_t error_handler = error_handler_t::strict) const
- {
- string_t result;
- serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
- if (indent >= 0)
- {
- s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
- }
- else
- {
- s.dump(*this, false, ensure_ascii, 0);
- }
- return result;
- }
- /// @brief return the type of the JSON value (explicit)
- /// @sa https://json.nlohmann.me/api/basic_json/type/
- constexpr value_t type() const noexcept
- {
- return m_data.m_type;
- }
- /// @brief return whether type is primitive
- /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
- constexpr bool is_primitive() const noexcept
- {
- return is_null() || is_string() || is_boolean() || is_number() || is_binary();
- }
- /// @brief return whether type is structured
- /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
- constexpr bool is_structured() const noexcept
- {
- return is_array() || is_object();
- }
- /// @brief return whether value is null
- /// @sa https://json.nlohmann.me/api/basic_json/is_null/
- constexpr bool is_null() const noexcept
- {
- return m_data.m_type == value_t::null;
- }
- /// @brief return whether value is a boolean
- /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
- constexpr bool is_boolean() const noexcept
- {
- return m_data.m_type == value_t::boolean;
- }
- /// @brief return whether value is a number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number/
- constexpr bool is_number() const noexcept
- {
- return is_number_integer() || is_number_float();
- }
- /// @brief return whether value is an integer number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
- constexpr bool is_number_integer() const noexcept
- {
- return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
- }
- /// @brief return whether value is an unsigned integer number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
- constexpr bool is_number_unsigned() const noexcept
- {
- return m_data.m_type == value_t::number_unsigned;
- }
- /// @brief return whether value is a floating-point number
- /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
- constexpr bool is_number_float() const noexcept
- {
- return m_data.m_type == value_t::number_float;
- }
- /// @brief return whether value is an object
- /// @sa https://json.nlohmann.me/api/basic_json/is_object/
- constexpr bool is_object() const noexcept
- {
- return m_data.m_type == value_t::object;
- }
- /// @brief return whether value is an array
- /// @sa https://json.nlohmann.me/api/basic_json/is_array/
- constexpr bool is_array() const noexcept
- {
- return m_data.m_type == value_t::array;
- }
- /// @brief return whether value is a string
- /// @sa https://json.nlohmann.me/api/basic_json/is_string/
- constexpr bool is_string() const noexcept
- {
- return m_data.m_type == value_t::string;
- }
- /// @brief return whether value is a binary array
- /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
- constexpr bool is_binary() const noexcept
- {
- return m_data.m_type == value_t::binary;
- }
- /// @brief return whether value is discarded
- /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
- constexpr bool is_discarded() const noexcept
- {
- return m_data.m_type == value_t::discarded;
- }
- /// @brief return the type of the JSON value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
- constexpr operator value_t() const noexcept
- {
- return m_data.m_type;
- }
- /// @}
- private:
- //////////////////
- // value access //
- //////////////////
- /// get a boolean (explicit)
- boolean_t get_impl(boolean_t* /*unused*/) const
- {
- if (JSON_HEDLEY_LIKELY(is_boolean()))
- {
- return m_data.m_value.boolean;
- }
- JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
- }
- /// get a pointer to the value (object)
- object_t* get_impl_ptr(object_t* /*unused*/) noexcept
- {
- return is_object() ? m_data.m_value.object : nullptr;
- }
- /// get a pointer to the value (object)
- constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
- {
- return is_object() ? m_data.m_value.object : nullptr;
- }
- /// get a pointer to the value (array)
- array_t* get_impl_ptr(array_t* /*unused*/) noexcept
- {
- return is_array() ? m_data.m_value.array : nullptr;
- }
- /// get a pointer to the value (array)
- constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
- {
- return is_array() ? m_data.m_value.array : nullptr;
- }
- /// get a pointer to the value (string)
- string_t* get_impl_ptr(string_t* /*unused*/) noexcept
- {
- return is_string() ? m_data.m_value.string : nullptr;
- }
- /// get a pointer to the value (string)
- constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
- {
- return is_string() ? m_data.m_value.string : nullptr;
- }
- /// get a pointer to the value (boolean)
- boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
- {
- return is_boolean() ? &m_data.m_value.boolean : nullptr;
- }
- /// get a pointer to the value (boolean)
- constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
- {
- return is_boolean() ? &m_data.m_value.boolean : nullptr;
- }
- /// get a pointer to the value (integer number)
- number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
- {
- return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
- }
- /// get a pointer to the value (integer number)
- constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
- {
- return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
- }
- /// get a pointer to the value (unsigned number)
- number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
- {
- return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
- }
- /// get a pointer to the value (unsigned number)
- constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
- {
- return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
- }
- /// get a pointer to the value (floating-point number)
- number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
- {
- return is_number_float() ? &m_data.m_value.number_float : nullptr;
- }
- /// get a pointer to the value (floating-point number)
- constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
- {
- return is_number_float() ? &m_data.m_value.number_float : nullptr;
- }
- /// get a pointer to the value (binary)
- binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
- {
- return is_binary() ? m_data.m_value.binary : nullptr;
- }
- /// get a pointer to the value (binary)
- constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
- {
- return is_binary() ? m_data.m_value.binary : nullptr;
- }
- /*!
- @brief helper function to implement get_ref()
- This function helps to implement get_ref() without code duplication for
- const and non-const overloads
- @tparam ThisType will be deduced as `basic_json` or `const basic_json`
- @throw type_error.303 if ReferenceType does not match underlying value
- type of the current JSON
- */
- template<typename ReferenceType, typename ThisType>
- static ReferenceType get_ref_impl(ThisType& obj)
- {
- // delegate the call to get_ptr<>()
- auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
- if (JSON_HEDLEY_LIKELY(ptr != nullptr))
- {
- return *ptr;
- }
- JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
- }
- public:
- /// @name value access
- /// Direct access to the stored value of a JSON value.
- /// @{
- /// @brief get a pointer value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
- template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value, int>::type = 0>
- auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
- {
- // delegate the call to get_impl_ptr<>()
- return get_impl_ptr(static_cast<PointerType>(nullptr));
- }
- /// @brief get a pointer value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
- template < typename PointerType, typename std::enable_if <
- std::is_pointer<PointerType>::value&&
- std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
- constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
- {
- // delegate the call to get_impl_ptr<>() const
- return get_impl_ptr(static_cast<PointerType>(nullptr));
- }
- private:
- /*!
- @brief get a value (explicit)
- Explicit type conversion between the JSON value and a compatible value
- which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
- and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
- The value is converted by calling the @ref json_serializer<ValueType>
- `from_json()` method.
- The function is equivalent to executing
- @code {.cpp}
- ValueType ret;
- JSONSerializer<ValueType>::from_json(*this, ret);
- return ret;
- @endcode
- This overloads is chosen if:
- - @a ValueType is not @ref basic_json,
- - @ref json_serializer<ValueType> has a `from_json()` method of the form
- `void from_json(const basic_json&, ValueType&)`, and
- - @ref json_serializer<ValueType> does not have a `from_json()` method of
- the form `ValueType from_json(const basic_json&)`
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @a ValueType
- @throw what @ref json_serializer<ValueType> `from_json()` method throws
- @liveexample{The example below shows several conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector<short>`\, (3) A JSON object can be converted to C++
- associative containers such as `std::unordered_map<std::string\,
- json>`.,get__ValueType_const}
- @since version 2.1.0
- */
- template < typename ValueType,
- detail::enable_if_t <
- detail::is_default_constructible<ValueType>::value&&
- detail::has_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
- {
- auto ret = ValueType();
- JSONSerializer<ValueType>::from_json(*this, ret);
- return ret;
- }
- /*!
- @brief get a value (explicit); special case
- Explicit type conversion between the JSON value and a compatible value
- which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
- and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
- The value is converted by calling the @ref json_serializer<ValueType>
- `from_json()` method.
- The function is equivalent to executing
- @code {.cpp}
- return JSONSerializer<ValueType>::from_json(*this);
- @endcode
- This overloads is chosen if:
- - @a ValueType is not @ref basic_json and
- - @ref json_serializer<ValueType> has a `from_json()` method of the form
- `ValueType from_json(const basic_json&)`
- @note If @ref json_serializer<ValueType> has both overloads of
- `from_json()`, this one is chosen.
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @a ValueType
- @throw what @ref json_serializer<ValueType> `from_json()` method throws
- @since version 2.1.0
- */
- template < typename ValueType,
- detail::enable_if_t <
- detail::has_non_default_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
- {
- return JSONSerializer<ValueType>::from_json(*this);
- }
- /*!
- @brief get special-case overload
- This overloads converts the current @ref basic_json in a different
- @ref basic_json type
- @tparam BasicJsonType == @ref basic_json
- @return a copy of *this, converted into @a BasicJsonType
- @complexity Depending on the implementation of the called `from_json()`
- method.
- @since version 3.2.0
- */
- template < typename BasicJsonType,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value,
- int > = 0 >
- BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
- {
- return *this;
- }
- /*!
- @brief get special-case overload
- This overloads avoids a lot of template boilerplate, it can be seen as the
- identity method
- @tparam BasicJsonType == @ref basic_json
- @return a copy of *this
- @complexity Constant.
- @since version 2.1.0
- */
- template<typename BasicJsonType,
- detail::enable_if_t<
- std::is_same<BasicJsonType, basic_json_t>::value,
- int> = 0>
- basic_json get_impl(detail::priority_tag<3> /*unused*/) const
- {
- return *this;
- }
- /*!
- @brief get a pointer value (explicit)
- @copydoc get()
- */
- template<typename PointerType,
- detail::enable_if_t<
- std::is_pointer<PointerType>::value,
- int> = 0>
- constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
- -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
- {
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
- }
- public:
- /*!
- @brief get a (pointer) value (explicit)
- Performs explicit type conversion between the JSON value and a compatible value if required.
- - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
- No copies are made.
- - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
- from the current @ref basic_json.
- - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
- method.
- @tparam ValueTypeCV the provided value type
- @tparam ValueType the returned value type
- @return copy of the JSON value, converted to @tparam ValueType if necessary
- @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
- @since version 2.1.0
- */
- template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
- #if defined(JSON_HAS_CPP_14)
- constexpr
- #endif
- auto get() const noexcept(
- noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
- -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
- {
- // we cannot static_assert on ValueTypeCV being non-const, because
- // there is support for get<const basic_json_t>(), which is why we
- // still need the uncvref
- static_assert(!std::is_reference<ValueTypeCV>::value,
- "get() cannot be used with reference types, you might want to use get_ref()");
- return get_impl<ValueType>(detail::priority_tag<4> {});
- }
- /*!
- @brief get a pointer value (explicit)
- Explicit pointer access to the internally stored JSON value. No copies are
- made.
- @warning The pointer becomes invalid if the underlying JSON object
- changes.
- @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
- object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
- @ref number_unsigned_t, or @ref number_float_t.
- @return pointer to the internally stored JSON value if the requested
- pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
- @complexity Constant.
- @liveexample{The example below shows how pointers to internal values of a
- JSON value can be requested. Note that no type conversions are made and a
- `nullptr` is returned if the value and the requested pointer type does not
- match.,get__PointerType}
- @sa see @ref get_ptr() for explicit pointer-member access
- @since version 1.0.0
- */
- template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value, int>::type = 0>
- auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
- {
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
- }
- /// @brief get a value (explicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_to/
- template < typename ValueType,
- detail::enable_if_t <
- !detail::is_basic_json<ValueType>::value&&
- detail::has_from_json<basic_json_t, ValueType>::value,
- int > = 0 >
- ValueType & get_to(ValueType& v) const noexcept(noexcept(
- JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
- {
- JSONSerializer<ValueType>::from_json(*this, v);
- return v;
- }
- // specialization to allow calling get_to with a basic_json value
- // see https://github.com/nlohmann/json/issues/2175
- template<typename ValueType,
- detail::enable_if_t <
- detail::is_basic_json<ValueType>::value,
- int> = 0>
- ValueType & get_to(ValueType& v) const
- {
- v = *this;
- return v;
- }
- template <
- typename T, std::size_t N,
- typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
- detail::enable_if_t <
- detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
- Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
- noexcept(noexcept(JSONSerializer<Array>::from_json(
- std::declval<const basic_json_t&>(), v)))
- {
- JSONSerializer<Array>::from_json(*this, v);
- return v;
- }
- /// @brief get a reference value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
- template<typename ReferenceType, typename std::enable_if<
- std::is_reference<ReferenceType>::value, int>::type = 0>
- ReferenceType get_ref()
- {
- // delegate call to get_ref_impl
- return get_ref_impl<ReferenceType>(*this);
- }
- /// @brief get a reference value (implicit)
- /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
- template < typename ReferenceType, typename std::enable_if <
- std::is_reference<ReferenceType>::value&&
- std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
- ReferenceType get_ref() const
- {
- // delegate call to get_ref_impl
- return get_ref_impl<ReferenceType>(*this);
- }
- /*!
- @brief get a value (implicit)
- Implicit type conversion between the JSON value and a compatible value.
- The call is realized by calling @ref get() const.
- @tparam ValueType non-pointer type compatible to the JSON value, for
- instance `int` for JSON integer numbers, `bool` for JSON booleans, or
- `std::vector` types for JSON arrays. The character type of @ref string_t
- as well as an initializer list of this type is excluded to avoid
- ambiguities as these types implicitly convert to `std::string`.
- @return copy of the JSON value, converted to type @a ValueType
- @throw type_error.302 in case passed type @a ValueType is incompatible
- to the JSON value type (e.g., the JSON value is of type boolean, but a
- string is requested); see example below
- @complexity Linear in the size of the JSON value.
- @liveexample{The example below shows several conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector<short>`\, (3) A JSON object can be converted to C++
- associative containers such as `std::unordered_map<std::string\,
- json>`.,operator__ValueType}
- @since version 1.0.0
- */
- template < typename ValueType, typename std::enable_if <
- detail::conjunction <
- detail::negation<std::is_pointer<ValueType>>,
- detail::negation<std::is_same<ValueType, std::nullptr_t>>,
- detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
- detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
- detail::negation<detail::is_basic_json<ValueType>>,
- detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
- #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
- detail::negation<std::is_same<ValueType, std::string_view>>,
- #endif
- #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
- detail::negation<std::is_same<ValueType, std::any>>,
- #endif
- detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
- >::value, int >::type = 0 >
- JSON_EXPLICIT operator ValueType() const
- {
- // delegate the call to get<>() const
- return get<ValueType>();
- }
- /// @brief get a binary value
- /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
- binary_t& get_binary()
- {
- if (!is_binary())
- {
- JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
- }
- return *get_ptr<binary_t*>();
- }
- /// @brief get a binary value
- /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
- const binary_t& get_binary() const
- {
- if (!is_binary())
- {
- JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
- }
- return *get_ptr<const binary_t*>();
- }
- /// @}
- ////////////////////
- // element access //
- ////////////////////
- /// @name element access
- /// Access to the JSON value.
- /// @{
- /// @brief access specified array element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(size_type idx)
- {
- // at only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- JSON_TRY
- {
- return set_parent(m_data.m_value.array->at(idx));
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- }
- else
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- }
- /// @brief access specified array element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(size_type idx) const
- {
- // at only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- JSON_TRY
- {
- return m_data.m_value.array->at(idx);
- }
- JSON_CATCH (std::out_of_range&)
- {
- // create better exception explanation
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- }
- else
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(const typename object_t::key_type& key)
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_data.m_value.object->find(key);
- if (it == m_data.m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
- }
- return set_parent(it->second);
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- reference at(KeyType && key)
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
- if (it == m_data.m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
- }
- return set_parent(it->second);
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(const typename object_t::key_type& key) const
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_data.m_value.object->find(key);
- if (it == m_data.m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
- }
- return it->second;
- }
- /// @brief access specified object element with bounds checking
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- const_reference at(KeyType && key) const
- {
- // at only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
- }
- auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
- if (it == m_data.m_value.object->end())
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
- }
- return it->second;
- }
- /// @brief access specified array element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](size_type idx)
- {
- // implicitly convert null value to an empty array
- if (is_null())
- {
- m_data.m_type = value_t::array;
- m_data.m_value.array = create<array_t>();
- assert_invariant();
- }
- // operator[] only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // fill up array with null values if given idx is outside range
- if (idx >= m_data.m_value.array->size())
- {
- #if JSON_DIAGNOSTICS
- // remember array size & capacity before resizing
- const auto old_size = m_data.m_value.array->size();
- const auto old_capacity = m_data.m_value.array->capacity();
- #endif
- m_data.m_value.array->resize(idx + 1);
- #if JSON_DIAGNOSTICS
- if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
- {
- // capacity has changed: update all parents
- set_parents();
- }
- else
- {
- // set parent for values added above
- set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
- }
- #endif
- assert_invariant();
- }
- return m_data.m_value.array->operator[](idx);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
- }
- /// @brief access specified array element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](size_type idx) const
- {
- // const operator[] only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- return m_data.m_value.array->operator[](idx);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](typename object_t::key_type key)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_data.m_type = value_t::object;
- m_data.m_value.object = create<object_t>();
- assert_invariant();
- }
- // operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
- return set_parent(result.first->second);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](const typename object_t::key_type& key) const
- {
- // const operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto it = m_data.m_value.object->find(key);
- JSON_ASSERT(it != m_data.m_value.object->end());
- return it->second;
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
- // (they seemingly cannot be constrained to resolve the ambiguity)
- template<typename T>
- reference operator[](T* key)
- {
- return operator[](typename object_t::key_type(key));
- }
- template<typename T>
- const_reference operator[](T* key) const
- {
- return operator[](typename object_t::key_type(key));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
- reference operator[](KeyType && key)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_data.m_type = value_t::object;
- m_data.m_value.object = create<object_t>();
- assert_invariant();
- }
- // operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
- return set_parent(result.first->second);
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- /// @brief access specified object element
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
- const_reference operator[](KeyType && key) const
- {
- // const operator[] only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
- JSON_ASSERT(it != m_data.m_value.object->end());
- return it->second;
- }
- JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
- }
- private:
- template<typename KeyType>
- using is_comparable_with_object_key = detail::is_comparable <
- object_comparator_t, const typename object_t::key_type&, KeyType >;
- template<typename ValueType>
- using value_return_type = std::conditional <
- detail::is_c_string_uncvref<ValueType>::value,
- string_t, typename std::decay<ValueType>::type >;
- public:
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, detail::enable_if_t <
- !detail::is_transparent<object_comparator_t>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(key);
- if (it != end())
- {
- return it->template get<ValueType>();
- }
- return default_value;
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- !detail::is_transparent<object_comparator_t>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(key);
- if (it != end())
- {
- return it->template get<ReturnType>();
- }
- return std::forward<ValueType>(default_value);
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class KeyType, detail::enable_if_t <
- detail::is_transparent<object_comparator_t>::value
- && !detail::is_json_pointer<KeyType>::value
- && is_comparable_with_object_key<KeyType>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(KeyType && key, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(std::forward<KeyType>(key));
- if (it != end())
- {
- return it->template get<ValueType>();
- }
- return default_value;
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_transparent<object_comparator_t>::value
- && !detail::is_json_pointer<KeyType>::value
- && is_comparable_with_object_key<KeyType>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(KeyType && key, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if key is found, return value and given default value otherwise
- const auto it = find(std::forward<KeyType>(key));
- if (it != end())
- {
- return it->template get<ReturnType>();
- }
- return std::forward<ValueType>(default_value);
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, detail::enable_if_t <
- detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ValueType value(const json_pointer& ptr, const ValueType& default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if pointer resolves a value, return it or use default value
- JSON_TRY
- {
- return ptr.get_checked(this).template get<ValueType>();
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- return default_value;
- }
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- /// @brief access specified object element via JSON Pointer with default value
- /// @sa https://json.nlohmann.me/api/basic_json/value/
- template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- ReturnType value(const json_pointer& ptr, ValueType && default_value) const
- {
- // value only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- // if pointer resolves a value, return it or use default value
- JSON_TRY
- {
- return ptr.get_checked(this).template get<ReturnType>();
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- return std::forward<ValueType>(default_value);
- }
- }
- JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
- }
- template < class ValueType, class BasicJsonType, detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value
- && detail::is_getable<basic_json_t, ValueType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
- {
- return value(ptr.convert(), default_value);
- }
- template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
- detail::enable_if_t <
- detail::is_basic_json<BasicJsonType>::value
- && detail::is_getable<basic_json_t, ReturnType>::value
- && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
- {
- return value(ptr.convert(), std::forward<ValueType>(default_value));
- }
- /// @brief access the first element
- /// @sa https://json.nlohmann.me/api/basic_json/front/
- reference front()
- {
- return *begin();
- }
- /// @brief access the first element
- /// @sa https://json.nlohmann.me/api/basic_json/front/
- const_reference front() const
- {
- return *cbegin();
- }
- /// @brief access the last element
- /// @sa https://json.nlohmann.me/api/basic_json/back/
- reference back()
- {
- auto tmp = end();
- --tmp;
- return *tmp;
- }
- /// @brief access the last element
- /// @sa https://json.nlohmann.me/api/basic_json/back/
- const_reference back() const
- {
- auto tmp = cend();
- --tmp;
- return *tmp;
- }
- /// @brief remove element given an iterator
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, detail::enable_if_t <
- std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
- IteratorType erase(IteratorType pos)
- {
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- IteratorType result = end();
- switch (m_data.m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- case value_t::binary:
- {
- if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
- {
- JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
- }
- if (is_string())
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
- m_data.m_value.string = nullptr;
- }
- else if (is_binary())
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
- m_data.m_value.binary = nullptr;
- }
- m_data.m_type = value_t::null;
- assert_invariant();
- break;
- }
- case value_t::object:
- {
- result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return result;
- }
- /// @brief remove elements given an iterator range
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template < class IteratorType, detail::enable_if_t <
- std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
- std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
- IteratorType erase(IteratorType first, IteratorType last)
- {
- // make sure iterator fits the current value
- if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
- }
- IteratorType result = end();
- switch (m_data.m_type)
- {
- case value_t::boolean:
- case value_t::number_float:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::string:
- case value_t::binary:
- {
- if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
- || !last.m_it.primitive_iterator.is_end()))
- {
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
- }
- if (is_string())
- {
- AllocatorType<string_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
- m_data.m_value.string = nullptr;
- }
- else if (is_binary())
- {
- AllocatorType<binary_t> alloc;
- std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
- std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
- m_data.m_value.binary = nullptr;
- }
- m_data.m_type = value_t::null;
- assert_invariant();
- break;
- }
- case value_t::object:
- {
- result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
- last.m_it.object_iterator);
- break;
- }
- case value_t::array:
- {
- result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
- last.m_it.array_iterator);
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return result;
- }
- private:
- template < typename KeyType, detail::enable_if_t <
- detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
- size_type erase_internal(KeyType && key)
- {
- // this erase only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- return m_data.m_value.object->erase(std::forward<KeyType>(key));
- }
- template < typename KeyType, detail::enable_if_t <
- !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
- size_type erase_internal(KeyType && key)
- {
- // this erase only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
- if (it != m_data.m_value.object->end())
- {
- m_data.m_value.object->erase(it);
- return 1;
- }
- return 0;
- }
- public:
- /// @brief remove element from a JSON object given a key
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- size_type erase(const typename object_t::key_type& key)
- {
- // the indirection via erase_internal() is added to avoid making this
- // function a template and thus de-rank it during overload resolution
- return erase_internal(key);
- }
- /// @brief remove element from a JSON object given a key
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- size_type erase(KeyType && key)
- {
- return erase_internal(std::forward<KeyType>(key));
- }
- /// @brief remove element from a JSON array given an index
- /// @sa https://json.nlohmann.me/api/basic_json/erase/
- void erase(const size_type idx)
- {
- // this erase only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- if (JSON_HEDLEY_UNLIKELY(idx >= size()))
- {
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
- }
- m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
- }
- else
- {
- JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
- }
- }
- /// @}
- ////////////
- // lookup //
- ////////////
- /// @name lookup
- /// @{
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- iterator find(const typename object_t::key_type& key)
- {
- auto result = end();
- if (is_object())
- {
- result.m_it.object_iterator = m_data.m_value.object->find(key);
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- const_iterator find(const typename object_t::key_type& key) const
- {
- auto result = cend();
- if (is_object())
- {
- result.m_it.object_iterator = m_data.m_value.object->find(key);
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- iterator find(KeyType && key)
- {
- auto result = end();
- if (is_object())
- {
- result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
- }
- return result;
- }
- /// @brief find an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/find/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- const_iterator find(KeyType && key) const
- {
- auto result = cend();
- if (is_object())
- {
- result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
- }
- return result;
- }
- /// @brief returns the number of occurrences of a key in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/count/
- size_type count(const typename object_t::key_type& key) const
- {
- // return 0 for all nonobject types
- return is_object() ? m_data.m_value.object->count(key) : 0;
- }
- /// @brief returns the number of occurrences of a key in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/count/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- size_type count(KeyType && key) const
- {
- // return 0 for all nonobject types
- return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
- }
- /// @brief check the existence of an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- bool contains(const typename object_t::key_type& key) const
- {
- return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
- }
- /// @brief check the existence of an element in a JSON object
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
- bool contains(KeyType && key) const
- {
- return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
- }
- /// @brief check the existence of an element in a JSON object given a JSON pointer
- /// @sa https://json.nlohmann.me/api/basic_json/contains/
- bool contains(const json_pointer& ptr) const
- {
- return ptr.contains(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.contains(this);
- }
- /// @}
- ///////////////
- // iterators //
- ///////////////
- /// @name iterators
- /// @{
- /// @brief returns an iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/begin/
- iterator begin() noexcept
- {
- iterator result(this);
- result.set_begin();
- return result;
- }
- /// @brief returns an iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/begin/
- const_iterator begin() const noexcept
- {
- return cbegin();
- }
- /// @brief returns a const iterator to the first element
- /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
- const_iterator cbegin() const noexcept
- {
- const_iterator result(this);
- result.set_begin();
- return result;
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/end/
- iterator end() noexcept
- {
- iterator result(this);
- result.set_end();
- return result;
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/end/
- const_iterator end() const noexcept
- {
- return cend();
- }
- /// @brief returns an iterator to one past the last element
- /// @sa https://json.nlohmann.me/api/basic_json/cend/
- const_iterator cend() const noexcept
- {
- const_iterator result(this);
- result.set_end();
- return result;
- }
- /// @brief returns an iterator to the reverse-beginning
- /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
- reverse_iterator rbegin() noexcept
- {
- return reverse_iterator(end());
- }
- /// @brief returns an iterator to the reverse-beginning
- /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
- const_reverse_iterator rbegin() const noexcept
- {
- return crbegin();
- }
- /// @brief returns an iterator to the reverse-end
- /// @sa https://json.nlohmann.me/api/basic_json/rend/
- reverse_iterator rend() noexcept
- {
- return reverse_iterator(begin());
- }
- /// @brief returns an iterator to the reverse-end
- /// @sa https://json.nlohmann.me/api/basic_json/rend/
- const_reverse_iterator rend() const noexcept
- {
- return crend();
- }
- /// @brief returns a const reverse iterator to the last element
- /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
- const_reverse_iterator crbegin() const noexcept
- {
- return const_reverse_iterator(cend());
- }
- /// @brief returns a const reverse iterator to one before the first
- /// @sa https://json.nlohmann.me/api/basic_json/crend/
- const_reverse_iterator crend() const noexcept
- {
- return const_reverse_iterator(cbegin());
- }
- public:
- /// @brief wrapper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- /// @deprecated This function is deprecated since 3.1.0 and will be removed in
- /// version 4.0.0 of the library. Please use @ref items() instead;
- /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
- JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
- static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
- {
- return ref.items();
- }
- /// @brief wrapper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- /// @deprecated This function is deprecated since 3.1.0 and will be removed in
- /// version 4.0.0 of the library. Please use @ref items() instead;
- /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
- JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
- static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
- {
- return ref.items();
- }
- /// @brief helper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- iteration_proxy<iterator> items() noexcept
- {
- return iteration_proxy<iterator>(*this);
- }
- /// @brief helper to access iterator member functions in range-based for
- /// @sa https://json.nlohmann.me/api/basic_json/items/
- iteration_proxy<const_iterator> items() const noexcept
- {
- return iteration_proxy<const_iterator>(*this);
- }
- /// @}
- //////////////
- // capacity //
- //////////////
- /// @name capacity
- /// @{
- /// @brief checks whether the container is empty.
- /// @sa https://json.nlohmann.me/api/basic_json/empty/
- bool empty() const noexcept
- {
- switch (m_data.m_type)
- {
- case value_t::null:
- {
- // null values are empty
- return true;
- }
- case value_t::array:
- {
- // delegate call to array_t::empty()
- return m_data.m_value.array->empty();
- }
- case value_t::object:
- {
- // delegate call to object_t::empty()
- return m_data.m_value.object->empty();
- }
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types are nonempty
- return false;
- }
- }
- }
- /// @brief returns the number of elements
- /// @sa https://json.nlohmann.me/api/basic_json/size/
- size_type size() const noexcept
- {
- switch (m_data.m_type)
- {
- case value_t::null:
- {
- // null values are empty
- return 0;
- }
- case value_t::array:
- {
- // delegate call to array_t::size()
- return m_data.m_value.array->size();
- }
- case value_t::object:
- {
- // delegate call to object_t::size()
- return m_data.m_value.object->size();
- }
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types have size 1
- return 1;
- }
- }
- }
- /// @brief returns the maximum possible number of elements
- /// @sa https://json.nlohmann.me/api/basic_json/max_size/
- size_type max_size() const noexcept
- {
- switch (m_data.m_type)
- {
- case value_t::array:
- {
- // delegate call to array_t::max_size()
- return m_data.m_value.array->max_size();
- }
- case value_t::object:
- {
- // delegate call to object_t::max_size()
- return m_data.m_value.object->max_size();
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // all other types have max_size() == size()
- return size();
- }
- }
- }
- /// @}
- ///////////////
- // modifiers //
- ///////////////
- /// @name modifiers
- /// @{
- /// @brief clears the contents
- /// @sa https://json.nlohmann.me/api/basic_json/clear/
- void clear() noexcept
- {
- switch (m_data.m_type)
- {
- case value_t::number_integer:
- {
- m_data.m_value.number_integer = 0;
- break;
- }
- case value_t::number_unsigned:
- {
- m_data.m_value.number_unsigned = 0;
- break;
- }
- case value_t::number_float:
- {
- m_data.m_value.number_float = 0.0;
- break;
- }
- case value_t::boolean:
- {
- m_data.m_value.boolean = false;
- break;
- }
- case value_t::string:
- {
- m_data.m_value.string->clear();
- break;
- }
- case value_t::binary:
- {
- m_data.m_value.binary->clear();
- break;
- }
- case value_t::array:
- {
- m_data.m_value.array->clear();
- break;
- }
- case value_t::object:
- {
- m_data.m_value.object->clear();
- break;
- }
- case value_t::null:
- case value_t::discarded:
- default:
- break;
- }
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(basic_json&& val)
- {
- // push_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_data.m_type = value_t::array;
- m_data.m_value = value_t::array;
- assert_invariant();
- }
- // add element to array (move semantics)
- const auto old_capacity = m_data.m_value.array->capacity();
- m_data.m_value.array->push_back(std::move(val));
- set_parent(m_data.m_value.array->back(), old_capacity);
- // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(basic_json&& val)
- {
- push_back(std::move(val));
- return *this;
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(const basic_json& val)
- {
- // push_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_data.m_type = value_t::array;
- m_data.m_value = value_t::array;
- assert_invariant();
- }
- // add element to array
- const auto old_capacity = m_data.m_value.array->capacity();
- m_data.m_value.array->push_back(val);
- set_parent(m_data.m_value.array->back(), old_capacity);
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(const basic_json& val)
- {
- push_back(val);
- return *this;
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(const typename object_t::value_type& val)
- {
- // push_back only works for null objects or objects
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
- {
- JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
- }
- // transform null object into an object
- if (is_null())
- {
- m_data.m_type = value_t::object;
- m_data.m_value = value_t::object;
- assert_invariant();
- }
- // add element to object
- auto res = m_data.m_value.object->insert(val);
- set_parent(res.first->second);
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(const typename object_t::value_type& val)
- {
- push_back(val);
- return *this;
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/push_back/
- void push_back(initializer_list_t init)
- {
- if (is_object() && init.size() == 2 && (*init.begin())->is_string())
- {
- basic_json&& key = init.begin()->moved_or_copied();
- push_back(typename object_t::value_type(
- std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
- }
- else
- {
- push_back(basic_json(init));
- }
- }
- /// @brief add an object to an object
- /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
- reference operator+=(initializer_list_t init)
- {
- push_back(init);
- return *this;
- }
- /// @brief add an object to an array
- /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
- template<class... Args>
- reference emplace_back(Args&& ... args)
- {
- // emplace_back only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
- {
- JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
- }
- // transform null object into an array
- if (is_null())
- {
- m_data.m_type = value_t::array;
- m_data.m_value = value_t::array;
- assert_invariant();
- }
- // add element to array (perfect forwarding)
- const auto old_capacity = m_data.m_value.array->capacity();
- m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
- return set_parent(m_data.m_value.array->back(), old_capacity);
- }
- /// @brief add an object to an object if key does not exist
- /// @sa https://json.nlohmann.me/api/basic_json/emplace/
- template<class... Args>
- std::pair<iterator, bool> emplace(Args&& ... args)
- {
- // emplace only works for null objects or arrays
- if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
- {
- JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
- }
- // transform null object into an object
- if (is_null())
- {
- m_data.m_type = value_t::object;
- m_data.m_value = value_t::object;
- assert_invariant();
- }
- // add element to array (perfect forwarding)
- auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
- set_parent(res.first->second);
- // create result iterator and set iterator to the result of emplace
- auto it = begin();
- it.m_it.object_iterator = res.first;
- // return pair of iterator and boolean
- return {it, res.second};
- }
- /// Helper for insertion of an iterator
- /// @note: This uses std::distance to support GCC 4.8,
- /// see https://github.com/nlohmann/json/pull/1257
- template<typename... Args>
- iterator insert_iterator(const_iterator pos, Args&& ... args)
- {
- iterator result(this);
- JSON_ASSERT(m_data.m_value.array != nullptr);
- auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
- m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
- result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
- // This could have been written as:
- // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
- // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
- set_parents();
- return result;
- }
- /// @brief inserts element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, const basic_json& val)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, val);
- }
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- /// @brief inserts element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, basic_json&& val)
- {
- return insert(pos, val);
- }
- /// @brief inserts copies of element into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, cnt, val);
- }
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- /// @brief inserts range of elements into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, const_iterator first, const_iterator last)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_UNLIKELY(!is_array()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
- {
- JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
- }
- /// @brief inserts elements from initializer list into array
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- iterator insert(const_iterator pos, initializer_list_t ilist)
- {
- // insert only works for arrays
- if (JSON_HEDLEY_UNLIKELY(!is_array()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if iterator pos fits to this JSON value
- if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
- {
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
- }
- // insert to array and return iterator
- return insert_iterator(pos, ilist.begin(), ilist.end());
- }
- /// @brief inserts range of elements into object
- /// @sa https://json.nlohmann.me/api/basic_json/insert/
- void insert(const_iterator first, const_iterator last)
- {
- // insert only works for objects
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- // passed iterators must belong to objects
- if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
- {
- JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
- }
- m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
- }
- /// @brief updates a JSON object from another object, overwriting existing keys
- /// @sa https://json.nlohmann.me/api/basic_json/update/
- void update(const_reference j, bool merge_objects = false)
- {
- update(j.begin(), j.end(), merge_objects);
- }
- /// @brief updates a JSON object from another object, overwriting existing keys
- /// @sa https://json.nlohmann.me/api/basic_json/update/
- void update(const_iterator first, const_iterator last, bool merge_objects = false)
- {
- // implicitly convert null value to an empty object
- if (is_null())
- {
- m_data.m_type = value_t::object;
- m_data.m_value.object = create<object_t>();
- assert_invariant();
- }
- if (JSON_HEDLEY_UNLIKELY(!is_object()))
- {
- JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
- }
- // check if range iterators belong to the same JSON object
- if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
- {
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
- }
- // passed iterators must belong to objects
- if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
- {
- JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
- }
- for (auto it = first; it != last; ++it)
- {
- if (merge_objects && it.value().is_object())
- {
- auto it2 = m_data.m_value.object->find(it.key());
- if (it2 != m_data.m_value.object->end())
- {
- it2->second.update(it.value(), true);
- continue;
- }
- }
- m_data.m_value.object->operator[](it.key()) = it.value();
- #if JSON_DIAGNOSTICS
- m_data.m_value.object->operator[](it.key()).m_parent = this;
- #endif
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(reference other) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- std::is_nothrow_move_assignable<json_value>::value
- )
- {
- std::swap(m_data.m_type, other.m_data.m_type);
- std::swap(m_data.m_value, other.m_data.m_value);
- set_parents();
- other.set_parents();
- assert_invariant();
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- friend void swap(reference left, reference right) noexcept (
- std::is_nothrow_move_constructible<value_t>::value&&
- std::is_nothrow_move_assignable<value_t>::value&&
- std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- std::is_nothrow_move_assignable<json_value>::value
- )
- {
- left.swap(right);
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- {
- // swap only works for arrays
- if (JSON_HEDLEY_LIKELY(is_array()))
- {
- using std::swap;
- swap(*(m_data.m_value.array), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- {
- // swap only works for objects
- if (JSON_HEDLEY_LIKELY(is_object()))
- {
- using std::swap;
- swap(*(m_data.m_value.object), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_string()))
- {
- using std::swap;
- swap(*(m_data.m_value.string), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_binary()))
- {
- using std::swap;
- swap(*(m_data.m_value.binary), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
- }
- }
- /// @brief exchanges the values
- /// @sa https://json.nlohmann.me/api/basic_json/swap/
- void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
- {
- // swap only works for strings
- if (JSON_HEDLEY_LIKELY(is_binary()))
- {
- using std::swap;
- swap(*(m_data.m_value.binary), other);
- }
- else
- {
- JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
- }
- }
- /// @}
- //////////////////////////////////////////
- // lexicographical comparison operators //
- //////////////////////////////////////////
- /// @name lexicographical comparison operators
- /// @{
- // note parentheses around operands are necessary; see
- // https://github.com/nlohmann/json/issues/1530
- #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
- const auto lhs_type = lhs.type(); \
- const auto rhs_type = rhs.type(); \
- \
- if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
- { \
- switch (lhs_type) \
- { \
- case value_t::array: \
- return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
- \
- case value_t::object: \
- return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
- \
- case value_t::null: \
- return (null_result); \
- \
- case value_t::string: \
- return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
- \
- case value_t::boolean: \
- return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
- \
- case value_t::number_integer: \
- return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
- \
- case value_t::number_unsigned: \
- return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
- \
- case value_t::number_float: \
- return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
- \
- case value_t::binary: \
- return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
- \
- case value_t::discarded: \
- default: \
- return (unordered_result); \
- } \
- } \
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
- { \
- return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
- } \
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
- { \
- return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
- } \
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
- { \
- return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
- } \
- else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
- { \
- return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
- } \
- else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
- { \
- return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
- } \
- else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
- { \
- return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
- } \
- else if(compares_unordered(lhs, rhs))\
- {\
- return (unordered_result);\
- }\
- \
- return (default_result);
- JSON_PRIVATE_UNLESS_TESTED:
- // returns true if:
- // - any operand is NaN and the other operand is of number type
- // - any operand is discarded
- // in legacy mode, discarded values are considered ordered if
- // an operation is computed as an odd number of inverses of others
- static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
- {
- if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
- || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
- {
- return true;
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
- #else
- static_cast<void>(inverse);
- return lhs.is_discarded() || rhs.is_discarded();
- #endif
- }
- private:
- bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
- {
- return compares_unordered(*this, rhs, inverse);
- }
- public:
- #if JSON_HAS_THREE_WAY_COMPARISON
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- bool operator==(const_reference rhs) const noexcept
- {
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wfloat-equal"
- #endif
- const_reference lhs = *this;
- JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator==(ScalarType rhs) const noexcept
- {
- return *this == basic_json(rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- bool operator!=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !operator==(rhs);
- }
- /// @brief comparison: 3-way
- /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
- std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
- {
- const_reference lhs = *this;
- // default_result is used if we cannot compare values. In that case,
- // we compare types.
- JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
- std::partial_ordering::equivalent,
- std::partial_ordering::unordered,
- lhs_type <=> rhs_type) // *NOPAD*
- }
- /// @brief comparison: 3-way
- /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
- {
- return *this <=> basic_json(rhs); // *NOPAD*
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- // all operators that are computed as an odd number of inverses of others
- // need to be overloaded to emulate the legacy comparison behavior
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
- bool operator<=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !(rhs < *this);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator<=(ScalarType rhs) const noexcept
- {
- return *this <= basic_json(rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
- bool operator>=(const_reference rhs) const noexcept
- {
- if (compares_unordered(rhs, true))
- {
- return false;
- }
- return !(*this < rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType>
- requires std::is_scalar_v<ScalarType>
- bool operator>=(ScalarType rhs) const noexcept
- {
- return *this >= basic_json(rhs);
- }
- #endif
- #else
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- friend bool operator==(const_reference lhs, const_reference rhs) noexcept
- {
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wfloat-equal"
- #endif
- JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs == basic_json(rhs);
- }
- /// @brief comparison: equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) == rhs;
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(lhs == rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs != basic_json(rhs);
- }
- /// @brief comparison: not equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) != rhs;
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- friend bool operator<(const_reference lhs, const_reference rhs) noexcept
- {
- // default_result is used if we cannot compare values. In that case,
- // we compare types. Note we have to call the operator explicitly,
- // because MSVC has problems otherwise.
- JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs < basic_json(rhs);
- }
- /// @brief comparison: less than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) < rhs;
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(rhs < lhs);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs <= basic_json(rhs);
- }
- /// @brief comparison: less than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) <= rhs;
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- friend bool operator>(const_reference lhs, const_reference rhs) noexcept
- {
- // double inverse
- if (compares_unordered(lhs, rhs))
- {
- return false;
- }
- return !(lhs <= rhs);
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs > basic_json(rhs);
- }
- /// @brief comparison: greater than
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) > rhs;
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
- {
- if (compares_unordered(lhs, rhs, true))
- {
- return false;
- }
- return !(lhs < rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
- {
- return lhs >= basic_json(rhs);
- }
- /// @brief comparison: greater than or equal
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
- template<typename ScalarType, typename std::enable_if<
- std::is_scalar<ScalarType>::value, int>::type = 0>
- friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
- {
- return basic_json(lhs) >= rhs;
- }
- #endif
- #undef JSON_IMPLEMENT_OPERATOR
- /// @}
- ///////////////////
- // serialization //
- ///////////////////
- /// @name serialization
- /// @{
- #ifndef JSON_NO_IO
- /// @brief serialize to stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
- friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
- {
- // read width member and use it as indentation parameter if nonzero
- const bool pretty_print = o.width() > 0;
- const auto indentation = pretty_print ? o.width() : 0;
- // reset width to 0 for subsequent calls to this stream
- o.width(0);
- // do the actual serialization
- serializer s(detail::output_adapter<char>(o), o.fill());
- s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
- return o;
- }
- /// @brief serialize to stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
- /// @deprecated This function is deprecated since 3.0.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// operator<<(std::ostream&, const basic_json&) instead; that is,
- /// replace calls like `j >> o;` with `o << j;`.
- JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
- friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
- {
- return o << j;
- }
- #endif // JSON_NO_IO
- /// @}
- /////////////////////
- // deserialization //
- /////////////////////
- /// @name deserialization
- /// @{
- /// @brief deserialize from a compatible input
- /// @sa https://json.nlohmann.me/api/basic_json/parse/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json parse(InputType&& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- /// @brief deserialize from a pair of character iterators
- /// @sa https://json.nlohmann.me/api/basic_json/parse/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json parse(IteratorType first,
- IteratorType last,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
- static basic_json parse(detail::span_input_adapter&& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true,
- const bool ignore_comments = false)
- {
- basic_json result;
- parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
- return result;
- }
- /// @brief check if the input is valid JSON
- /// @sa https://json.nlohmann.me/api/basic_json/accept/
- template<typename InputType>
- static bool accept(InputType&& i,
- const bool ignore_comments = false)
- {
- return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
- }
- /// @brief check if the input is valid JSON
- /// @sa https://json.nlohmann.me/api/basic_json/accept/
- template<typename IteratorType>
- static bool accept(IteratorType first, IteratorType last,
- const bool ignore_comments = false)
- {
- return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
- static bool accept(detail::span_input_adapter&& i,
- const bool ignore_comments = false)
- {
- return parser(i.get(), nullptr, false, ignore_comments).accept(true);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- template <typename InputType, typename SAX>
- JSON_HEDLEY_NON_NULL(2)
- static bool sax_parse(InputType&& i, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- return format == input_format_t::json
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- template<class IteratorType, class SAX>
- JSON_HEDLEY_NON_NULL(3)
- static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- return format == input_format_t::json
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- /// @brief generate SAX events
- /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
- /// @deprecated This function is deprecated since 3.8.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// sax_parse(ptr, ptr + len) instead.
- template <typename SAX>
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
- JSON_HEDLEY_NON_NULL(2)
- static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
- input_format_t format = input_format_t::json,
- const bool strict = true,
- const bool ignore_comments = false)
- {
- auto ia = i.get();
- return format == input_format_t::json
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
- }
- #ifndef JSON_NO_IO
- /// @brief deserialize from stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
- /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
- /// version 4.0.0 of the library. Please use
- /// operator>>(std::istream&, basic_json&) instead; that is,
- /// replace calls like `j << i;` with `i >> j;`.
- JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
- friend std::istream& operator<<(basic_json& j, std::istream& i)
- {
- return operator>>(i, j);
- }
- /// @brief deserialize from stream
- /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
- friend std::istream& operator>>(std::istream& i, basic_json& j)
- {
- parser(detail::input_adapter(i)).parse(false, j);
- return i;
- }
- #endif // JSON_NO_IO
- /// @}
- ///////////////////////////
- // convenience functions //
- ///////////////////////////
- /// @brief return the type as string
- /// @sa https://json.nlohmann.me/api/basic_json/type_name/
- JSON_HEDLEY_RETURNS_NON_NULL
- const char* type_name() const noexcept
- {
- switch (m_data.m_type)
- {
- case value_t::null:
- return "null";
- case value_t::object:
- return "object";
- case value_t::array:
- return "array";
- case value_t::string:
- return "string";
- case value_t::boolean:
- return "boolean";
- case value_t::binary:
- return "binary";
- case value_t::discarded:
- return "discarded";
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- default:
- return "number";
- }
- }
- JSON_PRIVATE_UNLESS_TESTED:
- //////////////////////
- // member variables //
- //////////////////////
- struct data
- {
- /// the type of the current element
- value_t m_type = value_t::null;
- /// the value of the current element
- json_value m_value = {};
- data(const value_t v)
- : m_type(v), m_value(v)
- {
- }
- data(size_type cnt, const basic_json& val)
- : m_type(value_t::array)
- {
- m_value.array = create<array_t>(cnt, val);
- }
- data() noexcept = default;
- data(data&&) noexcept = default;
- data(const data&) noexcept = delete;
- data& operator=(data&&) noexcept = delete;
- data& operator=(const data&) noexcept = delete;
- ~data() noexcept
- {
- m_value.destroy(m_type);
- }
- };
- data m_data = {};
- #if JSON_DIAGNOSTICS
- /// a pointer to a parent value (for debugging purposes)
- basic_json* m_parent = nullptr;
- #endif
- //////////////////////////////////////////
- // binary serialization/deserialization //
- //////////////////////////////////////////
- /// @name binary serialization/deserialization support
- /// @{
- public:
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static std::vector<std::uint8_t> to_cbor(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_cbor(j, result);
- return result;
- }
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_cbor(j);
- }
- /// @brief create a CBOR serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
- static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_cbor(j);
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_msgpack(j, result);
- return result;
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_msgpack(j);
- }
- /// @brief create a MessagePack serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
- static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_msgpack(j);
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
- const bool use_size = false,
- const bool use_type = false)
- {
- std::vector<std::uint8_t> result;
- to_ubjson(j, result, use_size, use_type);
- return result;
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
- }
- /// @brief create a UBJSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
- static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<char>(o).write_ubjson(j, use_size, use_type);
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
- const bool use_size = false,
- const bool use_type = false)
- {
- std::vector<std::uint8_t> result;
- to_bjdata(j, result, use_size, use_type);
- return result;
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
- }
- /// @brief create a BJData serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
- static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
- const bool use_size = false, const bool use_type = false)
- {
- binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static std::vector<std::uint8_t> to_bson(const basic_json& j)
- {
- std::vector<std::uint8_t> result;
- to_bson(j, result);
- return result;
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
- {
- binary_writer<std::uint8_t>(o).write_bson(j);
- }
- /// @brief create a BSON serialization of a given JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
- static void to_bson(const basic_json& j, detail::output_adapter<char> o)
- {
- binary_writer<char>(o).write_bson(j);
- }
- /// @brief create a JSON value from an input in CBOR format
- /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_cbor(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in CBOR format
- /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_cbor(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
- static basic_json from_cbor(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
- static basic_json from_cbor(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true,
- const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in MessagePack format
- /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_msgpack(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in MessagePack format
- /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_msgpack(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
- static basic_json from_msgpack(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
- static basic_json from_msgpack(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in UBJSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_ubjson(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in UBJSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_ubjson(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
- static basic_json from_ubjson(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
- static basic_json from_ubjson(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BJData format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bjdata(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BJData format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bjdata(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
- template<typename InputType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bson(InputType&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::forward<InputType>(i));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @brief create a JSON value from an input in BSON format
- /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
- template<typename IteratorType>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json from_bson(IteratorType first, IteratorType last,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = detail::input_adapter(std::move(first), std::move(last));
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- template<typename T>
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
- static basic_json from_bson(const T* ptr, std::size_t len,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- return from_bson(ptr, ptr + len, strict, allow_exceptions);
- }
- JSON_HEDLEY_WARN_UNUSED_RESULT
- JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
- static basic_json from_bson(detail::span_input_adapter&& i,
- const bool strict = true,
- const bool allow_exceptions = true)
- {
- basic_json result;
- detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
- auto ia = i.get();
- // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
- const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
- return res ? result : basic_json(value_t::discarded);
- }
- /// @}
- //////////////////////////
- // JSON Pointer support //
- //////////////////////////
- /// @name JSON Pointer functions
- /// @{
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- reference operator[](const json_pointer& ptr)
- {
- return ptr.get_unchecked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
- {
- return ptr.get_unchecked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
- const_reference operator[](const json_pointer& ptr) const
- {
- return ptr.get_unchecked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.get_unchecked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- reference at(const json_pointer& ptr)
- {
- return ptr.get_checked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
- {
- return ptr.get_checked(this);
- }
- /// @brief access specified element via JSON Pointer
- /// @sa https://json.nlohmann.me/api/basic_json/at/
- const_reference at(const json_pointer& ptr) const
- {
- return ptr.get_checked(this);
- }
- template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
- JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
- const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
- {
- return ptr.get_checked(this);
- }
- /// @brief return flattened JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/flatten/
- basic_json flatten() const
- {
- basic_json result(value_t::object);
- json_pointer::flatten("", *this, result);
- return result;
- }
- /// @brief unflatten a previously flattened JSON value
- /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
- basic_json unflatten() const
- {
- return json_pointer::unflatten(*this);
- }
- /// @}
- //////////////////////////
- // JSON Patch functions //
- //////////////////////////
- /// @name JSON Patch functions
- /// @{
- /// @brief applies a JSON patch in-place without copying the object
- /// @sa https://json.nlohmann.me/api/basic_json/patch/
- void patch_inplace(const basic_json& json_patch)
- {
- basic_json& result = *this;
- // the valid JSON Patch operations
- enum class patch_operations {add, remove, replace, move, copy, test, invalid};
- const auto get_op = [](const std::string & op)
- {
- if (op == "add")
- {
- return patch_operations::add;
- }
- if (op == "remove")
- {
- return patch_operations::remove;
- }
- if (op == "replace")
- {
- return patch_operations::replace;
- }
- if (op == "move")
- {
- return patch_operations::move;
- }
- if (op == "copy")
- {
- return patch_operations::copy;
- }
- if (op == "test")
- {
- return patch_operations::test;
- }
- return patch_operations::invalid;
- };
- // wrapper for "add" operation; add value at ptr
- const auto operation_add = [&result](json_pointer & ptr, basic_json val)
- {
- // adding to the root of the target document means replacing it
- if (ptr.empty())
- {
- result = val;
- return;
- }
- // make sure the top element of the pointer exists
- json_pointer const top_pointer = ptr.top();
- if (top_pointer != ptr)
- {
- result.at(top_pointer);
- }
- // get reference to parent of JSON pointer ptr
- const auto last_path = ptr.back();
- ptr.pop_back();
- // parent must exist when performing patch add per RFC6902 specs
- basic_json& parent = result.at(ptr);
- switch (parent.m_data.m_type)
- {
- case value_t::null:
- case value_t::object:
- {
- // use operator[] to add value
- parent[last_path] = val;
- break;
- }
- case value_t::array:
- {
- if (last_path == "-")
- {
- // special case: append to back
- parent.push_back(val);
- }
- else
- {
- const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
- if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
- {
- // avoid undefined behavior
- JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
- }
- // default case: insert add offset
- parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
- }
- break;
- }
- // if there exists a parent it cannot be primitive
- case value_t::string: // LCOV_EXCL_LINE
- case value_t::boolean: // LCOV_EXCL_LINE
- case value_t::number_integer: // LCOV_EXCL_LINE
- case value_t::number_unsigned: // LCOV_EXCL_LINE
- case value_t::number_float: // LCOV_EXCL_LINE
- case value_t::binary: // LCOV_EXCL_LINE
- case value_t::discarded: // LCOV_EXCL_LINE
- default: // LCOV_EXCL_LINE
- JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
- }
- };
- // wrapper for "remove" operation; remove value at ptr
- const auto operation_remove = [this, & result](json_pointer & ptr)
- {
- // get reference to parent of JSON pointer ptr
- const auto last_path = ptr.back();
- ptr.pop_back();
- basic_json& parent = result.at(ptr);
- // remove child
- if (parent.is_object())
- {
- // perform range check
- auto it = parent.find(last_path);
- if (JSON_HEDLEY_LIKELY(it != parent.end()))
- {
- parent.erase(it);
- }
- else
- {
- JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
- }
- }
- else if (parent.is_array())
- {
- // note erase performs range check
- parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
- }
- };
- // type check: top level value must be an array
- if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
- {
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
- }
- // iterate and apply the operations
- for (const auto& val : json_patch)
- {
- // wrapper to get a value for an operation
- const auto get_value = [&val](const std::string & op,
- const std::string & member,
- bool string_type) -> basic_json &
- {
- // find value
- auto it = val.m_data.m_value.object->find(member);
- // context-sensitive error message
- const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
- // check if desired value is present
- if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
- {
- // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
- }
- // check if result is of type string
- if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
- {
- // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
- JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
- }
- // no error: return value
- return it->second;
- };
- // type check: every element of the array must be an object
- if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
- {
- JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
- }
- // collect mandatory members
- const auto op = get_value("op", "op", true).template get<std::string>();
- const auto path = get_value(op, "path", true).template get<std::string>();
- json_pointer ptr(path);
- switch (get_op(op))
- {
- case patch_operations::add:
- {
- operation_add(ptr, get_value("add", "value", false));
- break;
- }
- case patch_operations::remove:
- {
- operation_remove(ptr);
- break;
- }
- case patch_operations::replace:
- {
- // the "path" location must exist - use at()
- result.at(ptr) = get_value("replace", "value", false);
- break;
- }
- case patch_operations::move:
- {
- const auto from_path = get_value("move", "from", true).template get<std::string>();
- json_pointer from_ptr(from_path);
- // the "from" location must exist - use at()
- basic_json const v = result.at(from_ptr);
- // The move operation is functionally identical to a
- // "remove" operation on the "from" location, followed
- // immediately by an "add" operation at the target
- // location with the value that was just removed.
- operation_remove(from_ptr);
- operation_add(ptr, v);
- break;
- }
- case patch_operations::copy:
- {
- const auto from_path = get_value("copy", "from", true).template get<std::string>();
- const json_pointer from_ptr(from_path);
- // the "from" location must exist - use at()
- basic_json const v = result.at(from_ptr);
- // The copy is functionally identical to an "add"
- // operation at the target location using the value
- // specified in the "from" member.
- operation_add(ptr, v);
- break;
- }
- case patch_operations::test:
- {
- bool success = false;
- JSON_TRY
- {
- // check if "value" matches the one at "path"
- // the "path" location must exist - use at()
- success = (result.at(ptr) == get_value("test", "value", false));
- }
- JSON_INTERNAL_CATCH (out_of_range&)
- {
- // ignore out of range errors: success remains false
- }
- // throw an exception if test fails
- if (JSON_HEDLEY_UNLIKELY(!success))
- {
- JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
- }
- break;
- }
- case patch_operations::invalid:
- default:
- {
- // op must be "add", "remove", "replace", "move", "copy", or
- // "test"
- JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
- }
- }
- }
- }
- /// @brief applies a JSON patch to a copy of the current object
- /// @sa https://json.nlohmann.me/api/basic_json/patch/
- basic_json patch(const basic_json& json_patch) const
- {
- basic_json result = *this;
- result.patch_inplace(json_patch);
- return result;
- }
- /// @brief creates a diff as a JSON patch
- /// @sa https://json.nlohmann.me/api/basic_json/diff/
- JSON_HEDLEY_WARN_UNUSED_RESULT
- static basic_json diff(const basic_json& source, const basic_json& target,
- const std::string& path = "")
- {
- // the patch
- basic_json result(value_t::array);
- // if the values are the same, return empty patch
- if (source == target)
- {
- return result;
- }
- if (source.type() != target.type())
- {
- // different types: replace value
- result.push_back(
- {
- {"op", "replace"}, {"path", path}, {"value", target}
- });
- return result;
- }
- switch (source.type())
- {
- case value_t::array:
- {
- // first pass: traverse common elements
- std::size_t i = 0;
- while (i < source.size() && i < target.size())
- {
- // recursive call to compare array values at index i
- auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
- result.insert(result.end(), temp_diff.begin(), temp_diff.end());
- ++i;
- }
- // We now reached the end of at least one array
- // in a second pass, traverse the remaining elements
- // remove my remaining elements
- const auto end_index = static_cast<difference_type>(result.size());
- while (i < source.size())
- {
- // add operations in reverse order to avoid invalid
- // indices
- result.insert(result.begin() + end_index, object(
- {
- {"op", "remove"},
- {"path", detail::concat(path, '/', std::to_string(i))}
- }));
- ++i;
- }
- // add other remaining elements
- while (i < target.size())
- {
- result.push_back(
- {
- {"op", "add"},
- {"path", detail::concat(path, "/-")},
- {"value", target[i]}
- });
- ++i;
- }
- break;
- }
- case value_t::object:
- {
- // first pass: traverse this object's elements
- for (auto it = source.cbegin(); it != source.cend(); ++it)
- {
- // escape the key name to be used in a JSON patch
- const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
- if (target.find(it.key()) != target.end())
- {
- // recursive call to compare object values at key it
- auto temp_diff = diff(it.value(), target[it.key()], path_key);
- result.insert(result.end(), temp_diff.begin(), temp_diff.end());
- }
- else
- {
- // found a key that is not in o -> remove it
- result.push_back(object(
- {
- {"op", "remove"}, {"path", path_key}
- }));
- }
- }
- // second pass: traverse other object's elements
- for (auto it = target.cbegin(); it != target.cend(); ++it)
- {
- if (source.find(it.key()) == source.end())
- {
- // found a key that is not in this -> add it
- const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
- result.push_back(
- {
- {"op", "add"}, {"path", path_key},
- {"value", it.value()}
- });
- }
- }
- break;
- }
- case value_t::null:
- case value_t::string:
- case value_t::boolean:
- case value_t::number_integer:
- case value_t::number_unsigned:
- case value_t::number_float:
- case value_t::binary:
- case value_t::discarded:
- default:
- {
- // both primitive type: replace value
- result.push_back(
- {
- {"op", "replace"}, {"path", path}, {"value", target}
- });
- break;
- }
- }
- return result;
- }
- /// @}
- ////////////////////////////////
- // JSON Merge Patch functions //
- ////////////////////////////////
- /// @name JSON Merge Patch functions
- /// @{
- /// @brief applies a JSON Merge Patch
- /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
- void merge_patch(const basic_json& apply_patch)
- {
- if (apply_patch.is_object())
- {
- if (!is_object())
- {
- *this = object();
- }
- for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
- {
- if (it.value().is_null())
- {
- erase(it.key());
- }
- else
- {
- operator[](it.key()).merge_patch(it.value());
- }
- }
- }
- else
- {
- *this = apply_patch;
- }
- }
- /// @}
- };
- /// @brief user-defined to_string function for JSON values
- /// @sa https://json.nlohmann.me/api/basic_json/to_string/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
- {
- return j.dump();
- }
- inline namespace literals
- {
- inline namespace json_literals
- {
- /// @brief user-defined string literal for JSON values
- /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
- JSON_HEDLEY_NON_NULL(1)
- #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
- inline nlohmann::json operator ""_json(const char* s, std::size_t n)
- #else
- inline nlohmann::json operator "" _json(const char* s, std::size_t n)
- #endif
- {
- return nlohmann::json::parse(s, s + n);
- }
- /// @brief user-defined string literal for JSON pointer
- /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
- JSON_HEDLEY_NON_NULL(1)
- #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
- inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
- #else
- inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
- #endif
- {
- return nlohmann::json::json_pointer(std::string(s, n));
- }
- } // namespace json_literals
- } // namespace literals
- NLOHMANN_JSON_NAMESPACE_END
- ///////////////////////
- // nonmember support //
- ///////////////////////
- namespace std // NOLINT(cert-dcl58-cpp)
- {
- /// @brief hash value for JSON objects
- /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
- {
- std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
- {
- return nlohmann::detail::hash(j);
- }
- };
- // specialization for std::less<value_t>
- template<>
- struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
- {
- /*!
- @brief compare two value_t enum values
- @since version 3.0.0
- */
- bool operator()(::nlohmann::detail::value_t lhs,
- ::nlohmann::detail::value_t rhs) const noexcept
- {
- #if JSON_HAS_THREE_WAY_COMPARISON
- return std::is_lt(lhs <=> rhs); // *NOPAD*
- #else
- return ::nlohmann::detail::operator<(lhs, rhs);
- #endif
- }
- };
- // C++20 prohibit function specialization in the std namespace.
- #ifndef JSON_HAS_CPP_20
- /// @brief exchanges the values of two JSON objects
- /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
- NLOHMANN_BASIC_JSON_TPL_DECLARATION
- inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
- is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
- is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
- {
- j1.swap(j2);
- }
- #endif
- } // namespace std
- #if JSON_USE_GLOBAL_UDLS
- #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
- using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- #else
- using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
- #endif
- #endif
- #include <nlohmann/detail/macro_unscope.hpp>
- #endif // INCLUDE_NLOHMANN_JSON_HPP_
|