libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmJson.c 108KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmJson.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmLex.h"
  11. #include "cmLinkedHeap.h"
  12. #include "cmFile.h"
  13. enum
  14. {
  15. kLCurlyLexTId = kUserLexTId+1,
  16. kRCurlyLexTId,
  17. kLHardLexTId,
  18. kRHardLexTId,
  19. kColonLexTId,
  20. kCommaLexTId,
  21. kTrueLexTId,
  22. kFalseLexTId,
  23. kNullLexTId
  24. };
  25. typedef struct
  26. {
  27. unsigned id;
  28. const char* text;
  29. } cmJsToken_t;
  30. // serialization buffer header
  31. typedef struct
  32. {
  33. unsigned id; // always set to 'json'
  34. unsigned byteCnt; // count of bytes following this field (total buf bytes = byteCnt + (2*sizeof(unsigned)))
  35. unsigned nodeCnt; // count of nodes in this buffer
  36. unsigned version; // buffer serialization version number
  37. } cmJsSerialHdr_t;
  38. // serialization helper record
  39. typedef struct
  40. {
  41. cmJsSerialHdr_t hdr;
  42. char* basePtr;
  43. char* nextPtr;
  44. char* endPtr;
  45. } cmJsSerial_t;
  46. // deserialization helper record
  47. typedef struct
  48. {
  49. unsigned nodeCnt;
  50. unsigned nodeIdx;
  51. const char* nextPtr;
  52. const char* endPtr;
  53. } cmJsDeserial_t;
  54. typedef struct
  55. {
  56. cmErr_t err; //
  57. cmLexH lexH; // parsing lexer
  58. cmLHeapH_t heapH; // linked heap stores all node memory
  59. cmJsonNode_t* rootPtr; // root of internal node tree
  60. cmJsonNode_t* basePtr; // base of parsing stack
  61. cmJsonNode_t* lastPtr; // top of parsing stack
  62. cmJsRC_t rc; // last error code
  63. char* serialBufPtr; // serial buffer pointer
  64. unsigned serialByteCnt; // count of bytes in serialBuf[]
  65. bool reportErrPosnFl;// report the file posn of syntax errors
  66. } cmJs_t;
  67. cmJsToken_t _cmJsTokenArray[] =
  68. {
  69. { kLCurlyLexTId, "{" },
  70. { kRCurlyLexTId, "}" },
  71. { kLHardLexTId, "[" },
  72. { kRHardLexTId, "]" },
  73. { kColonLexTId, ":" },
  74. { kCommaLexTId, "," },
  75. { kTrueLexTId, "true"},
  76. { kFalseLexTId, "false"},
  77. { kNullLexTId, "null" },
  78. { kErrorLexTId,""}
  79. };
  80. cmJsToken_t _cmJsNodeTypeLabel[] =
  81. {
  82. { kObjectTId, "object" },
  83. { kPairTId, "pair" },
  84. { kArrayTId, "array" },
  85. { kStringTId, "string" },
  86. { kIntTId, "int" },
  87. { kRealTId, "real" },
  88. { kNullTId, "null" },
  89. { kTrueTId, "true" },
  90. { kFalseTId, "false" },
  91. { kInvalidTId,"invalid"}
  92. };
  93. cmJsonH_t cmJsonNullHandle = cmSTATIC_NULL_HANDLE;
  94. cmJsRC_t _cmJsonRemoveNode( cmJs_t* p, cmJsonNode_t* np, bool freeFl, bool balancePairsFl );
  95. void _cmJsonFreeNode( cmJs_t* p, cmJsonNode_t* np);
  96. const char* _cmJsonNodeTypeIdToLabel( unsigned nodeTypeId )
  97. {
  98. unsigned i;
  99. for(i=0; _cmJsNodeTypeLabel[i].id != kInvalidTId; ++i)
  100. if( _cmJsNodeTypeLabel[i].id == nodeTypeId )
  101. break;
  102. return _cmJsNodeTypeLabel[i].text;
  103. }
  104. unsigned _cmJsonNodeTypeLabelToId( const char* typeLabel )
  105. {
  106. unsigned i;
  107. for(i=0; _cmJsNodeTypeLabel[i].id != kInvalidTId; ++i)
  108. if( strcmp(_cmJsNodeTypeLabel[i].text,typeLabel) == 0 )
  109. break;
  110. return _cmJsNodeTypeLabel[i].id;
  111. }
  112. cmJs_t* _cmJsonHandleToPtr( cmJsonH_t h )
  113. {
  114. cmJs_t* p = (cmJs_t*)h.h;
  115. assert(p != NULL);
  116. p->rc = kOkJsRC;
  117. return p;
  118. }
  119. cmJsRC_t _cmJsonError( cmJs_t* p, cmJsRC_t rc, const char* fmt, ... )
  120. {
  121. va_list vl;
  122. va_start(vl,fmt);
  123. rc = cmErrVMsg(&p->err,rc,fmt,vl);
  124. va_end(vl);
  125. return rc;
  126. }
  127. cmJsRC_t _cmJsonSyntaxError( cmJs_t* p, const char* fmt, ... )
  128. {
  129. int bn = 1024;
  130. char buf[bn+1];
  131. buf[0]=0;
  132. buf[bn]=0;
  133. va_list vl;
  134. va_start(vl,fmt);
  135. if( p->reportErrPosnFl )
  136. snprintf(buf,bn,"Syntax error on line:%i column:%i. ",cmLexCurrentLineNumber(p->lexH),cmLexCurrentColumnNumber(p->lexH));
  137. int n = strlen(buf);
  138. vsnprintf(buf+n,bn-n,fmt,vl);
  139. va_end(vl);
  140. return cmErrMsg(&p->err,kSyntaxErrJsRC,"%s",buf);
  141. }
  142. // Note that the stack is formed by a linked list
  143. // which is chained together using the nodes parentPtr.
  144. // This works beacause the parentPtr for object,array,
  145. // and pair nodes (the only nodes on the stack) is not
  146. // needed as long as the node is on the stack. Once the
  147. // node is popped the parentPtr is then set from the
  148. // new stack top.
  149. cmJsRC_t _cmJsonPushNode( cmJs_t* p, cmJsonNode_t* np )
  150. {
  151. np->ownerPtr = p->lastPtr;
  152. p->lastPtr = np;
  153. if( p->basePtr == NULL )
  154. p->basePtr = np;
  155. return kOkJsRC;
  156. }
  157. cmJsRC_t _cmJsonPopNode( cmJs_t* p )
  158. {
  159. if( p->lastPtr == NULL )
  160. return _cmJsonSyntaxError(p,"A parser stack underlow signalled a syntax error.");
  161. cmJsonNode_t* t = p->lastPtr;
  162. // remove the top element
  163. p->lastPtr = p->lastPtr->ownerPtr;
  164. // set the parent of the popped node
  165. t->ownerPtr = p->lastPtr;
  166. if( p->lastPtr == NULL )
  167. p->basePtr = NULL;
  168. return kOkJsRC;
  169. }
  170. cmJsRC_t cmJsonInitialize( cmJsonH_t* hp, cmCtx_t* ctx )
  171. {
  172. cmJsRC_t rc;
  173. cmJs_t* p;
  174. unsigned i;
  175. // finalize before initialize
  176. if((rc = cmJsonFinalize(hp)) != kOkJsRC )
  177. return rc;
  178. // allocate the main object record
  179. if((p = cmMemAllocZ( cmJs_t, 1 )) == NULL )
  180. return cmErrMsg(&ctx->err,kMemAllocErrJsRC,"Object memory allocation failed.");
  181. cmErrSetup(&p->err,&ctx->rpt,"JSON Parser");
  182. // allocate the linked heap mgr
  183. if( cmLHeapIsValid(p->heapH = cmLHeapCreate(1024,ctx)) == false )
  184. {
  185. rc = _cmJsonError(p,kMemAllocErrJsRC,"Linked heap object allocation failed.");
  186. goto errLabel;
  187. }
  188. // allocate the lexer
  189. if(cmLexIsValid(p->lexH = cmLexInit(NULL,0,0,&ctx->rpt)) == false )
  190. {
  191. rc = _cmJsonError(p,kLexErrJsRC,"Lex allocation failed.");
  192. goto errLabel;
  193. }
  194. // register json specific tokens with the lexer
  195. for(i=0; _cmJsTokenArray[i].id != kErrorLexTId; ++i)
  196. {
  197. cmRC_t lexRC;
  198. if( (lexRC = cmLexRegisterToken(p->lexH, _cmJsTokenArray[i].id, _cmJsTokenArray[i].text )) != kOkLexRC )
  199. {
  200. rc = _cmJsonError(p,kLexErrJsRC,"Lex token registration failed for:'%s'.\nLexer Error:%s",_cmJsTokenArray[i].text, cmLexRcToMsg(lexRC) );
  201. goto errLabel;
  202. }
  203. }
  204. hp->h = p;
  205. return kOkJsRC;
  206. errLabel:
  207. cmMemPtrFree(&p);
  208. if( cmLHeapIsValid(p->heapH) )
  209. cmLHeapDestroy(&p->heapH);
  210. if( cmLexIsValid(p->lexH) )
  211. cmLexFinal(&p->lexH);
  212. return rc;
  213. }
  214. cmJsRC_t cmJsonInitializeFromFile( cmJsonH_t* hp, const char* fn, cmCtx_t* ctx )
  215. {
  216. cmJsRC_t jsRC;
  217. if((jsRC = cmJsonInitialize(hp,ctx)) != kOkJsRC )
  218. return jsRC;
  219. if((jsRC = cmJsonParseFile(*hp,fn,NULL)) != kOkJsRC )
  220. cmJsonFinalize(hp);
  221. return jsRC;
  222. }
  223. cmJsRC_t cmJsonInitializeFromBuf( cmJsonH_t* hp, cmCtx_t* ctx, const char* buf, unsigned bufByteCnt )
  224. {
  225. cmJsRC_t jsRC;
  226. if((jsRC = cmJsonInitialize(hp,ctx)) != kOkJsRC )
  227. return jsRC;
  228. if((jsRC = cmJsonParse(*hp,buf,bufByteCnt,NULL)) != kOkJsRC )
  229. cmJsonFinalize(hp);
  230. return jsRC;
  231. }
  232. cmJsRC_t cmJsonFinalize( cmJsonH_t* hp )
  233. {
  234. cmRC_t lexRC;
  235. if( hp == NULL || hp->h == NULL )
  236. return kOkJsRC;
  237. cmJs_t* p = _cmJsonHandleToPtr(*hp);
  238. // free the internal heap object
  239. cmLHeapDestroy( &p->heapH );
  240. // free the lexer
  241. if( cmLexIsValid(p->lexH) )
  242. if((lexRC = cmLexFinal(&p->lexH)) != kOkLexRC )
  243. return _cmJsonError(p,kLexErrJsRC,"Lexer finalization failed.\nLexer Error:%s",cmLexRcToMsg(lexRC));
  244. cmMemPtrFree(&p->serialBufPtr);
  245. // free the handle
  246. cmMemPtrFree(&hp->h);
  247. return kOkJsRC;
  248. }
  249. bool cmJsonIsValid( cmJsonH_t h )
  250. { return h.h != NULL; }
  251. cmJsRC_t _cmJsonLinkInChild( cmJs_t* p, cmJsonNode_t* parentPtr, cmJsonNode_t* np )
  252. {
  253. cmJsRC_t rc = kOkJsRC;
  254. np->ownerPtr = parentPtr;
  255. switch( parentPtr->typeId )
  256. {
  257. case kObjectTId:
  258. case kArrayTId:
  259. case kPairTId:
  260. {
  261. // if the parent is an 'object' then the child must be a 'pair'
  262. if( parentPtr->typeId == kObjectTId && np->typeId != kPairTId )
  263. rc = _cmJsonSyntaxError(p,"Expect only 'pair' nodes as children of 'objects'.");
  264. // if the parent is a 'pair' then is may have a max of two children
  265. if( parentPtr->typeId == kPairTId && cmJsonChildCount(parentPtr) >= 2 )
  266. rc = _cmJsonSyntaxError(p,"'pair' nodes may only have 2 children.");
  267. // insert the new node into the parent child list
  268. // if the new node is the first child
  269. if( parentPtr->u.childPtr == NULL )
  270. parentPtr->u.childPtr = np;
  271. else
  272. {
  273. // if the new node is the second or greater child
  274. cmJsonNode_t* lp = parentPtr->u.childPtr;
  275. while( lp->siblingPtr != NULL )
  276. lp = lp->siblingPtr;
  277. lp->siblingPtr = np;
  278. }
  279. }
  280. break;
  281. default:
  282. rc = _cmJsonSyntaxError(p,"'%s' nodes cannot be parent nodes.",_cmJsonNodeTypeIdToLabel(parentPtr->typeId));
  283. break;
  284. }
  285. return rc;
  286. }
  287. // This function creates nodes it also:
  288. // 1. inserts array elments into their parents child list
  289. // 2. inserts pairs into their parents member list
  290. // 3. assigns values to pairs
  291. cmJsRC_t _cmJsonCreateNode( cmJs_t* p, cmJsonNode_t* parentPtr, unsigned newNodeTypeId, cmJsonNode_t** npp )
  292. {
  293. cmJsRC_t rc = kOkJsRC;
  294. cmJsonNode_t* np;
  295. assert( npp != NULL );
  296. *npp = NULL;
  297. // allocate the new node
  298. if((np = cmLHeapAllocZ( p->heapH, sizeof(cmJsonNode_t) )) == NULL )
  299. return _cmJsonError(p,kMemAllocErrJsRC,"Error allocating node memory.");
  300. // set the new node type
  301. np->typeId = newNodeTypeId;
  302. np->ownerPtr = parentPtr;
  303. if( parentPtr == NULL )
  304. {
  305. if( newNodeTypeId != kObjectTId && newNodeTypeId != kArrayTId )
  306. rc = _cmJsonSyntaxError(p,"'%s' nodes must have a parent node.",_cmJsonNodeTypeIdToLabel(newNodeTypeId));
  307. }
  308. else
  309. {
  310. // if the parent is an 'object', 'array', or 'pair' then the
  311. // new node must be a child - insert it into the parent child list
  312. if((rc = _cmJsonLinkInChild( p, parentPtr, np )) != kOkJsRC )
  313. return rc;
  314. switch( newNodeTypeId )
  315. {
  316. case kObjectTId:
  317. case kArrayTId:
  318. break;
  319. case kPairTId:
  320. if( parentPtr == NULL || parentPtr->typeId != kObjectTId )
  321. rc = _cmJsonSyntaxError(p,"'pair' nodes must be the child of an object 'node'.");
  322. break;
  323. default:
  324. if( parentPtr == NULL )
  325. rc = _cmJsonSyntaxError(p,"'%s' nodes must have parent nodes.",_cmJsonNodeTypeIdToLabel(newNodeTypeId));
  326. }
  327. }
  328. // assign the return value
  329. *npp = np;
  330. if( p->rootPtr == NULL)
  331. {
  332. if( np->typeId != kObjectTId && np->typeId != kArrayTId )
  333. rc = _cmJsonSyntaxError(p,"The root object must be an 'object' or 'array'.");
  334. p->rootPtr = np;
  335. }
  336. return rc;
  337. }
  338. cmJsRC_t _cmJsonCreateNumber( cmJs_t* p, cmJsonNode_t* parentPtr, unsigned nodeTId, cmJsonNode_t** npp )
  339. {
  340. // numbers may only occurr as children of a 'pair' or element of an 'array'
  341. if( (parentPtr==NULL) || (parentPtr->typeId != kPairTId && parentPtr->typeId != kArrayTId) )
  342. return _cmJsonSyntaxError(p, "The parent of scalar:%*s is not a 'pair' or 'array'.", cmLexTokenCharCount(p->lexH), cmLexTokenText(p->lexH) );
  343. return _cmJsonCreateNode(p,parentPtr,nodeTId,npp);
  344. }
  345. cmJsRC_t _cmJsonCreateReal(cmJs_t* p, cmJsonNode_t* parentPtr, double v, cmJsonNode_t** newNodePtrPtr )
  346. {
  347. cmJsRC_t rc;
  348. cmJsonNode_t* np = NULL;
  349. if( newNodePtrPtr != NULL )
  350. *newNodePtrPtr = NULL;
  351. if((rc= _cmJsonCreateNumber(p,parentPtr,kRealTId,&np)) == kOkJsRC )
  352. {
  353. np->u.realVal = v;
  354. if( newNodePtrPtr != NULL)
  355. *newNodePtrPtr = np;
  356. }
  357. return rc;
  358. }
  359. cmJsRC_t _cmJsonCreateInt(cmJs_t* p, cmJsonNode_t* parentPtr, int v, cmJsonNode_t** newNodePtrPtr )
  360. {
  361. cmJsRC_t rc;
  362. cmJsonNode_t* np = NULL;
  363. if( newNodePtrPtr != NULL )
  364. *newNodePtrPtr = NULL;
  365. if((rc= _cmJsonCreateNumber(p,parentPtr,kIntTId,&np)) == kOkJsRC )
  366. {
  367. np->u.intVal = v;
  368. if( newNodePtrPtr != NULL )
  369. *newNodePtrPtr = np;
  370. }
  371. return rc;
  372. }
  373. cmJsRC_t _cmJsonCreateBool(cmJs_t* p, cmJsonNode_t* parentPtr, bool fl, cmJsonNode_t** newNodePtrPtr )
  374. {
  375. cmJsRC_t rc;
  376. cmJsonNode_t* np = NULL;
  377. if( newNodePtrPtr != NULL )
  378. *newNodePtrPtr = NULL;
  379. if((rc= _cmJsonCreateNumber(p,parentPtr,fl?kTrueTId:kFalseTId,&np)) == kOkJsRC )
  380. {
  381. np->u.boolVal = fl;
  382. if( newNodePtrPtr != NULL )
  383. *newNodePtrPtr = np;
  384. }
  385. return rc;
  386. }
  387. cmJsRC_t _cmJsonCreateNull(cmJs_t* p, cmJsonNode_t* parentPtr, cmJsonNode_t** newNodePtrPtr )
  388. {
  389. cmJsRC_t rc;
  390. cmJsonNode_t* np = NULL;
  391. if( newNodePtrPtr != NULL )
  392. *newNodePtrPtr = NULL;
  393. if((rc = _cmJsonCreateNumber(p,parentPtr,kNullTId,&np)) == kOkJsRC )
  394. {
  395. if( newNodePtrPtr != NULL )
  396. *newNodePtrPtr = np;
  397. }
  398. return rc;
  399. }
  400. cmJsRC_t _cmJsonEscapeInt( cmJs_t* p, const char* sp, unsigned i, unsigned n, unsigned hexDigitCnt, char* rp )
  401. {
  402. char buf[hexDigitCnt+1];
  403. memset(buf,0,hexDigitCnt+1);
  404. // fill buf[] with the next two characters
  405. unsigned j;
  406. for(j=0; i<n && j<hexDigitCnt; ++i,++j)
  407. buf[j] = sp[i];
  408. // be sure the buffer was filled - we must get exactly two characters
  409. if( i == n )
  410. return _cmJsonError(p,kInvalidHexEscapeJsRC,"An invalid hex escape code was encountered.");
  411. // do the text to int conversion
  412. errno = 0;
  413. long val = strtol(buf,NULL,16);
  414. // validate the conversion
  415. if( errno != 0 )
  416. return _cmJsonError(p,kInvalidHexEscapeJsRC,"Hex escape value conversion failed.");
  417. // convert the long to a character
  418. if( val > 0xff )
  419. return _cmJsonError(p,kInvalidHexEscapeJsRC,"Hex escape value is out of range (0x00-0xff).");
  420. *rp = (char)val;
  421. return kOkJsRC;
  422. }
  423. cmJsRC_t _cmJsonEscapeString( cmJs_t* p, char* dp, const char* sp, unsigned n )
  424. {
  425. cmJsRC_t rc;
  426. unsigned hexDigCnt = 2; // count of digits in \u notation
  427. unsigned i,j;
  428. for(i=0,j=0; i<n; ++i,++j)
  429. {
  430. if( (sp[i] == '\\') && (i<(n-1) ))
  431. {
  432. switch( sp[i+1] )
  433. {
  434. case 'b': dp[j] = '\b'; break;
  435. case 'f': dp[j] = '\f'; break;
  436. case 'n': dp[j] = '\n'; break;
  437. case 'r': dp[j] = '\r'; break;
  438. case 't': dp[j] = '\t'; break;
  439. case 'u':
  440. {
  441. if((rc = _cmJsonEscapeInt( p, sp, i+2, n, hexDigCnt, dp+j )) != kOkJsRC )
  442. return rc;
  443. i += hexDigCnt; // skip hex digits
  444. }
  445. break;
  446. default:
  447. dp[j] = sp[i+1];
  448. break;
  449. }
  450. ++i; // skip the escape character '\'
  451. }
  452. else
  453. {
  454. dp[j] = sp[i];
  455. }
  456. }
  457. if( j < n )
  458. dp[j] = 0;
  459. return kOkJsRC;
  460. }
  461. // if 'cp' is NULL or 'cn' is 0 then the current string is dealloc'd
  462. // and the internal string value is left as NULL.
  463. cmJsRC_t _cmJsonSetString( cmJs_t* p, cmJsonNode_t* np, const char* cp, unsigned cn )
  464. {
  465. assert( np->typeId == kStringTId );
  466. cmJsRC_t rc = kOkJsRC;
  467. // deallocate the current string
  468. if( np->u.stringVal != NULL )
  469. {
  470. cmLHeapFree(p->heapH,np->u.stringVal);
  471. np->u.stringVal = NULL;
  472. }
  473. if( cp != NULL && cn>0 )
  474. {
  475. // allocate the node data memory to hold the string
  476. if((np->u.stringVal = cmLHeapAllocZ(p->heapH,cn+1)) == NULL )
  477. return _cmJsonError(p,kMemAllocErrJsRC,"Unable to allocate stirng memory.");
  478. // copy the string into the node data memory
  479. if((rc = _cmJsonEscapeString(p, np->u.stringVal, cp, cn)) != kOkJsRC )
  480. return rc;
  481. np->u.stringVal[cn]=0;
  482. }
  483. return rc;
  484. }
  485. cmJsRC_t _cmJsonCreateString(cmJs_t* p, cmJsonNode_t* parentPtr, const char* cp, unsigned cn, cmJsonNode_t** newNodePtrPtr )
  486. {
  487. cmJsRC_t rc;
  488. cmJsonNode_t* np = NULL;
  489. if( newNodePtrPtr != NULL )
  490. *newNodePtrPtr = NULL;
  491. // strings may only occurr as children of a 'pair' or element of an 'array'
  492. if( (parentPtr->typeId != kPairTId && parentPtr->typeId != kArrayTId ) )
  493. return _cmJsonSyntaxError(p, "The parent of string:%*s is not a 'pair', 'array', or 'object'.", cn,cp);
  494. // create the new node
  495. if((rc = _cmJsonCreateNode(p,parentPtr,kStringTId,&np)) != kOkJsRC )
  496. return rc;
  497. if((rc = _cmJsonSetString(p,np,cp,cn)) != kOkJsRC )
  498. return rc;
  499. /*
  500. // allocate the node data memory to hold the string
  501. if((np->u.stringVal = cmLHeapAllocZ(p->heapH,cn+1)) == NULL )
  502. return _cmJsonError(p,kMemAllocErrJsRC,"Unable to allocate stirng memory.");
  503. if((rc = _cmJsonEscapeString(p, np->u.stringVal, cp, cn)) != kOkJsRC )
  504. return rc;
  505. // copy the string into the node data memory
  506. //strncpy(np->u.stringVal,cp,cn);
  507. np->u.stringVal[cn]=0;
  508. */
  509. if( newNodePtrPtr != NULL )
  510. *newNodePtrPtr = np;
  511. return rc;
  512. }
  513. cmJsRC_t _cmJsonCreatePair( cmJs_t* p, cmJsonNode_t* parentPtr, const char* label, cmJsonNode_t** newNodePtrPtr )
  514. {
  515. cmJsRC_t rc;
  516. if((rc = _cmJsonCreateNode(p,parentPtr,kPairTId,newNodePtrPtr)) != kOkJsRC )
  517. return rc;
  518. return _cmJsonCreateString( p, *newNodePtrPtr, label, strlen(label), NULL);
  519. }
  520. // if fn == NULL then the buffer must contain the text to parse
  521. cmJsRC_t _cmJsonParse(cmJsonH_t h, const char* buf, unsigned bufCharCnt, const cmChar_t* fn, cmJsonNode_t* altRootPtr )
  522. {
  523. unsigned lexTId = kErrorLexTId;
  524. cmJs_t* p = _cmJsonHandleToPtr(h);
  525. cmJsonNode_t* cnp = altRootPtr == p->rootPtr ? altRootPtr : p->rootPtr;
  526. cmJsonNode_t* nnp = NULL;
  527. cmJsRC_t rc;
  528. p->reportErrPosnFl = true;
  529. // assign the text buffer and reset the lexer
  530. if( fn == NULL )
  531. rc = cmLexSetTextBuffer( p->lexH, buf, bufCharCnt );
  532. else
  533. rc = cmLexSetFile( p->lexH, fn );
  534. if( rc != kOkLexRC )
  535. return _cmJsonError( p, kLexErrJsRC, "Error setting lexer buffer.");
  536. // get the next token
  537. while( (lexTId = cmLexGetNextToken( p->lexH )) != kErrorLexTId && (lexTId != kEofLexTId ) && (rc==kOkJsRC) )
  538. {
  539. cnp = p->lastPtr;
  540. // if cnp is a pair and it's value has been assigned
  541. if( cnp != NULL && cnp->typeId == kPairTId && cmJsonChildCount(cnp)==2 )
  542. {
  543. if((rc = _cmJsonPopNode(p)) != kOkJsRC )
  544. break;
  545. cnp = p->lastPtr;
  546. }
  547. switch( lexTId )
  548. {
  549. case kRealLexTId: // real number
  550. rc = _cmJsonCreateReal(p, cnp, cmLexTokenDouble( p->lexH ), NULL);
  551. break;
  552. case kHexLexTId: // hexidecimal integer
  553. // allow hex integers to be equivalent to decimal integers
  554. case kIntLexTId: // decimal integer
  555. rc = _cmJsonCreateInt(p, cnp, cmLexTokenInt( p->lexH ), NULL );
  556. break;
  557. case kTrueLexTId: // true
  558. rc = _cmJsonCreateBool(p, cnp, true, NULL );
  559. break;
  560. case kFalseLexTId: // false
  561. rc = _cmJsonCreateBool(p, cnp, false, NULL );
  562. break;
  563. case kNullLexTId: // null
  564. rc = _cmJsonCreateNull(p, cnp, NULL );
  565. break;
  566. case kIdentLexTId: // identifier
  567. // allow identifiers to be equivalent to strings.
  568. case kQStrLexTId: // quoted string
  569. if( cnp == NULL )
  570. rc = _cmJsonSyntaxError(p,"Encountered a 'string' with no parent.");
  571. else
  572. if( cnp->typeId == kObjectTId )
  573. {
  574. if((rc = _cmJsonCreateNode(p,cnp,kPairTId,&nnp)) == kOkJsRC )
  575. {
  576. _cmJsonPushNode(p,nnp);
  577. cnp = nnp;
  578. }
  579. //if((rc = _cmJsonCreateNewParent(p,cnp,kPairTId)) == kOkJsRC )
  580. // cnp = p->lastPtr;
  581. }
  582. if( rc == kOkJsRC )
  583. rc = _cmJsonCreateString(p, cnp, cmLexTokenText(p->lexH), cmLexTokenCharCount(p->lexH), NULL);
  584. break;
  585. case kColonLexTId:
  586. if( cnp->typeId != kPairTId )
  587. rc = _cmJsonSyntaxError(p,"A colon was found outside of a 'pair' element.");
  588. break;
  589. case kLCurlyLexTId: // {
  590. //rc = _cmJsonCreateNewParent(p, cnp, kObjectTId );
  591. if((rc = _cmJsonCreateNode(p,cnp,kObjectTId,&nnp)) == kOkJsRC )
  592. _cmJsonPushNode(p,nnp);
  593. break;
  594. case kRCurlyLexTId: // }
  595. if( cnp == NULL || cnp->typeId != kObjectTId )
  596. rc = _cmJsonSyntaxError(p,"A '}' was found without an accompanying opening bracket.");
  597. else
  598. rc = _cmJsonPopNode(p);
  599. break;
  600. case kLHardLexTId: // [
  601. //rc = _cmJsonCreateNewParent(p, cnp, kArrayTId);
  602. if((rc = _cmJsonCreateNode(p,cnp,kArrayTId,&nnp)) == kOkJsRC )
  603. _cmJsonPushNode(p,nnp);
  604. break;
  605. case kRHardLexTId: // ]
  606. if( cnp == NULL || cnp->typeId != kArrayTId )
  607. rc = _cmJsonSyntaxError(p,"A ']' was found without an accompanying opening bracket.");
  608. else
  609. rc = _cmJsonPopNode(p);
  610. break;
  611. case kCommaLexTId: // ,
  612. if( (cnp==NULL) || (cnp->typeId != kArrayTId && cnp->typeId != kObjectTId) )
  613. rc = _cmJsonSyntaxError(p,"Commas may only occur in 'array' and 'object' nodes.");
  614. break;
  615. case kSpaceLexTId: // white space
  616. case kBlockCmtLexTId: // block comment
  617. case kLineCmtLexTId: // line comment
  618. assert(0);
  619. break;
  620. default:
  621. break;
  622. }
  623. }
  624. if( lexTId == kErrorLexTId )
  625. rc = _cmJsonSyntaxError( p, "The lexer failed: %s.", cmLexRcToMsg(cmLexErrorRC(p->lexH)));
  626. p->reportErrPosnFl = false;
  627. return rc;
  628. }
  629. cmJsRC_t cmJsonParse( cmJsonH_t h, const char* buf, unsigned bufCharCnt, cmJsonNode_t* altRootPtr )
  630. { return _cmJsonParse(h,buf,bufCharCnt,NULL,altRootPtr); }
  631. cmJsRC_t cmJsonParseFile( cmJsonH_t h, const char* fn, cmJsonNode_t* altRootPtr )
  632. { return _cmJsonParse(h,NULL,0,fn,altRootPtr); }
  633. /*
  634. cmJsRC_t cmJsonParseFile( cmJsonH_t h, const char* fn )
  635. {
  636. cmJsRC_t rc = kOkJsRC;
  637. FILE* fp = NULL;
  638. cmJs_t* p = _cmJsonHandleToPtr(h);
  639. unsigned n = 0;
  640. char* textBuf = NULL;
  641. assert( fn != NULL && p != NULL );
  642. // open the file
  643. if((fp = fopen(fn,"rb")) == NULL )
  644. return _cmJsonError(p,kFileOpenErrJsRC,"Unable to open the file:'%s'.",fn);
  645. // seek to the end
  646. if( fseek(fp,0,SEEK_END) != 0 )
  647. {
  648. rc= _cmJsonError(p,kFileSeekErrJsRC,"Unable to seek to the end of '%s'.",fn);
  649. goto errLabel;
  650. }
  651. // get the length of the file
  652. if( (n=ftell(fp)) == 0 )
  653. {
  654. rc = _cmJsonError(p,kFileOpenErrJsRC,"The file '%s' appears to be empty.",fn);
  655. goto errLabel;
  656. }
  657. // rewind the file
  658. if( fseek(fp,0,SEEK_SET) != 0 )
  659. {
  660. rc = _cmJsonError(p,kFileSeekErrJsRC,"Unable to seek to the beginning of '%s'.",fn);
  661. goto errLabel;
  662. }
  663. // allocate the text buffer
  664. if((textBuf = cmMemAllocZ( char, n+1)) == NULL )
  665. {
  666. rc = _cmJsonError(p,kMemAllocErrJsRC,"Unable to allocate the text file buffer for:'%s'.",fn);
  667. goto errLabel;
  668. }
  669. // read the file into the text buffer
  670. if( fread(textBuf,n,1,fp) != 1 )
  671. {
  672. rc = _cmJsonError(p,kFileReadErrJsRC,"File read failed on:'%s'.",fn);
  673. goto errLabel;
  674. }
  675. rc = cmJsonParse(h,textBuf,n,NULL);
  676. errLabel:
  677. // close the file
  678. if( fclose(fp) != 0 )
  679. {
  680. rc = _cmJsonError(p,kFileCloseErrJsRC,"File close failed on:'%s'.",fn);
  681. goto errLabel;
  682. }
  683. // free the buffer
  684. if( textBuf != NULL )
  685. cmMemFree(textBuf);
  686. return rc;
  687. }
  688. */
  689. cmJsonNode_t* cmJsonRoot( cmJsonH_t h )
  690. {
  691. cmJs_t* p = _cmJsonHandleToPtr(h);
  692. return p->rootPtr;
  693. }
  694. cmJsRC_t cmJsonClearTree( cmJsonH_t h )
  695. {
  696. cmJs_t* p = _cmJsonHandleToPtr(h);
  697. p->rootPtr = NULL;
  698. p->basePtr = NULL;
  699. p->lastPtr = NULL;
  700. cmLHeapClear(p->heapH,true);
  701. return kOkJsRC;
  702. }
  703. bool cmJsonIsObject( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kObjectTId); }
  704. bool cmJsonIsArray( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kArrayTId); }
  705. bool cmJsonIsPair( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kPairTId); }
  706. bool cmJsonIsString( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kStringTId); }
  707. bool cmJsonIsInt( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kIntTId); }
  708. bool cmJsonIsReal( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kRealTId); }
  709. bool cmJsonIsBool( const cmJsonNode_t* np ) { return cmIsFlag(np->typeId,kTrueTId | kFalseTId); }
  710. unsigned cmJsonChildCount( const cmJsonNode_t* np )
  711. {
  712. if( np == NULL )
  713. return 0;
  714. unsigned n = 0;
  715. switch( np->typeId )
  716. {
  717. case kObjectTId:
  718. case kArrayTId:
  719. case kPairTId:
  720. {
  721. const cmJsonNode_t* lp = np->u.childPtr;
  722. while( lp != NULL )
  723. {
  724. ++n;
  725. lp = lp->siblingPtr;
  726. }
  727. }
  728. break;
  729. default:
  730. break;
  731. }
  732. return n;
  733. }
  734. cmJsonNode_t* cmJsonArrayElement( cmJsonNode_t* np, unsigned index )
  735. {
  736. unsigned i;
  737. assert( index < cmJsonChildCount(np));
  738. np = np->u.childPtr;
  739. for(i=0; i<index; ++i)
  740. np = np->siblingPtr;
  741. return np;
  742. }
  743. const cmJsonNode_t* cmJsonArrayElementC( const cmJsonNode_t* np, unsigned index )
  744. { return cmJsonArrayElement( (cmJsonNode_t*)np, index ); }
  745. const char* cmJsonPairLabel( const cmJsonNode_t* pairPtr )
  746. {
  747. assert( pairPtr->typeId == kPairTId );
  748. if( pairPtr->typeId != kPairTId )
  749. return NULL;
  750. return pairPtr->u.childPtr->u.stringVal;
  751. }
  752. unsigned cmJsonPairTypeId( const cmJsonNode_t* pairPtr )
  753. {
  754. assert( pairPtr->typeId == kPairTId );
  755. return pairPtr->u.childPtr->siblingPtr->typeId;
  756. }
  757. cmJsonNode_t* cmJsonPairValue( cmJsonNode_t* pairPtr )
  758. {
  759. assert( pairPtr->typeId == kPairTId );
  760. if( pairPtr->typeId != kPairTId )
  761. return NULL;
  762. return pairPtr->u.childPtr->siblingPtr;
  763. }
  764. cmJsonNode_t* cmJsonFindValue( cmJsonH_t h, const char* label, const cmJsonNode_t* np, unsigned keyTypeMask )
  765. {
  766. cmJs_t* p = _cmJsonHandleToPtr(h);
  767. if( np == NULL )
  768. np = p->rootPtr;
  769. if( np == NULL )
  770. return NULL;
  771. // we are only interested in pairs
  772. if( np->typeId == kPairTId )
  773. {
  774. // pairs must have exactly two nodes - the first must be a string
  775. assert(np->u.childPtr != NULL && np->u.childPtr->typeId == kStringTId && np->u.childPtr->siblingPtr != NULL );
  776. if( strcmp(cmJsonPairLabel(np),label) == 0 )
  777. {
  778. if( (keyTypeMask==kInvalidTId) || (keyTypeMask & np->u.childPtr->siblingPtr->typeId) )
  779. return np->u.childPtr->siblingPtr;
  780. }
  781. }
  782. // if the node is an object,array, or pair ...
  783. if( np->typeId==kObjectTId || np->typeId==kArrayTId || np->typeId==kPairTId )
  784. {
  785. // ... then recurse on its children
  786. cmJsonNode_t* cnp = np->u.childPtr;
  787. while(cnp != NULL)
  788. {
  789. cmJsonNode_t* rp;
  790. if((rp = cmJsonFindValue(h,label,cnp,keyTypeMask)) != NULL )
  791. return rp;
  792. cnp = cnp->siblingPtr;
  793. }
  794. }
  795. return NULL;
  796. }
  797. cmJsRC_t _cmJsonFindPathValue( cmJs_t* p, const char* pathPrefix, const char* path, const cmJsonNode_t* rp, const cmJsonNode_t** rpp )
  798. {
  799. cmJsRC_t rc = kOkJsRC;
  800. if( rp == NULL )
  801. rp = p->rootPtr;
  802. if( rp == NULL )
  803. return kOkJsRC;
  804. assert( cmJsonIsObject(rp));
  805. assert( rpp != NULL );
  806. *rpp = NULL;
  807. // create a copy of the path
  808. unsigned i,j;
  809. unsigned sn = (pathPrefix==NULL ? 0 : strlen(pathPrefix)) + strlen(path) + 1; // add one for the possible extra seperator
  810. char ss[ 1024 ];
  811. char* sp = NULL;
  812. char* sm = NULL;
  813. char* sb = ss;
  814. // don't put more than 1k on the stack
  815. if( sn + 1 > 1024 )
  816. {
  817. sm = cmMemAllocZ(char,sn+1);
  818. sb = sm;
  819. }
  820. sp = sb;
  821. sp[0] = 0;
  822. if(pathPrefix != NULL )
  823. {
  824. strcpy(sp,pathPrefix);
  825. // if pathPrefix does not end in a '/' then insert one
  826. if( sp[ strlen(sp)-1 ] != '/' )
  827. strcat(sp,"/");
  828. }
  829. // the '/' has already been inserted - skip any leading '/' character in path
  830. strcat(sp,path[0]=='/' ? path+1 : path );
  831. // terminate each path label with a '/0'.
  832. sp = ss;
  833. for(i=0,j=0; sp < ss + sn; ++sp, ++i )
  834. if( *sp == '/' )
  835. {
  836. *sp = 0;
  837. ++j;
  838. }
  839. if( i > 0 )
  840. {
  841. sp = sb;
  842. while( sp < sb + sn )
  843. {
  844. // labeled values are always associated with pairs and
  845. // pairs only exist as the children of objects.
  846. if( cmJsonIsObject(rp) == false )
  847. {
  848. rc = cmErrMsg(&p->err,kInvalidNodeTypeJsRC,"A non-object node was encountered on a object path.");
  849. break;
  850. }
  851. // get the count of pairs in this object
  852. unsigned cn = cmJsonChildCount( rp );
  853. cmJsonNode_t* cp = rp->u.childPtr;
  854. unsigned k;
  855. for(k=0; k<cn; ++k)
  856. {
  857. // all children of an object must be pairs
  858. assert( cp != NULL && cmJsonIsPair(cp) );
  859. // if this is the labeled pair we are looking for
  860. if( strcmp(cmJsonPairLabel(cp),sp) == 0 )
  861. break;
  862. cp = cp->siblingPtr;
  863. }
  864. // if the search failed
  865. if( k == cn || cp == NULL )
  866. {
  867. rc = cmErrMsg(&p->err,kNodeNotFoundJsRC,"The path label '%s' could not be found.",cmStringNullGuard(sp));
  868. break;
  869. }
  870. // take the value of the located pair to continue the search
  871. rp = cmJsonPairValue(cp);
  872. // advance to the next label
  873. sp += strlen(sp) + 1;
  874. }
  875. }
  876. cmMemPtrFree(&sm);
  877. *rpp = rp;
  878. return rc;
  879. }
  880. cmJsRC_t _cmJsonPathToValueError( cmJs_t* p, cmJsRC_t rc, const char* pathPrefix, const char* path, const char* typeLabel )
  881. {
  882. if( pathPrefix != NULL )
  883. cmErrMsg(&p->err,rc,"The JSON value at '%s/%s' could not be converted to a '%s'.",cmStringNullGuard(pathPrefix),cmStringNullGuard(path),cmStringNullGuard(typeLabel));
  884. else
  885. cmErrMsg(&p->err,rc,"The JSON value at '%s' could not be converted to a '%s'.",cmStringNullGuard(path),cmStringNullGuard(typeLabel));
  886. return rc;
  887. }
  888. cmJsRC_t cmJsonPathToValueNode( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, const cmJsonNode_t** nodePtrPtr )
  889. {
  890. cmJsRC_t rc = kOkJsRC;
  891. cmJs_t* p = _cmJsonHandleToPtr(h);
  892. if( objectNodePtr == NULL )
  893. objectNodePtr = p->rootPtr;
  894. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,nodePtrPtr)) != kOkJsRC )
  895. return rc;
  896. return rc;
  897. }
  898. cmJsRC_t cmJsonPathToBool( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, bool* retValPtr )
  899. {
  900. const cmJsonNode_t* rp;
  901. cmJsRC_t rc = kOkJsRC;
  902. cmJs_t* p = _cmJsonHandleToPtr(h);
  903. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  904. return rc;
  905. if((rc = cmJsonBoolValue(rp,retValPtr)) != kOkJsRC )
  906. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"bool");
  907. return rc;
  908. }
  909. cmJsRC_t cmJsonPathToInt( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, int* retValPtr )
  910. {
  911. const cmJsonNode_t* rp;
  912. cmJsRC_t rc = kOkJsRC;
  913. cmJs_t* p = _cmJsonHandleToPtr(h);
  914. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  915. return rc;
  916. if((rc = cmJsonIntValue(rp,retValPtr)) != kOkJsRC )
  917. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"bool");
  918. return rc;
  919. }
  920. cmJsRC_t cmJsonPathToUInt( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, unsigned* retValPtr )
  921. {
  922. const cmJsonNode_t* rp;
  923. cmJsRC_t rc = kOkJsRC;
  924. cmJs_t* p = _cmJsonHandleToPtr(h);
  925. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  926. return rc;
  927. if((rc = cmJsonUIntValue(rp,retValPtr)) != kOkJsRC )
  928. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"unsigned integer");
  929. return rc;
  930. }
  931. cmJsRC_t cmJsonPathToReal( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, double* retValPtr )
  932. {
  933. const cmJsonNode_t* rp;
  934. cmJsRC_t rc = kOkJsRC;
  935. cmJs_t* p = _cmJsonHandleToPtr(h);
  936. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  937. return rc;
  938. if((rc = cmJsonRealValue(rp,retValPtr)) != kOkJsRC )
  939. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"real");
  940. return rc;
  941. }
  942. cmJsRC_t cmJsonPathToString( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, const char** retValPtr )
  943. {
  944. const cmJsonNode_t* rp = NULL;
  945. cmJsRC_t rc = kOkJsRC;
  946. cmJs_t* p = _cmJsonHandleToPtr(h);
  947. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  948. return rc;
  949. if((rc = cmJsonStringValue(rp,retValPtr)) != kOkJsRC )
  950. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"string");
  951. return rc;
  952. }
  953. cmJsRC_t cmJsonPathToPair( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr )
  954. {
  955. const cmJsonNode_t* rp;
  956. cmJsRC_t rc = kOkJsRC;
  957. cmJs_t* p = _cmJsonHandleToPtr(h);
  958. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  959. return rc;
  960. if((rc = cmJsonPairNode(rp,retValPtr)) != kOkJsRC )
  961. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"pair");
  962. return rc;
  963. }
  964. cmJsRC_t cmJsonPathToArray( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr )
  965. {
  966. const cmJsonNode_t* rp;
  967. cmJsRC_t rc = kOkJsRC;
  968. cmJs_t* p = _cmJsonHandleToPtr(h);
  969. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  970. return rc;
  971. if((rc = cmJsonArrayNode(rp,retValPtr)) != kOkJsRC )
  972. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"array");
  973. return rc;
  974. }
  975. cmJsRC_t cmJsonPathToObject( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr )
  976. {
  977. const cmJsonNode_t* rp;
  978. cmJsRC_t rc = kOkJsRC;
  979. cmJs_t* p = _cmJsonHandleToPtr(h);
  980. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objectNodePtr,&rp)) != kOkJsRC )
  981. return rc;
  982. if((rc = cmJsonObjectNode(rp,retValPtr)) != kOkJsRC )
  983. return _cmJsonPathToValueError(p,rc,pathPrefix,path,"object");
  984. return rc;
  985. }
  986. const cmJsonNode_t* cmJsonFindPathValueC( cmJsonH_t h, const char* path, const cmJsonNode_t* np, unsigned typeIdMask )
  987. {
  988. cmJs_t* p = _cmJsonHandleToPtr(h);
  989. const cmJsonNode_t* rp = NULL;
  990. cmJsRC_t rc = kOkJsRC;
  991. if((rc = _cmJsonFindPathValue(p,NULL,path,np,&rp)) != kOkJsRC )
  992. {
  993. // validate the return type
  994. if( rp != NULL )
  995. if( (typeIdMask!=kInvalidTId) && (typeIdMask & rp->typeId)==0 )
  996. {
  997. cmErrMsg(&p->err,kInvalidNodeTypeJsRC,"The value at the end of the path '%s' did not match the requested type.",cmStringNullGuard(path));
  998. rp = NULL;
  999. }
  1000. }
  1001. return rp;
  1002. }
  1003. cmJsonNode_t* cmJsonFindPathValue( cmJsonH_t h, const char* path, const cmJsonNode_t* np, unsigned typeIdMask )
  1004. { return (cmJsonNode_t*)cmJsonFindPathValueC(h,path,np,typeIdMask ); }
  1005. cmJsRC_t _cmJsonFindMemberValue( const cmJsonNode_t* np, const char* label, unsigned keyTypeId, cmJsonNode_t** npp )
  1006. {
  1007. *npp = NULL;
  1008. // the src node must be an object
  1009. if( np->typeId != kObjectTId )
  1010. return kNodeNotFoundJsRC;
  1011. // for each member pair
  1012. const cmJsonNode_t* cnp = np->u.childPtr;
  1013. while( cnp != NULL )
  1014. {
  1015. assert( (cnp->typeId & kMaskTId) == kPairTId );
  1016. // if the labels match ...
  1017. if( strcmp( label, cmJsonPairLabel(cnp)) == 0 )
  1018. {
  1019. // ... and the type flags match ...
  1020. if( (keyTypeId==kInvalidTId || cmIsFlag(cnp->u.childPtr->siblingPtr->typeId,keyTypeId) ) )
  1021. {
  1022. *npp = cnp->u.childPtr->siblingPtr;
  1023. return kOkJsRC; // ... then the key was found.
  1024. }
  1025. // ... label match but wrong type ... this is considered an error
  1026. return kNodeCannotCvtJsRC;
  1027. }
  1028. cnp = cnp->siblingPtr;
  1029. }
  1030. return kNodeNotFoundJsRC;
  1031. }
  1032. cmJsRC_t cmJsonUIntValue( const cmJsonNode_t* vp, unsigned* retPtr )
  1033. {
  1034. cmJsRC_t rc = kOkJsRC;
  1035. if( vp == NULL )
  1036. return kNodeCannotCvtJsRC;
  1037. switch(vp->typeId)
  1038. {
  1039. case kIntTId: *retPtr = vp->u.intVal; break;
  1040. case kRealTId: *retPtr = (unsigned)vp->u.realVal; break;
  1041. case kTrueTId: *retPtr = 1; break;
  1042. case kFalseTId: *retPtr = 0; break;
  1043. default:
  1044. rc = kNodeCannotCvtJsRC;
  1045. }
  1046. return rc;
  1047. }
  1048. cmJsRC_t cmJsonIntValue( const cmJsonNode_t* vp, int* retPtr )
  1049. {
  1050. cmJsRC_t rc = kOkJsRC;
  1051. if( vp == NULL )
  1052. return kNodeCannotCvtJsRC;
  1053. switch(vp->typeId)
  1054. {
  1055. case kIntTId: *retPtr = vp->u.intVal; break;
  1056. case kRealTId: *retPtr = (int)vp->u.realVal; break;
  1057. case kTrueTId: *retPtr = 1; break;
  1058. case kFalseTId: *retPtr = 0; break;
  1059. default:
  1060. rc = kNodeCannotCvtJsRC;
  1061. }
  1062. return rc;
  1063. }
  1064. cmJsRC_t cmJsonRealValue( const cmJsonNode_t* vp, double* retPtr )
  1065. {
  1066. cmJsRC_t rc = kOkJsRC;
  1067. if( vp == NULL )
  1068. return kNodeCannotCvtJsRC;
  1069. switch(vp->typeId)
  1070. {
  1071. case kIntTId: *retPtr = vp->u.intVal; break;
  1072. case kRealTId: *retPtr = vp->u.realVal; break;
  1073. case kTrueTId: *retPtr = 1; break;
  1074. case kFalseTId: *retPtr = 0; break;
  1075. default:
  1076. rc = kNodeCannotCvtJsRC;
  1077. }
  1078. return rc;
  1079. }
  1080. cmJsRC_t cmJsonBoolValue( const cmJsonNode_t* vp, bool* retPtr )
  1081. {
  1082. cmJsRC_t rc = kOkJsRC;
  1083. if( vp == NULL )
  1084. return kNodeCannotCvtJsRC;
  1085. switch(vp->typeId)
  1086. {
  1087. case kIntTId: *retPtr = vp->u.intVal != 0; break;
  1088. case kRealTId: *retPtr = (int)vp->u.realVal != 0; break;
  1089. case kTrueTId: *retPtr = 1; break;
  1090. case kFalseTId: *retPtr = 0; break;
  1091. default:
  1092. rc = kNodeCannotCvtJsRC;
  1093. }
  1094. return rc;
  1095. }
  1096. cmJsRC_t cmJsonStringValue( const cmJsonNode_t* vp, const char **retPtrPtr )
  1097. {
  1098. cmJsRC_t rc = kOkJsRC;
  1099. if( vp == NULL || vp->typeId != kStringTId )
  1100. return kNodeCannotCvtJsRC;
  1101. *retPtrPtr = vp->u.stringVal;
  1102. return rc;
  1103. }
  1104. cmJsRC_t cmJsonPairNode( const cmJsonNode_t* vp, cmJsonNode_t **retPtrPtr )
  1105. {
  1106. cmJsRC_t rc = kOkJsRC;
  1107. if( !cmJsonIsPair(vp) )
  1108. return kNodeCannotCvtJsRC;
  1109. *retPtrPtr = (cmJsonNode_t*)vp;
  1110. return rc;
  1111. }
  1112. cmJsRC_t cmJsonArrayNode( const cmJsonNode_t* vp, cmJsonNode_t **retPtrPtr )
  1113. {
  1114. cmJsRC_t rc = kOkJsRC;
  1115. if( !cmJsonIsArray(vp) )
  1116. return kNodeCannotCvtJsRC;
  1117. *retPtrPtr = (cmJsonNode_t*)vp;
  1118. return rc;
  1119. }
  1120. cmJsRC_t cmJsonObjectNode( const cmJsonNode_t* vp, cmJsonNode_t **retPtrPtr )
  1121. {
  1122. cmJsRC_t rc = kOkJsRC;
  1123. if( !cmJsonIsObject(vp) )
  1124. return kNodeCannotCvtJsRC;
  1125. *retPtrPtr = (cmJsonNode_t*)vp;
  1126. return rc;
  1127. }
  1128. cmJsRC_t cmJsonUIntMember( const cmJsonNode_t* np, const char* label, unsigned* retPtr )
  1129. {
  1130. cmJsonNode_t* vp;
  1131. cmJsRC_t rc;
  1132. if((rc = _cmJsonFindMemberValue(np,label,kNumericTId,&vp)) != kOkJsRC )
  1133. return rc;
  1134. return cmJsonUIntValue(vp,retPtr);
  1135. }
  1136. cmJsRC_t cmJsonIntMember( const cmJsonNode_t* np, const char* label, int* retPtr )
  1137. {
  1138. cmJsonNode_t* vp;
  1139. cmJsRC_t rc;
  1140. if((rc = _cmJsonFindMemberValue(np,label,kNumericTId,&vp)) != kOkJsRC )
  1141. return rc;
  1142. return cmJsonIntValue(vp,retPtr);
  1143. }
  1144. cmJsRC_t cmJsonRealMember( const cmJsonNode_t* np, const char* label, double* retPtr )
  1145. {
  1146. cmJsonNode_t* vp;
  1147. cmJsRC_t rc;
  1148. if((rc = _cmJsonFindMemberValue(np,label,kNumericTId,&vp)) != kOkJsRC )
  1149. return rc;
  1150. return cmJsonRealValue(vp,retPtr);
  1151. }
  1152. cmJsRC_t cmJsonBoolMember( const cmJsonNode_t* np, const char* label, bool* retPtr )
  1153. {
  1154. cmJsonNode_t* vp;
  1155. cmJsRC_t rc;
  1156. if((rc = _cmJsonFindMemberValue(np,label,kNumericTId,&vp)) != kOkJsRC )
  1157. return rc;
  1158. return cmJsonBoolValue(vp,retPtr);
  1159. }
  1160. cmJsRC_t cmJsonStringMember( const cmJsonNode_t* np, const char* label, const char** retPtrPtr )
  1161. {
  1162. cmJsonNode_t* vp;
  1163. cmJsRC_t rc;
  1164. *retPtrPtr = NULL;
  1165. if((rc = _cmJsonFindMemberValue(np,label,kStringTId,&vp)) != kOkJsRC )
  1166. return rc;
  1167. return cmJsonStringValue(vp,retPtrPtr);
  1168. }
  1169. cmJsRC_t cmJsonNodeMember( const cmJsonNode_t* np, const char* label, cmJsonNode_t** retPtrPtr )
  1170. {
  1171. cmJsonNode_t* vp;
  1172. cmJsRC_t rc;
  1173. *retPtrPtr = NULL;
  1174. if((rc = _cmJsonFindMemberValue(np,label,kArrayTId|kObjectTId,&vp)) != kOkJsRC )
  1175. return rc;
  1176. *retPtrPtr = vp;
  1177. return rc;
  1178. }
  1179. cmJsonNode_t* cmJsonNodeMemberValue( const cmJsonNode_t* np, const char* label )
  1180. {
  1181. assert( cmJsonIsObject(np) );
  1182. unsigned n = cmJsonChildCount(np);
  1183. unsigned j = 0;
  1184. for(; j<n; ++j)
  1185. {
  1186. const cmJsonNode_t* cnp = cmJsonArrayElementC(np,j);
  1187. assert( cnp != NULL && cmJsonIsPair(cnp) );
  1188. if( strcmp(label,cmJsonPairLabel(cnp))==0 )
  1189. return cmJsonPairValue((cmJsonNode_t*)cnp);
  1190. }
  1191. return NULL;
  1192. }
  1193. cmJsRC_t cmJsonVMemberValues( const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, va_list vl )
  1194. {
  1195. unsigned typeId;
  1196. cmJsRC_t rc = kOkJsRC;
  1197. if( errLabelPtrPtr != NULL )
  1198. *errLabelPtrPtr = NULL;
  1199. const char* label;
  1200. while( ((label = va_arg(vl,const char*)) != NULL) && (rc==kOkJsRC) )
  1201. {
  1202. typeId = va_arg(vl,unsigned);
  1203. switch( typeId & kMaskTId )
  1204. {
  1205. case kObjectTId:
  1206. case kPairTId:
  1207. case kArrayTId:
  1208. {
  1209. cmJsonNode_t** nodePtrPtr = va_arg(vl, cmJsonNode_t**);
  1210. if((rc = cmJsonNodeMember(objectNodePtr,label,nodePtrPtr )) == kOkJsRC )
  1211. {
  1212. cmJsonNode_t* np = *nodePtrPtr;
  1213. if( (np->typeId & kMaskTId) != (typeId&kMaskTId) )
  1214. rc = kNodeCannotCvtJsRC;
  1215. }
  1216. }
  1217. break;
  1218. case kIntTId:
  1219. {
  1220. int* ip = va_arg(vl, int* );
  1221. assert(ip != NULL);
  1222. rc = cmJsonIntMember(objectNodePtr, label, ip);
  1223. }
  1224. break;
  1225. case kRealTId:
  1226. {
  1227. double* dp = va_arg(vl, double*);
  1228. assert(dp != NULL);
  1229. rc = cmJsonRealMember(objectNodePtr, label, dp);
  1230. }
  1231. break;
  1232. case kStringTId:
  1233. {
  1234. const char** cpp = va_arg(vl, const char**);
  1235. assert(cpp != NULL);
  1236. rc = cmJsonStringMember(objectNodePtr, label, cpp);
  1237. }
  1238. break;
  1239. case kTrueTId:
  1240. case kFalseTId:
  1241. case kBoolTId:
  1242. {
  1243. bool* bp = va_arg(vl, bool* );
  1244. rc = cmJsonBoolMember(objectNodePtr, label, bp);
  1245. }
  1246. break;
  1247. default:
  1248. // missing terminating NULL on the var args list???
  1249. assert(0);
  1250. break;
  1251. }
  1252. if( (rc == kNodeNotFoundJsRC) && cmIsFlag(typeId,kOptArgJsFl) )
  1253. rc = kOkJsRC;
  1254. if( rc != kOkJsRC && errLabelPtrPtr != NULL )
  1255. *errLabelPtrPtr = label;
  1256. }
  1257. return rc;
  1258. }
  1259. cmJsRC_t cmJsonMemberValues( const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, ...)
  1260. {
  1261. va_list vl;
  1262. va_start(vl,errLabelPtrPtr);
  1263. cmJsRC_t rc = cmJsonVMemberValues(objectNodePtr,errLabelPtrPtr,vl);
  1264. va_end(vl);
  1265. return rc;
  1266. }
  1267. cmJsRC_t cmJsonVPathValues( cmJsonH_t h, const char* pathPrefix, const cmJsonNode_t* objNodePtr, const char** errLabelPtrPtr, va_list vl )
  1268. {
  1269. cmJsRC_t rc = kOkJsRC;
  1270. cmJs_t* p = _cmJsonHandleToPtr(h);
  1271. if( errLabelPtrPtr != NULL )
  1272. *errLabelPtrPtr = NULL;
  1273. const char* path;
  1274. while( ((path = va_arg(vl,const char*)) != NULL) && (rc==kOkJsRC) )
  1275. {
  1276. unsigned typeId;
  1277. const cmJsonNode_t* vnp;
  1278. typeId = va_arg(vl,unsigned);
  1279. // find the requested pair value
  1280. if((rc = _cmJsonFindPathValue(p,pathPrefix,path,objNodePtr,&vnp)) != kOkJsRC )
  1281. break;
  1282. switch( typeId & kMaskTId )
  1283. {
  1284. case kObjectTId:
  1285. case kPairTId:
  1286. case kArrayTId:
  1287. {
  1288. const cmJsonNode_t** nodePtrPtr = va_arg(vl, const cmJsonNode_t**);
  1289. if( (vnp->typeId & kMaskTId) != (typeId & kMaskTId) )
  1290. rc = kNodeCannotCvtJsRC;
  1291. else
  1292. *nodePtrPtr = vnp;
  1293. }
  1294. break;
  1295. case kIntTId:
  1296. {
  1297. int* ip = va_arg(vl, int* );
  1298. assert(ip != NULL);
  1299. rc = cmJsonIntValue(vnp, ip);
  1300. }
  1301. break;
  1302. case kRealTId:
  1303. {
  1304. double* dp = va_arg(vl, double*);
  1305. assert(dp != NULL);
  1306. rc = cmJsonRealValue(vnp, dp);
  1307. }
  1308. break;
  1309. case kStringTId:
  1310. {
  1311. const char** cpp = va_arg(vl, const char**);
  1312. assert(cpp != NULL);
  1313. rc = cmJsonStringValue(vnp, cpp);
  1314. }
  1315. break;
  1316. case kTrueTId:
  1317. case kFalseTId:
  1318. {
  1319. bool* bp = va_arg(vl, bool* );
  1320. rc = cmJsonBoolValue(vnp, bp);
  1321. }
  1322. break;
  1323. default:
  1324. // missing terminating NULL on the var args list???
  1325. assert(0);
  1326. break;
  1327. }
  1328. if( (rc == kNodeNotFoundJsRC) && cmIsFlag(typeId,kOptArgJsFl) )
  1329. rc = kOkJsRC;
  1330. if( rc != kOkJsRC && errLabelPtrPtr != NULL )
  1331. *errLabelPtrPtr = path;
  1332. }
  1333. return rc;
  1334. }
  1335. cmJsRC_t cmJsonPathValues( cmJsonH_t h, const char* pathPrefix, const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, ... )
  1336. {
  1337. va_list vl;
  1338. va_start(vl,errLabelPtrPtr);
  1339. cmJsRC_t rc = cmJsonVPathValues(h,pathPrefix,objectNodePtr,errLabelPtrPtr,vl);
  1340. va_end(vl);
  1341. return rc;
  1342. }
  1343. cmJsonNode_t* _cmJsonCreateNode2( cmJsonH_t h, unsigned newNodeTypeId, cmJsonNode_t* parentPtr )
  1344. {
  1345. cmJs_t* p = _cmJsonHandleToPtr(h);
  1346. cmJsonNode_t* np = NULL;
  1347. if((p->rc = _cmJsonCreateNode(p,parentPtr,newNodeTypeId,&np)) != kOkJsRC )
  1348. return NULL;
  1349. return np;
  1350. }
  1351. cmJsRC_t cmJsonCreate( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned typeId, const char* sv, int iv, double dv, cmJsonNode_t** rpp )
  1352. {
  1353. cmJsonNode_t* rp = NULL;
  1354. cmJsRC_t rc = kOkJsRC;
  1355. cmJs_t* p = _cmJsonHandleToPtr(h);
  1356. if( rpp != NULL )
  1357. *rpp = NULL;
  1358. switch( typeId )
  1359. {
  1360. case kObjectTId:
  1361. case kArrayTId:
  1362. if((rp = _cmJsonCreateNode2(h,typeId,parentPtr)) == NULL)
  1363. rc = p->rc;
  1364. else
  1365. {
  1366. if( rpp != NULL )
  1367. *rpp = rp;
  1368. }
  1369. break;
  1370. case kPairTId: rc = _cmJsonCreatePair(p,parentPtr,sv,rpp); break;
  1371. case kIntTId: rc = _cmJsonCreateInt(p,parentPtr,iv,rpp); break;
  1372. case kRealTId: rc = _cmJsonCreateReal(p,parentPtr,dv,rpp); break;
  1373. case kTrueTId: rc = _cmJsonCreateBool(p,parentPtr,true,rpp); break;
  1374. case kFalseTId: rc = _cmJsonCreateBool(p,parentPtr,false,rpp); break;
  1375. case kNullTId: rc = _cmJsonCreateNull(p,parentPtr,rpp); break;
  1376. case kStringTId: rc = _cmJsonCreateString(p,parentPtr,sv,strlen(sv),rpp); break;
  1377. default:
  1378. assert(0);
  1379. break;
  1380. }
  1381. return rc;
  1382. }
  1383. cmJsonNode_t* cmJsonCreateObject( cmJsonH_t h, cmJsonNode_t* parentPtr )
  1384. { return _cmJsonCreateNode2(h,kObjectTId,parentPtr); }
  1385. cmJsonNode_t* cmJsonCreateArray( cmJsonH_t h, cmJsonNode_t* parentPtr )
  1386. { return _cmJsonCreateNode2(h,kArrayTId,parentPtr); }
  1387. cmJsonNode_t* cmJsonCreatePair( cmJsonH_t h, cmJsonNode_t* parentPtr, const char* label )
  1388. {
  1389. cmJsonNode_t* np;
  1390. cmJs_t* p = _cmJsonHandleToPtr(h);
  1391. if((_cmJsonCreatePair(p,parentPtr,label,&np)) != kOkJsRC )
  1392. return NULL;
  1393. return np;
  1394. }
  1395. cmJsRC_t cmJsonCreateString( cmJsonH_t h, cmJsonNode_t* parentPtr, const char* stringValue )
  1396. {
  1397. cmJs_t* p = _cmJsonHandleToPtr(h);
  1398. return _cmJsonCreateString( p, parentPtr, stringValue, strlen(stringValue),NULL);;
  1399. }
  1400. cmJsRC_t cmJsonCreateStringN(cmJsonH_t h, cmJsonNode_t* parentPtr, const char* stringValue, unsigned stringCharCnt )
  1401. {
  1402. cmJs_t* p = _cmJsonHandleToPtr(h);
  1403. return _cmJsonCreateString( p, parentPtr, stringValue, stringCharCnt,NULL);;
  1404. }
  1405. cmJsRC_t cmJsonCreateInt( cmJsonH_t h, cmJsonNode_t* parentPtr, int value )
  1406. {
  1407. cmJs_t* p = _cmJsonHandleToPtr(h);
  1408. return _cmJsonCreateInt( p, parentPtr, value, NULL );
  1409. }
  1410. cmJsRC_t cmJsonCreateReal( cmJsonH_t h, cmJsonNode_t* parentPtr, double value )
  1411. {
  1412. cmJs_t* p = _cmJsonHandleToPtr(h);
  1413. return _cmJsonCreateReal( p, parentPtr, value, NULL );
  1414. }
  1415. cmJsRC_t cmJsonCreateBool( cmJsonH_t h, cmJsonNode_t* parentPtr, bool value )
  1416. {
  1417. cmJs_t* p = _cmJsonHandleToPtr(h);
  1418. return _cmJsonCreateBool( p, parentPtr, value,NULL );
  1419. }
  1420. cmJsRC_t cmJsonCreateNull( cmJsonH_t h, cmJsonNode_t* parentPtr )
  1421. {
  1422. cmJs_t* p = _cmJsonHandleToPtr(h);
  1423. return _cmJsonCreateNull( p, parentPtr, NULL );
  1424. }
  1425. cmJsRC_t cmJsonCreateStringArray( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const char** value )
  1426. {
  1427. cmJs_t* p = _cmJsonHandleToPtr(h);
  1428. cmJsRC_t rc = kOkJsRC;
  1429. cmJsonNode_t* np;
  1430. unsigned i;
  1431. if((np = cmJsonCreateArray(h,parentPtr)) == NULL )
  1432. return _cmJsonError(p,cmErrLastRC(&p->err),"Unable to create 'bool' array.");
  1433. for(i=0; i<n; ++i)
  1434. if((rc = cmJsonCreateString(h,np,value[i])) != kOkJsRC )
  1435. return _cmJsonError(p,rc,"Unable to create 'bool' array element at index %i.",i);
  1436. return rc;
  1437. }
  1438. cmJsRC_t cmJsonCreateIntArray( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const int* value )
  1439. {
  1440. cmJs_t* p = _cmJsonHandleToPtr(h);
  1441. cmJsRC_t rc = kOkJsRC;
  1442. cmJsonNode_t* np;
  1443. unsigned i;
  1444. if((np = cmJsonCreateArray(h,parentPtr)) == NULL )
  1445. return _cmJsonError(p,cmErrLastRC(&p->err),"Unable to create 'int' array.");
  1446. for(i=0; i<n; ++i)
  1447. if((rc = cmJsonCreateInt(h,np,value[i])) != kOkJsRC )
  1448. return _cmJsonError(p,rc,"Unable to create 'int' array element at index %i.",i);
  1449. return rc;
  1450. }
  1451. cmJsRC_t cmJsonCreateRealArray( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const double* value )
  1452. {
  1453. cmJs_t* p = _cmJsonHandleToPtr(h);
  1454. cmJsRC_t rc = kOkJsRC;
  1455. cmJsonNode_t* np;
  1456. unsigned i;
  1457. if((np = cmJsonCreateArray(h,parentPtr)) == NULL )
  1458. return _cmJsonError(p,cmErrLastRC(&p->err),"Unable to create 'real' array.");
  1459. for(i=0; i<n; ++i)
  1460. if((rc = cmJsonCreateReal(h,np,value[i])) != kOkJsRC )
  1461. return _cmJsonError(p,rc,"Unable to create 'real' array element at index %i.",i);
  1462. return rc;
  1463. }
  1464. cmJsRC_t cmJsonCreateBoolArray( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const bool* value )
  1465. {
  1466. cmJs_t* p = _cmJsonHandleToPtr(h);
  1467. cmJsRC_t rc = kOkJsRC;
  1468. cmJsonNode_t* np;
  1469. unsigned i;
  1470. if((np = cmJsonCreateArray(h,parentPtr)) == NULL )
  1471. return _cmJsonError(p,cmErrLastRC(&p->err),"Unable to create 'bool' array.");
  1472. for(i=0; i<n; ++i)
  1473. if((rc = cmJsonCreateBool(h,np,value[i])) != kOkJsRC )
  1474. return _cmJsonError(p,rc,"Unable to create 'bool' array element at index %i.",i);
  1475. return rc;
  1476. }
  1477. cmJsRC_t cmJsonSetInt( cmJsonH_t h, cmJsonNode_t* np, int ival )
  1478. {
  1479. if( np->typeId != kIntTId )
  1480. return _cmJsonError(_cmJsonHandleToPtr(h),kInvalidNodeTypeJsRC,"Cannot assign type 'int' to node type '%s'.",_cmJsonNodeTypeIdToLabel(np->typeId));
  1481. np->u.intVal = ival;
  1482. return kOkJsRC;
  1483. }
  1484. cmJsRC_t cmJsonSetReal( cmJsonH_t h, cmJsonNode_t * np, double rval )
  1485. {
  1486. if( np->typeId != kRealTId )
  1487. return _cmJsonError(_cmJsonHandleToPtr(h),kInvalidNodeTypeJsRC,"Cannot assign type 'real' to node type '%s'.",_cmJsonNodeTypeIdToLabel(np->typeId));
  1488. np->u.realVal = rval;
  1489. return kOkJsRC;
  1490. }
  1491. cmJsRC_t cmJsonSetBool( cmJsonH_t h, cmJsonNode_t * np, bool bval )
  1492. {
  1493. if( np->typeId == kTrueTId || np->typeId==kFalseTId )
  1494. return _cmJsonError(_cmJsonHandleToPtr(h),kInvalidNodeTypeJsRC,"Cannot assign type 'bool' to node type '%s'.",_cmJsonNodeTypeIdToLabel(np->typeId));
  1495. np->u.boolVal = bval;
  1496. return kOkJsRC;
  1497. }
  1498. cmJsRC_t cmJsonSetString( cmJsonH_t h, cmJsonNode_t* np, const char* sval )
  1499. {
  1500. cmJs_t* p = _cmJsonHandleToPtr(h);
  1501. if( np->typeId != kStringTId )
  1502. return _cmJsonError(p,kInvalidNodeTypeJsRC,"Cannot assign type 'string' to node type '%s'.",_cmJsonNodeTypeIdToLabel(np->typeId));
  1503. unsigned sn = strlen(sval);
  1504. if( np->u.stringVal != NULL && strlen(np->u.stringVal) <= sn )
  1505. strcpy(np->u.stringVal,sval);
  1506. else
  1507. return _cmJsonSetString(p,np,sval,sn);
  1508. return kOkJsRC;
  1509. }
  1510. cmJsonNode_t* cmJsonInsertPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned typeId, const char* sv, int iv, double dv )
  1511. {
  1512. assert( objectNodePtr->typeId == kObjectTId );
  1513. cmJsRC_t rc;
  1514. cmJsonNode_t* pairNodePtr;
  1515. cmJs_t* p = _cmJsonHandleToPtr(h);
  1516. if((rc = _cmJsonCreatePair(p,objectNodePtr,label,&pairNodePtr)) != kOkJsRC )
  1517. return NULL;
  1518. assert( pairNodePtr != NULL );
  1519. if((rc = cmJsonCreate(h,pairNodePtr,typeId,sv,iv,dv,NULL)) != kOkJsRC )
  1520. return NULL;
  1521. return pairNodePtr;
  1522. }
  1523. cmJsonNode_t* cmJsonInsertPairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label )
  1524. {
  1525. assert( objectNodePtr->typeId == kObjectTId );
  1526. cmJsonNode_t* pairNodePtr;
  1527. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1528. return NULL;
  1529. return cmJsonCreateObject(h,pairNodePtr);
  1530. }
  1531. cmJsonNode_t* cmJsonInsertPairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label )
  1532. {
  1533. assert( objectNodePtr->typeId == kObjectTId );
  1534. cmJsonNode_t* pairNodePtr;
  1535. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1536. return NULL;
  1537. return cmJsonCreateArray(h,pairNodePtr);
  1538. }
  1539. cmJsonNode_t* cmJsonInsertPairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* pairLabel )
  1540. {
  1541. assert( objectNodePtr->typeId == kObjectTId );
  1542. cmJsonNode_t* pairNodePtr;
  1543. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1544. return NULL;
  1545. return cmJsonCreatePair(h,pairNodePtr,pairLabel);
  1546. }
  1547. cmJsRC_t cmJsonInsertPairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, int intVal )
  1548. {
  1549. assert( objectNodePtr->typeId == kObjectTId );
  1550. cmJsonNode_t* pairNodePtr;
  1551. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1552. return cmJsonErrorCode(h);
  1553. return cmJsonCreateInt(h,pairNodePtr,intVal);
  1554. }
  1555. cmJsRC_t cmJsonInsertPairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, double realVal )
  1556. {
  1557. assert( objectNodePtr->typeId == kObjectTId );
  1558. cmJsonNode_t* pairNodePtr;
  1559. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1560. return cmJsonErrorCode(h);
  1561. return cmJsonCreateReal(h,pairNodePtr,realVal);
  1562. }
  1563. cmJsRC_t cmJsonInsertPairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* stringVal )
  1564. { return cmJsonInsertPairStringN(h,objectNodePtr,label,stringVal,strlen(stringVal)); }
  1565. cmJsRC_t cmJsonInsertPairStringN( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* stringVal, unsigned stringCharCnt )
  1566. {
  1567. assert( objectNodePtr->typeId == kObjectTId );
  1568. cmJsonNode_t* pairNodePtr;
  1569. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1570. return cmJsonErrorCode(h);
  1571. return cmJsonCreateStringN(h,pairNodePtr,stringVal,stringCharCnt);
  1572. }
  1573. cmJsRC_t cmJsonInsertPairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, bool boolVal )
  1574. {
  1575. assert( objectNodePtr->typeId == kObjectTId );
  1576. cmJsonNode_t* pairNodePtr;
  1577. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1578. return cmJsonErrorCode(h);
  1579. return cmJsonCreateBool(h,pairNodePtr,boolVal);
  1580. }
  1581. cmJsRC_t cmJsonInsertPairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label )
  1582. {
  1583. assert( objectNodePtr->typeId == kObjectTId );
  1584. cmJsonNode_t* pairNodePtr;
  1585. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1586. return cmJsonErrorCode(h);
  1587. return cmJsonCreateNull(h,pairNodePtr);
  1588. }
  1589. cmJsRC_t cmJsonInsertPairIntArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const int* values )
  1590. {
  1591. assert( objectNodePtr->typeId == kObjectTId );
  1592. cmJsonNode_t* pairNodePtr;
  1593. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1594. return cmJsonErrorCode(h);
  1595. return cmJsonCreateIntArray(h,pairNodePtr,n,values);
  1596. }
  1597. cmJsRC_t cmJsonInsertPairRealArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const double* values )
  1598. {
  1599. assert( objectNodePtr->typeId == kObjectTId );
  1600. cmJsonNode_t* pairNodePtr;
  1601. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1602. return cmJsonErrorCode(h);
  1603. return cmJsonCreateRealArray(h,pairNodePtr,n,values);
  1604. }
  1605. cmJsRC_t cmJsonInsertPairStringArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const char** values )
  1606. {
  1607. assert( objectNodePtr->typeId == kObjectTId );
  1608. cmJsonNode_t* pairNodePtr;
  1609. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1610. return cmJsonErrorCode(h);
  1611. return cmJsonCreateStringArray(h,pairNodePtr,n,values);
  1612. }
  1613. cmJsRC_t cmJsonInsertPairBoolArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const bool* values )
  1614. {
  1615. assert( objectNodePtr->typeId == kObjectTId );
  1616. cmJsonNode_t* pairNodePtr;
  1617. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) == NULL )
  1618. return cmJsonErrorCode(h);
  1619. return cmJsonCreateBoolArray(h,pairNodePtr,n,values);
  1620. }
  1621. cmJsonNode_t* cmJsonInsertPairIntArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const int* values )
  1622. {
  1623. assert( objectNodePtr->typeId == kObjectTId );
  1624. cmJsonNode_t* pairNodePtr;
  1625. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) != NULL )
  1626. if( cmJsonCreateIntArray(h,pairNodePtr,n,values) != kOkJsRC )
  1627. return NULL;
  1628. return pairNodePtr;
  1629. }
  1630. cmJsonNode_t* cmJsonInsertPairRealArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const double* values )
  1631. {
  1632. assert( objectNodePtr->typeId == kObjectTId );
  1633. cmJsonNode_t* pairNodePtr;
  1634. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) != NULL )
  1635. if( cmJsonCreateRealArray(h,pairNodePtr,n,values) != kOkJsRC )
  1636. return NULL;
  1637. return pairNodePtr;
  1638. }
  1639. cmJsonNode_t* cmJsonInsertPairStringArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const char** values )
  1640. {
  1641. assert( objectNodePtr->typeId == kObjectTId );
  1642. cmJsonNode_t* pairNodePtr;
  1643. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) != NULL )
  1644. if( cmJsonCreateStringArray(h,pairNodePtr,n,values) != kOkJsRC )
  1645. return NULL;
  1646. return pairNodePtr;
  1647. }
  1648. cmJsonNode_t* cmJsonInsertPairBoolArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const bool* values )
  1649. {
  1650. assert( objectNodePtr->typeId == kObjectTId );
  1651. cmJsonNode_t* pairNodePtr;
  1652. if((pairNodePtr = cmJsonCreatePair(h,objectNodePtr,label)) != NULL )
  1653. if( cmJsonCreateBoolArray(h,pairNodePtr,n,values) != kOkJsRC )
  1654. return NULL;
  1655. return pairNodePtr;
  1656. }
  1657. cmJsRC_t _cmJsonInsertOrReplacePair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, unsigned newTypeId, const char* sv, int iv, double dv, cmJsonNode_t* nv, bool insertFl, cmJsonNode_t** retNodePtrPtr )
  1658. {
  1659. cmJsRC_t rc = kOkJsRC;
  1660. cmJs_t* p = _cmJsonHandleToPtr(h);
  1661. cmJsonNode_t* valNodePtr = NULL;
  1662. cmJsonNode_t* pairNodePtr = NULL;
  1663. assert( objectNodePtr->typeId == kObjectTId );
  1664. if( retNodePtrPtr != NULL )
  1665. *retNodePtrPtr = NULL;
  1666. // if a matching pair was not found ....
  1667. if(( valNodePtr = cmJsonFindValue(h,label,objectNodePtr,matchTypeMask)) == NULL )
  1668. {
  1669. // ... and insertion is not allowed then return error
  1670. if( insertFl == false )
  1671. return kNodeNotFoundJsRC;
  1672. // ... otherwise insert a new pair and return a pointer to it
  1673. pairNodePtr = cmJsonInsertPair(h,objectNodePtr,label,newTypeId,sv,iv,dv);
  1674. goto errLabel;
  1675. }
  1676. // ... otherwise a match was found to at least the pair label.
  1677. // If matchTypeMask was set to kInvalidTId then the type id
  1678. // of the found pair may not be the same as newTypeId. To handle
  1679. // this case we proceed by first deallocating all resources held
  1680. // by the found node and then proceeding by either creating
  1681. // deleting the found node and creating a replacement node
  1682. // (object,array,pair) or forcing the found node to a new
  1683. // type (int,real,true,false,string,null).
  1684. assert( valNodePtr != NULL);
  1685. pairNodePtr = valNodePtr->ownerPtr;
  1686. // release any resources held by the found node
  1687. switch( valNodePtr->typeId )
  1688. {
  1689. case kObjectTId:
  1690. case kArrayTId:
  1691. case kPairTId:
  1692. // remove the pair value node and replace it with a 'null' node.
  1693. if((rc =_cmJsonRemoveNode( p, valNodePtr, true, true )) != kOkJsRC )
  1694. goto errLabel;
  1695. break;
  1696. case kStringTId:
  1697. // deallocate string memory
  1698. _cmJsonSetString( p, valNodePtr, NULL, 0 );
  1699. break;
  1700. }
  1701. // relace the found node with the new node
  1702. switch( newTypeId )
  1703. {
  1704. case kObjectTId:
  1705. case kArrayTId:
  1706. case kPairTId:
  1707. {
  1708. cmJsonNode_t* newValueNodePtr = NULL;
  1709. // remove the current pair value ....
  1710. if((rc =_cmJsonRemoveNode( p, valNodePtr, true, false )) != kOkJsRC )
  1711. goto errLabel;
  1712. // new pair nodes should have the pair label in 'sv'
  1713. assert( newTypeId!=kPairTId || (newTypeId==kPairTId && sv != NULL ));
  1714. // if no new value was given or the new value is a pair then ...
  1715. if( nv == NULL || newTypeId == kPairTId )
  1716. {
  1717. // ... create a new blank array,obj or pair
  1718. if((rc = cmJsonCreate( h, pairNodePtr, newTypeId, sv, 0, 0, &newValueNodePtr )) != kOkJsRC )
  1719. goto errLabel;
  1720. }
  1721. // if the new value is a pair and no value node was given then set the
  1722. // new pairs value node to NULL
  1723. if( nv == NULL && newTypeId == kPairTId )
  1724. {
  1725. if((rc = _cmJsonCreateNull(p,newValueNodePtr,NULL)) != kOkJsRC )
  1726. goto errLabel;
  1727. }
  1728. // if a new value node was given
  1729. if( nv != NULL )
  1730. {
  1731. // the new child node should not already be linked to a parent
  1732. assert( nv->ownerPtr == NULL );
  1733. // if the new value is an obj or array then the new
  1734. // value node type id should be the same
  1735. assert( newTypeId==kPairTId || newTypeId==nv->typeId );
  1736. //
  1737. cmJsonNode_t* pp = newTypeId==kPairTId ? newValueNodePtr : pairNodePtr;
  1738. assert( pp->typeId == kPairTId );
  1739. // link in the child to the pair
  1740. if((rc = _cmJsonLinkInChild(p,pp,nv)) != kOkJsRC )
  1741. goto errLabel;
  1742. }
  1743. }
  1744. break;
  1745. // All cases below follow the same pattern:
  1746. // 1. Set the type id to the replacement value type id
  1747. // 2. Assign the value to the node.
  1748. // This sequence is safe because all resources were freed
  1749. // by the earlier switch.
  1750. case kStringTId:
  1751. valNodePtr->typeId = kStringTId;
  1752. _cmJsonSetString( p, valNodePtr, sv, strlen(sv) );
  1753. break;
  1754. case kIntTId:
  1755. valNodePtr->typeId =kIntTId;
  1756. valNodePtr->u.intVal = iv;
  1757. break;
  1758. case kRealTId:
  1759. valNodePtr->typeId = kRealTId;
  1760. valNodePtr->u.realVal = dv;
  1761. break;
  1762. case kTrueTId:
  1763. valNodePtr->typeId = kTrueTId;
  1764. valNodePtr->u.boolVal = true;
  1765. break;
  1766. case kFalseTId:
  1767. valNodePtr->typeId = kFalseTId;
  1768. valNodePtr->u.boolVal = false;
  1769. break;
  1770. case kNullTId:
  1771. valNodePtr->typeId = kNullTId;
  1772. break;
  1773. default:
  1774. { assert(0); }
  1775. }
  1776. errLabel:
  1777. if( rc == kOkJsRC )
  1778. if( retNodePtrPtr != NULL )
  1779. *retNodePtrPtr = pairNodePtr;
  1780. return rc;
  1781. }
  1782. cmJsonNode_t* cmJsonInsertOrReplacePair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, unsigned typeId, const char* sv, int iv, double dv, cmJsonNode_t* nv )
  1783. {
  1784. cmJsonNode_t* retNodePtr = NULL;
  1785. _cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,typeId,sv,iv,dv,nv,true,&retNodePtr );
  1786. return retNodePtr;
  1787. }
  1788. cmJsonNode_t* cmJsonInsertOrReplacePairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newObjNodePtr )
  1789. {
  1790. cmJsonNode_t* pairPtr;
  1791. if((pairPtr = cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kObjectTId,NULL,0,0,newObjNodePtr)) == NULL )
  1792. return NULL;
  1793. return pairPtr->u.childPtr->siblingPtr;
  1794. }
  1795. cmJsonNode_t* cmJsonInsertOrReplacePairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newArrayNodePtr )
  1796. {
  1797. cmJsonNode_t* pairPtr;
  1798. if((pairPtr = cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kArrayTId,NULL,0,0,newArrayNodePtr)) == NULL )
  1799. return NULL;
  1800. return pairPtr->u.childPtr->siblingPtr;
  1801. }
  1802. cmJsonNode_t* cmJsonInsertOrReplacePairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* newPairLabel, cmJsonNode_t* newPairValNodePtr )
  1803. {
  1804. cmJsonNode_t* pairPtr;
  1805. if((pairPtr = cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kPairTId,newPairLabel,0,0,newPairValNodePtr)) == NULL )
  1806. return NULL;
  1807. return pairPtr->u.childPtr->siblingPtr;
  1808. }
  1809. cmJsRC_t cmJsonInsertOrReplacePairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, int intVal )
  1810. { return cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kIntTId,NULL,intVal,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1811. cmJsRC_t cmJsonInsertOrReplacePairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, double realVal )
  1812. { return cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kRealTId,NULL,0,realVal,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1813. cmJsRC_t cmJsonInsertOrReplacePairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* stringVal )
  1814. { return cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kStringTId,stringVal,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1815. cmJsRC_t cmJsonInsertOrReplacePairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, bool boolVal )
  1816. { return cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,boolVal ? kTrueTId : kFalseTId,NULL,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1817. cmJsRC_t cmJsonInsertOrReplacePairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask )
  1818. { return cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,kNullTId,NULL,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1819. cmJsonNode_t* cmJsonReplacePair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, unsigned newTypeId, const char* sv, int iv, double dv, cmJsonNode_t* nv )
  1820. {
  1821. cmJsonNode_t* retNodePtr = NULL;
  1822. _cmJsonInsertOrReplacePair(h,objectNodePtr,label,matchTypeMask,newTypeId,sv,iv,dv,nv,false,&retNodePtr );
  1823. return retNodePtr;
  1824. }
  1825. cmJsonNode_t* cmJsonReplacePairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newPairNodePtr )
  1826. {
  1827. cmJsonNode_t* pairPtr;
  1828. if((pairPtr = cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kObjectTId,NULL,0,0,newPairNodePtr)) == NULL )
  1829. return NULL;
  1830. return pairPtr->u.childPtr->siblingPtr;
  1831. }
  1832. cmJsonNode_t* cmJsonReplacePairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newArrayNodePtr )
  1833. {
  1834. cmJsonNode_t* pairPtr;
  1835. if((pairPtr = cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kArrayTId,NULL,0,0,newArrayNodePtr)) == NULL )
  1836. return NULL;
  1837. return pairPtr->u.childPtr->siblingPtr;
  1838. }
  1839. cmJsonNode_t* cmJsonReplacePairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* newPairLabel, cmJsonNode_t* newPairValNodePtr )
  1840. {
  1841. cmJsonNode_t* pairPtr;
  1842. if((pairPtr = cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kPairTId,newPairLabel,0,0,newPairValNodePtr)) == NULL )
  1843. return NULL;
  1844. return pairPtr->u.childPtr->siblingPtr;
  1845. }
  1846. cmJsRC_t cmJsonReplacePairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, int intVal )
  1847. { return cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kIntTId,NULL,intVal,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1848. cmJsRC_t cmJsonReplacePairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, double realVal )
  1849. { return cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kRealTId,NULL,0,realVal,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1850. cmJsRC_t cmJsonReplacePairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* stringVal )
  1851. { return cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kStringTId,stringVal,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1852. cmJsRC_t cmJsonReplacePairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, bool boolVal )
  1853. { return cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,boolVal ? kTrueTId : kFalseTId,NULL,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1854. cmJsRC_t cmJsonReplacePairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask )
  1855. { return cmJsonReplacePair(h,objectNodePtr,label,matchTypeMask,kNullTId,NULL,0,0,NULL) == NULL ? cmJsonErrorCode(h) : kOkJsRC; }
  1856. cmJsRC_t cmJsonVInsertPairs( cmJsonH_t h, cmJsonNode_t* objNodePtr, va_list vl )
  1857. {
  1858. cmJsRC_t rc = kOkJsRC;
  1859. assert( objNodePtr->typeId == kObjectTId );
  1860. const char* label;
  1861. while( ((label = va_arg(vl,const char*)) != NULL) && (rc == kOkJsRC) )
  1862. {
  1863. unsigned sel = va_arg(vl,unsigned);
  1864. switch( sel )
  1865. {
  1866. case kObjectTId:
  1867. if( cmJsonInsertPairObject(h,objNodePtr,label) == NULL )
  1868. rc = cmJsonErrorCode(h);
  1869. break;
  1870. case kArrayTId:
  1871. if( cmJsonInsertPairArray(h,objNodePtr,label) == NULL )
  1872. rc = cmJsonErrorCode(h);
  1873. break;
  1874. case kPairTId:
  1875. if( cmJsonInsertPairPair(h,objNodePtr,label, va_arg(vl,const char*)) == NULL )
  1876. rc = cmJsonErrorCode(h);
  1877. break;
  1878. case kIntTId:
  1879. rc = cmJsonInsertPairInt(h,objNodePtr,label, va_arg(vl,int) );
  1880. break;
  1881. case kRealTId:
  1882. rc = cmJsonInsertPairReal(h,objNodePtr,label, va_arg(vl,double) );
  1883. break;
  1884. case kStringTId:
  1885. rc = cmJsonInsertPairString(h,objNodePtr,label, va_arg(vl,const char *) );
  1886. break;
  1887. case kTrueTId:
  1888. case kFalseTId:
  1889. case kBoolTId:
  1890. rc = cmJsonInsertPairBool(h,objNodePtr,label, va_arg(vl,int) );
  1891. break;
  1892. case kNullTId:
  1893. rc = cmJsonInsertPairNull(h,objNodePtr,label );
  1894. break;
  1895. default:
  1896. // missing terminating NULL on the var args list???
  1897. assert(0);
  1898. break;
  1899. }
  1900. }
  1901. return rc;
  1902. }
  1903. cmJsRC_t cmJsonInsertPairs( cmJsonH_t h, cmJsonNode_t* objectNodePtr, ... )
  1904. {
  1905. va_list vl;
  1906. va_start(vl,objectNodePtr);
  1907. cmJsRC_t rc = cmJsonVInsertPairs(h,objectNodePtr,vl);
  1908. va_end(vl);
  1909. return rc;
  1910. }
  1911. cmJsonNode_t* cmJsonVCreateFilledObject( cmJsonH_t h, cmJsonNode_t* parentPtr, va_list vl )
  1912. {
  1913. cmJsonNode_t* np;
  1914. if((np = cmJsonCreateObject(h,parentPtr)) == NULL)
  1915. return NULL;
  1916. if( cmJsonVInsertPairs(h,np,vl) != kOkJsRC )
  1917. {
  1918. cmJsonRemoveNode(h,np,true);
  1919. return NULL;
  1920. }
  1921. return np;
  1922. }
  1923. cmJsonNode_t* cmJsonCreateFilledObject( cmJsonH_t h, cmJsonNode_t* parentPtr, ... )
  1924. {
  1925. va_list vl;
  1926. va_start(vl,parentPtr);
  1927. cmJsonNode_t* np = cmJsonVCreateFilledObject(h,parentPtr,vl);
  1928. va_end(vl);
  1929. return np;
  1930. }
  1931. void _cmJsonFreeNode( cmJs_t* p, cmJsonNode_t* np )
  1932. {
  1933. switch( np->typeId )
  1934. {
  1935. case kObjectTId:
  1936. case kPairTId:
  1937. case kArrayTId:
  1938. {
  1939. cmJsonNode_t* cnp = np->u.childPtr;
  1940. while( cnp != NULL )
  1941. {
  1942. cmJsonNode_t* nnp = cnp->siblingPtr;
  1943. _cmJsonFreeNode(p,cnp);
  1944. cnp = nnp;
  1945. }
  1946. }
  1947. break;
  1948. case kStringTId:
  1949. if( np->u.stringVal != NULL )
  1950. cmLHeapFree(p->heapH,np->u.stringVal);
  1951. break;
  1952. }
  1953. cmLHeapFree(p->heapH,np);
  1954. }
  1955. cmJsRC_t _cmJsonRemoveNode( cmJs_t* p, cmJsonNode_t* np, bool freeFl, bool balancePairsFl )
  1956. {
  1957. if(np == NULL )
  1958. return kOkJsRC;
  1959. cmJsonNode_t* parentPtr = np->ownerPtr;
  1960. // if np is the root ...
  1961. if( np == p->rootPtr )
  1962. {
  1963. // ... we only need to set the root to null to remove the node.
  1964. p->rootPtr = NULL;
  1965. }
  1966. else
  1967. {
  1968. if( parentPtr != NULL )
  1969. {
  1970. // get the parents first child
  1971. cmJsonNode_t* cnp = parentPtr->u.childPtr;
  1972. // if np is the first child then make the second child the first child
  1973. if( cnp == np )
  1974. {
  1975. if( parentPtr->typeId == kPairTId )
  1976. return _cmJsonError( p, kCannotRemoveLabelJsRC, "Cannot remove pair label nodes because this would invalidate the tree structure.");
  1977. parentPtr->u.childPtr = cnp->siblingPtr;
  1978. }
  1979. else
  1980. {
  1981. // otherwise unlink it from the child chain
  1982. while( cnp != NULL )
  1983. {
  1984. if( cnp->siblingPtr == np )
  1985. {
  1986. cnp->siblingPtr = np->siblingPtr;
  1987. // if the parent is a pair then the removed node is a
  1988. // 'pair value' which must be replaced with a null node in order
  1989. // to maintain a valid tree.
  1990. if( (parentPtr->typeId == kPairTId) && balancePairsFl)
  1991. _cmJsonCreateNull( p, parentPtr, NULL );
  1992. break;
  1993. }
  1994. cnp = cnp->siblingPtr;
  1995. }
  1996. assert( cnp != NULL );
  1997. }
  1998. }
  1999. }
  2000. // if the memory assoc'd with the removed node should be released
  2001. if( freeFl )
  2002. {
  2003. _cmJsonFreeNode(p,np);
  2004. /*
  2005. if( np->typeId == kStringTId )
  2006. {
  2007. cmLHeapFree(p->heapH,np->u.stringVal);
  2008. np->u.stringVal = NULL;
  2009. }
  2010. cmLHeapFree(p->heapH,np);
  2011. */
  2012. }
  2013. return kOkJsRC;
  2014. }
  2015. cmJsRC_t cmJsonRemoveNode( cmJsonH_t h, cmJsonNode_t* np, bool freeFl )
  2016. {
  2017. cmJs_t* p = _cmJsonHandleToPtr(h);
  2018. return _cmJsonRemoveNode( p, np, freeFl, true );
  2019. }
  2020. cmJsRC_t _cmJsonValidateErr( cmJs_t* p, const char* text )
  2021. {
  2022. if( p != NULL )
  2023. return _cmJsonSyntaxError(p,text);
  2024. return kValidateFailJsRC;
  2025. }
  2026. // 'p' is optional. If 'p' is set to NULL the function will return kValidFailJsRC if the
  2027. // tree rooted at 'np' is invalid and will not print an error message.
  2028. cmJsRC_t _cmJsonValidateNode( cmJs_t* p, const cmJsonNode_t* np, const cmJsonNode_t* parentPtr )
  2029. {
  2030. cmJsRC_t rc = kOkJsRC;
  2031. if( parentPtr != np->ownerPtr )
  2032. return _cmJsonValidateErr(p,"A child->parent link does not agree with a parent->child link.");
  2033. if( parentPtr == NULL )
  2034. {
  2035. if( np->typeId != kArrayTId && np->typeId != kObjectTId )
  2036. return _cmJsonValidateErr(p,"Only 'array' and 'object' nodes may be the root element.");
  2037. }
  2038. else
  2039. {
  2040. if( parentPtr->typeId != kArrayTId && parentPtr->typeId != kObjectTId && parentPtr->typeId != kPairTId )
  2041. return _cmJsonValidateErr(p,"Parent nodes must be either 'object','array' or 'pair' nodes.");
  2042. }
  2043. switch( np->typeId )
  2044. {
  2045. case kPairTId:
  2046. if( cmJsonChildCount(np) != 2 )
  2047. return _cmJsonValidateErr(p,"'pair' nodes must have exactly two children.");
  2048. if( np->u.childPtr->typeId != kStringTId )
  2049. return _cmJsonValidateErr(p,"The first child of 'pair' nodes must be a 'string' node.");
  2050. // fall through
  2051. case kObjectTId:
  2052. case kArrayTId:
  2053. {
  2054. // validate each child node
  2055. cmJsonNode_t* cnp = np->u.childPtr;
  2056. while(cnp != NULL)
  2057. {
  2058. if( cnp->ownerPtr != np )
  2059. return _cmJsonValidateErr(p,"A parent->child pointer was not validated with a child->parent pointer.");
  2060. if( np->typeId == kObjectTId && cnp->typeId != kPairTId )
  2061. return _cmJsonValidateErr(p,"All 'object' child nodes must be 'pair' nodes.");
  2062. if((rc = _cmJsonValidateNode(p,cnp,np)) != kOkJsRC )
  2063. return rc;
  2064. cnp = cnp->siblingPtr;
  2065. }
  2066. }
  2067. break;
  2068. case kStringTId:
  2069. case kIntTId:
  2070. case kRealTId:
  2071. case kNullTId:
  2072. case kTrueTId:
  2073. case kFalseTId:
  2074. default:
  2075. break;
  2076. }
  2077. return rc;
  2078. }
  2079. cmJsRC_t cmJsonValidateTree( cmJsonH_t h )
  2080. {
  2081. cmJs_t* p = _cmJsonHandleToPtr(h);
  2082. return _cmJsonValidateNode(p,p->rootPtr,NULL);
  2083. }
  2084. cmJsRC_t cmJsonValidate( const cmJsonNode_t* np )
  2085. { return _cmJsonValidateNode(NULL,np,np->ownerPtr); }
  2086. cmJsonNode_t* _cmJsonDuplicateNode( cmJs_t* p, const cmJsonNode_t* np, cmJsonNode_t* parentPtr )
  2087. {
  2088. cmJsonNode_t* newParentPtr = NULL;
  2089. cmJsonNode_t* newNodePtr = NULL;
  2090. cmJsRC_t rc = kOkJsRC;
  2091. switch( np->typeId )
  2092. {
  2093. case kObjectTId:
  2094. case kArrayTId:
  2095. rc = _cmJsonCreateNode(p,parentPtr,np->typeId,&newParentPtr);
  2096. break;
  2097. case kPairTId:
  2098. rc = _cmJsonCreatePair(p,parentPtr,np->u.childPtr->u.stringVal,&newParentPtr);
  2099. break;
  2100. case kIntTId:
  2101. rc = _cmJsonCreateInt(p,parentPtr,np->u.intVal,&newNodePtr);
  2102. break;
  2103. case kRealTId:
  2104. rc = _cmJsonCreateReal(p,parentPtr,np->u.realVal,&newNodePtr);
  2105. break;
  2106. case kStringTId:
  2107. rc = _cmJsonCreateString(p,parentPtr,np->u.stringVal,strlen(np->u.stringVal),&newNodePtr);
  2108. break;
  2109. case kTrueTId:
  2110. case kFalseTId:
  2111. rc = _cmJsonCreateBool(p,parentPtr,np->u.boolVal,&newNodePtr);
  2112. break;
  2113. case kNullTId:
  2114. rc = _cmJsonCreateNull(p,parentPtr,&newNodePtr);
  2115. }
  2116. if( rc != kOkJsRC )
  2117. return NULL;
  2118. if( newParentPtr != NULL )
  2119. {
  2120. newNodePtr = newParentPtr;
  2121. cmJsonNode_t* cnp = np->u.childPtr;
  2122. if(np->typeId == kPairTId)
  2123. cnp = np->u.childPtr->siblingPtr;
  2124. while( cnp != NULL )
  2125. {
  2126. if( _cmJsonDuplicateNode(p,cnp,newParentPtr) != kOkJsRC )
  2127. return NULL;
  2128. cnp = cnp->siblingPtr;
  2129. }
  2130. }
  2131. return newNodePtr;
  2132. }
  2133. cmJsonNode_t* cmJsonDuplicateNode( cmJsonH_t h, const cmJsonNode_t* np, cmJsonNode_t* parentPtr )
  2134. {
  2135. cmJs_t* p = _cmJsonHandleToPtr(h);
  2136. assert( _cmJsonValidateNode(p,np,NULL) == kOkJsRC );
  2137. return _cmJsonDuplicateNode(p,np,parentPtr);
  2138. }
  2139. cmJsRC_t cmJsonMergeObjectNodes( cmJsonH_t h, cmJsonNode_t* dstObjNodePtr, const cmJsonNode_t* srcObjNodePtr )
  2140. {
  2141. assert( dstObjNodePtr!=NULL && dstObjNodePtr->typeId == kObjectTId );
  2142. assert( srcObjNodePtr!=NULL && srcObjNodePtr->typeId == kObjectTId );
  2143. cmJsRC_t rc = kOkJsRC;
  2144. cmJs_t* p = _cmJsonHandleToPtr(h);
  2145. cmJsonNode_t* cnp = NULL;
  2146. const cmJsonNode_t* snp = srcObjNodePtr->u.childPtr;
  2147. while( snp!=NULL && rc==kOkJsRC )
  2148. {
  2149. cmJsonNode_t* dnp;
  2150. assert( snp->typeId == kPairTId );
  2151. // if the src pair was not found in the dst object ...
  2152. if((rc = _cmJsonFindMemberValue(dstObjNodePtr, cmJsonPairLabel(snp), snp->u.childPtr->siblingPtr->typeId, &dnp )) != kOkJsRC )
  2153. {
  2154. cmJsonNode_t* newPairNodePtr;
  2155. // the only acceptable error is kNodeNotFoundJsRC
  2156. // (in particular we reject kNodeCannotCvtJsRC to avoid duplicating
  2157. // pairs with the same name but different types)
  2158. if( rc != kNodeNotFoundJsRC )
  2159. goto errLabel;
  2160. // create the new pair and attach it to the dst obj node
  2161. if((rc = _cmJsonCreatePair(p,dstObjNodePtr,cmJsonPairLabel(snp),&newPairNodePtr)) != kOkJsRC )
  2162. goto errLabel;
  2163. // duplicate the src pair value node and attcmh it to the new dst node
  2164. if( _cmJsonDuplicateNode(p,snp->u.childPtr->siblingPtr,newPairNodePtr) == NULL )
  2165. rc = p->rc;
  2166. // set kTempJsFl on the new node to use possible cleanup on error later
  2167. newPairNodePtr->typeId = cmSetFlag(newPairNodePtr->typeId,kTempJsFl);
  2168. }
  2169. snp = snp->siblingPtr;
  2170. }
  2171. errLabel:
  2172. // for each dst obj pair
  2173. cnp = dstObjNodePtr->u.childPtr;
  2174. while( cnp != NULL)
  2175. {
  2176. // if this child is a new node
  2177. if( cmIsFlag(cnp->typeId,kTempJsFl) )
  2178. {
  2179. // clear the temp fl
  2180. cnp->typeId = cmClrFlag(cnp->typeId,kTempJsFl);
  2181. // if there was an error remove all new pairs
  2182. if( rc != kOkJsRC )
  2183. cmJsonRemoveNode(h,cnp,true);
  2184. }
  2185. cnp = cnp->siblingPtr;
  2186. }
  2187. return rc;
  2188. }
  2189. void _cmJsonSerialCopy( cmJsSerial_t* rp, const void* sp, unsigned sn )
  2190. {
  2191. assert( rp->nextPtr + sn <= rp->endPtr );
  2192. memcpy(rp->nextPtr,sp,sn);
  2193. rp->nextPtr += sn;
  2194. }
  2195. cmJsRC_t _cmJsonSerializeNode( const cmJsonNode_t* np, cmJsSerial_t* rp )
  2196. {
  2197. cmJsRC_t rc = kOkJsRC;
  2198. // on the first pass rp->basePtr will be NULL so collect size information
  2199. // on the second pass rp->basePtr will be set so copy out data
  2200. // write the type id of this node
  2201. if( rp->basePtr != NULL )
  2202. _cmJsonSerialCopy(rp,&np->typeId,sizeof(np->typeId));
  2203. else
  2204. rp->hdr.byteCnt += sizeof(np->typeId);
  2205. rp->hdr.nodeCnt++;
  2206. switch( np->typeId )
  2207. {
  2208. // write the child count
  2209. case kObjectTId:
  2210. case kArrayTId:
  2211. if( rp->basePtr == NULL )
  2212. rp->hdr.byteCnt += sizeof(unsigned);
  2213. else
  2214. {
  2215. unsigned n = cmJsonChildCount( np );
  2216. _cmJsonSerialCopy(rp,&n,sizeof(unsigned));
  2217. }
  2218. // fall through
  2219. case kPairTId:
  2220. {
  2221. cmJsonNode_t* cnp = np->u.childPtr;
  2222. while(cnp != NULL )
  2223. {
  2224. _cmJsonSerializeNode(cnp,rp);
  2225. cnp = cnp->siblingPtr;
  2226. }
  2227. }
  2228. break;
  2229. case kStringTId:
  2230. // write the string contents
  2231. if( rp->basePtr == NULL )
  2232. rp->hdr.byteCnt += strlen(np->u.stringVal) + 1;
  2233. else
  2234. _cmJsonSerialCopy( rp, np->u.stringVal, strlen(np->u.stringVal)+1 );
  2235. break;
  2236. case kIntTId:
  2237. // write the int value
  2238. if( rp->basePtr == NULL )
  2239. rp->hdr.byteCnt += sizeof(np->u.intVal);
  2240. else
  2241. _cmJsonSerialCopy(rp,&np->u.intVal,sizeof(np->u.intVal));
  2242. break;
  2243. case kRealTId:
  2244. // write the real value
  2245. if( rp->basePtr == NULL )
  2246. rp->hdr.byteCnt += sizeof(np->u.realVal);
  2247. else
  2248. _cmJsonSerialCopy(rp, &np->u.realVal, sizeof(np->u.realVal));
  2249. break;
  2250. }
  2251. return rc;
  2252. }
  2253. unsigned cmJsonSerialByteCount( const cmJsonNode_t* np )
  2254. {
  2255. cmJsRC_t rc;
  2256. cmJsSerial_t vr;
  2257. memset(&vr,0,sizeof(vr));
  2258. // make a first pass to determine the size of the buffer
  2259. if((rc = _cmJsonSerializeNode(np,&vr)) != kOkJsRC )
  2260. return rc;
  2261. // increment the buffer size to include the buffer header
  2262. return (4*sizeof(unsigned)) + vr.hdr.byteCnt;
  2263. }
  2264. cmJsRC_t cmJsonSerialize( const cmJsonNode_t* np, void* buf, unsigned bufByteCnt )
  2265. {
  2266. cmJsRC_t rc = kOkJsRC;
  2267. cmJsSerial_t vr;
  2268. memset(&vr,0,sizeof(vr));
  2269. // setup the serial buffer
  2270. vr.hdr.id = 'json';
  2271. vr.hdr.byteCnt = bufByteCnt - (2*sizeof(unsigned));
  2272. vr.hdr.version = 0;
  2273. vr.basePtr = buf;
  2274. vr.nextPtr = vr.basePtr;
  2275. vr.endPtr = vr.basePtr + bufByteCnt;
  2276. // write the header recd
  2277. _cmJsonSerialCopy(&vr, &vr.hdr.id, sizeof(unsigned));
  2278. _cmJsonSerialCopy(&vr, &vr.hdr.byteCnt, sizeof(unsigned));
  2279. _cmJsonSerialCopy(&vr, &vr.hdr.nodeCnt, sizeof(unsigned));
  2280. _cmJsonSerialCopy(&vr, &vr.hdr.version, sizeof(unsigned));
  2281. // copy the node data into the serial buffer
  2282. if((rc = _cmJsonSerializeNode(np,&vr)) != kOkJsRC )
  2283. return rc;
  2284. vr.basePtr = buf;
  2285. vr.nextPtr = vr.basePtr;
  2286. _cmJsonSerialCopy(&vr, &vr.hdr.id, sizeof(unsigned));
  2287. _cmJsonSerialCopy(&vr, &vr.hdr.byteCnt, sizeof(unsigned));
  2288. _cmJsonSerialCopy(&vr, &vr.hdr.nodeCnt, sizeof(unsigned));
  2289. return rc;
  2290. }
  2291. cmJsRC_t cmJsonSerializeTree( cmJsonH_t h, const cmJsonNode_t* np, void** bufPtrPtr, unsigned* bufByteCntPtr)
  2292. {
  2293. cmJsRC_t rc;
  2294. cmJsSerial_t vr;
  2295. memset(&vr,0,sizeof(vr));
  2296. cmJs_t* p = _cmJsonHandleToPtr(h);
  2297. assert( bufPtrPtr != NULL && bufByteCntPtr != NULL );
  2298. *bufPtrPtr = NULL;
  2299. *bufByteCntPtr = 0;
  2300. if( np == NULL )
  2301. np = p->rootPtr;
  2302. // validate the tree
  2303. if((rc = _cmJsonValidateNode(p,np,np->ownerPtr)) != kOkJsRC )
  2304. return rc;
  2305. // increment the buffer size to include the buffer header
  2306. p->serialByteCnt = cmJsonSerialByteCount(np);
  2307. // allocate the serial buffer memory
  2308. p->serialBufPtr = cmMemResize( char, p->serialBufPtr, p->serialByteCnt );
  2309. // serialize the tree
  2310. if((rc = cmJsonSerialize(np, p->serialBufPtr, p->serialByteCnt )) != kOkJsRC )
  2311. return rc;
  2312. *bufPtrPtr = p->serialBufPtr;
  2313. *bufByteCntPtr = p->serialByteCnt;
  2314. return rc;
  2315. }
  2316. const void* _cmJsonDeserialAdv( cmJsDeserial_t* rp, unsigned n )
  2317. {
  2318. const void* vp = rp->nextPtr;
  2319. rp->nextPtr += n;
  2320. assert(rp->nextPtr <= rp->endPtr);
  2321. assert(rp->nodeIdx <= rp->nodeCnt);
  2322. return vp;
  2323. }
  2324. int _cmJsonDeserialInt( cmJsDeserial_t* rp )
  2325. { return *(const int*)_cmJsonDeserialAdv(rp,sizeof(int)); }
  2326. unsigned _cmJsonDeserialUint( cmJsDeserial_t* rp )
  2327. { return *(const unsigned*)_cmJsonDeserialAdv(rp,sizeof(unsigned)); }
  2328. double _cmJsonDeserialReal( cmJsDeserial_t* rp )
  2329. { return *(const double*)_cmJsonDeserialAdv(rp,sizeof(double)); }
  2330. cmJsRC_t _cmJsonDeserializeNode( cmJs_t* p, cmJsonNode_t* parentPtr, cmJsDeserial_t* rp )
  2331. {
  2332. cmJsRC_t rc = kOkJsRC;
  2333. unsigned typeId = _cmJsonDeserialUint(rp);
  2334. unsigned childCnt = 0;
  2335. cmJsonNode_t* newParentPtr = NULL;
  2336. rp->nodeIdx++;
  2337. switch( typeId )
  2338. {
  2339. case kPairTId:
  2340. rc = _cmJsonCreateNode(p,parentPtr,typeId,&newParentPtr);
  2341. childCnt = 2;
  2342. break;
  2343. case kObjectTId:
  2344. case kArrayTId:
  2345. rc = _cmJsonCreateNode(p,parentPtr,typeId,&newParentPtr);
  2346. childCnt = _cmJsonDeserialUint(rp);
  2347. break;
  2348. case kStringTId:
  2349. {
  2350. unsigned sn = strlen(rp->nextPtr);
  2351. rc = _cmJsonCreateString( p, parentPtr, rp->nextPtr, sn,NULL);
  2352. _cmJsonDeserialAdv(rp,sn+1);
  2353. }
  2354. break;
  2355. case kIntTId:
  2356. {
  2357. int v = _cmJsonDeserialInt(rp);
  2358. rc = _cmJsonCreateInt( p, parentPtr, v, NULL );
  2359. }
  2360. break;
  2361. case kRealTId:
  2362. {
  2363. double v = _cmJsonDeserialReal(rp);
  2364. rc = _cmJsonCreateReal( p, parentPtr, v, NULL );
  2365. }
  2366. break;
  2367. case kNullTId:
  2368. rc = _cmJsonCreateNull( p, parentPtr, NULL );
  2369. break;
  2370. case kTrueTId:
  2371. rc = _cmJsonCreateBool( p, parentPtr, true, NULL );
  2372. break;
  2373. case kFalseTId:
  2374. rc = _cmJsonCreateBool( p, parentPtr, false, NULL );
  2375. break;
  2376. default:
  2377. assert(0);
  2378. break;
  2379. }
  2380. if( rc != kOkJsRC )
  2381. return rc;
  2382. // if the current node is a parent
  2383. if( childCnt > 0 )
  2384. {
  2385. unsigned i;
  2386. assert( newParentPtr != NULL );
  2387. for(i=0; i<childCnt; ++i)
  2388. if((rc= _cmJsonDeserializeNode( p, newParentPtr, rp )) != kOkJsRC )
  2389. return rc;
  2390. }
  2391. return rc;
  2392. }
  2393. cmJsRC_t _cmJsonDeserialize( cmJs_t* p, const void* vbuf, cmJsonNode_t* altRootPtr )
  2394. {
  2395. cmJsDeserial_t r;
  2396. cmJsonNode_t* rootPtr = altRootPtr == NULL ? p->rootPtr : altRootPtr;
  2397. const char* buf = (const char*)vbuf;
  2398. memset(&r,0,sizeof(r));
  2399. r.nextPtr = buf;
  2400. r.endPtr = buf + (4*sizeof(unsigned)); // the buf must at least contain a header
  2401. // read the buffer header
  2402. unsigned hdrId = _cmJsonDeserialUint(&r);
  2403. unsigned byteCnt = _cmJsonDeserialUint(&r);
  2404. r.nodeCnt = _cmJsonDeserialUint(&r);
  2405. /*unsigned version =*/ _cmJsonDeserialUint(&r);
  2406. if( hdrId != 'json' )
  2407. return _cmJsonError(p,kSerialErrJsRC,"The buffer does not have the correct header.");
  2408. if( byteCnt < (4*sizeof(unsigned)) )
  2409. return _cmJsonError(p,kSerialErrJsRC,"The buffer is too small to be contain any information.");
  2410. // change the buffer end pointer to the correct size based
  2411. // on the the byte count stored in the buffer
  2412. r.endPtr = buf + byteCnt + (2*sizeof(unsigned));
  2413. return _cmJsonDeserializeNode(p, rootPtr, &r );
  2414. }
  2415. cmJsRC_t cmJsonDeserialize( cmJsonH_t h, const void* bufPtr, cmJsonNode_t* altRootPtr )
  2416. {
  2417. cmJs_t* p = _cmJsonHandleToPtr(h);
  2418. return _cmJsonDeserialize(p,bufPtr,altRootPtr);
  2419. }
  2420. cmJsRC_t cmJsonLeafToString( const cmJsonNode_t* np, cmChar_t* buf, unsigned bufCharCnt )
  2421. {
  2422. const char* cp = NULL;
  2423. unsigned n = 0;
  2424. assert( buf!=NULL && bufCharCnt > 0 );
  2425. switch(np->typeId & kMaskTId )
  2426. {
  2427. case kStringTId:
  2428. cp = np->u.stringVal==NULL ? "" : np->u.stringVal;
  2429. break;
  2430. case kNullTId:
  2431. cp = "null";
  2432. break;
  2433. case kTrueTId:
  2434. cp = "true";
  2435. break;
  2436. case kFalseTId:
  2437. cp = "false";
  2438. break;
  2439. case kIntTId:
  2440. n = snprintf(buf,bufCharCnt,"%i",np->u.intVal)+1;
  2441. break;
  2442. case kRealTId:
  2443. n = snprintf(buf,bufCharCnt,"%f",np->u.realVal)+1;
  2444. break;
  2445. default:
  2446. assert(0);
  2447. return kInvalidNodeTypeJsRC;
  2448. }
  2449. if( cp != NULL )
  2450. {
  2451. n = strlen(cp)+1;
  2452. if( bufCharCnt < n )
  2453. n = bufCharCnt;
  2454. strncpy(buf,cp,n);
  2455. /*
  2456. n = strlen(np->u.stringVal)+1;
  2457. if( bufCharCnt < n )
  2458. n = bufCharCnt;
  2459. strncpy(buf,np->u.stringVal,n);
  2460. */
  2461. }
  2462. buf[bufCharCnt-1]=0;
  2463. assert( n>0 && n < bufCharCnt );
  2464. return n == bufCharCnt ? kBufTooSmallJsRC : kOkJsRC ;
  2465. }
  2466. cmJsRC_t _cmJsonRptCsvTokErr( cmJs_t* p, unsigned lineNo, cmLexH lexH, const char* iFn )
  2467. {
  2468. unsigned n = cmMin(31,cmLexTokenCharCount(lexH));
  2469. char b[n+1];
  2470. strncpy(b,cmLexTokenText(lexH),n);
  2471. b[n]=0;
  2472. return _cmJsonError( p, kCsvErrJsRC, "Unexpected token '%s' during CSV parse on line %i of '%s'.",b,cmLexCurrentLineNumber(lexH),cmStringNullGuard(iFn));
  2473. }
  2474. cmJsRC_t _cmJsonRptCsvTypeErr( cmJs_t* p, unsigned lineNo, cmLexH lexH, const char* iFn, const char* actualTypeStr, unsigned expTypeId )
  2475. {
  2476. unsigned n = cmMin(31,cmLexTokenCharCount(lexH));
  2477. char b[n+1];
  2478. strncpy(b,cmLexTokenText(lexH),n);
  2479. b[n]=0;
  2480. return _cmJsonError( p, kCsvErrJsRC, "Unexpected token '%s' during CSV parse on line %i of '%s'.\nExpected type:%s actual type:%s",b,cmLexCurrentLineNumber(lexH),cmStringNullGuard(iFn),_cmJsonNodeTypeIdToLabel(expTypeId),actualTypeStr);
  2481. }
  2482. cmJsRC_t cmJsonFromCSV( cmJsonH_t h, const char* iFn, cmJsonNode_t* parentNodePtr, cmJsonNode_t** arrayNodePtrPtr )
  2483. {
  2484. enum
  2485. {
  2486. kCommaTokId = kUserLexTId+1,
  2487. kIntTokId,
  2488. kRealTokId,
  2489. kTrueTokId,
  2490. kFalseTokId,
  2491. kStringTokId,
  2492. kBoolTokId
  2493. };
  2494. typedef struct field_str
  2495. {
  2496. char* fieldLabel;
  2497. unsigned typeId;
  2498. struct field_str* linkPtr;
  2499. } field_t;
  2500. cmJsRC_t rc = kOkJsRC;
  2501. cmJs_t* p = _cmJsonHandleToPtr(h);
  2502. cmLexH lexH = cmLexInit( NULL, 0, 0, p->err.rpt );
  2503. field_t* fieldList = NULL;
  2504. cmJsonNode_t* arrayNodePtr = NULL;
  2505. cmJsonNode_t* objNodePtr = NULL;
  2506. unsigned lineNo = 0;
  2507. field_t* fieldPtr = NULL;
  2508. field_t* lp = NULL;
  2509. unsigned tokId;
  2510. unsigned fieldIdx = 0;
  2511. // validate the init state of the lexer
  2512. if( cmLexIsValid(lexH) == false )
  2513. {
  2514. rc = _cmJsonError( p, kLexErrJsRC, "Lexer initialization failed on CSV parse of '%s'.",cmStringNullGuard(iFn));
  2515. goto errLabel;
  2516. }
  2517. // register CSV specific tokens
  2518. cmLexRegisterToken( lexH, kCommaTokId, ",");
  2519. cmLexRegisterToken( lexH, kIntTokId, "int");
  2520. cmLexRegisterToken( lexH, kRealTokId, "real");
  2521. cmLexRegisterToken( lexH, kTrueTokId, "true");
  2522. cmLexRegisterToken( lexH, kFalseTokId, "false");
  2523. cmLexRegisterToken( lexH, kStringTokId, "string");
  2524. cmLexRegisterToken( lexH, kBoolTokId, "bool");
  2525. // lex the file
  2526. if( cmLexSetFile( lexH, iFn ) != kOkLexRC )
  2527. {
  2528. rc = _cmJsonError( p, kLexErrJsRC, "Lex failed on CSV parse of '%s'.",cmStringNullGuard(iFn));
  2529. goto errLabel;
  2530. }
  2531. // create the parent array
  2532. if((arrayNodePtr = cmJsonCreateArray( h, parentNodePtr )) == NULL )
  2533. {
  2534. rc = _cmJsonError( p, kCsvErrJsRC, "CSV array create failed during parse of '%s'.",cmStringNullGuard(iFn));
  2535. goto errLabel;
  2536. }
  2537. // iterate through the lexer file
  2538. while(((tokId = cmLexGetNextToken(lexH)) != kErrorLexTId) && (tokId != kEofLexTId) )
  2539. {
  2540. unsigned fieldTypeTokId = kInvalidTId;
  2541. switch( cmLexCurrentLineNumber(lexH) )
  2542. {
  2543. // line 1 contains the field type labels (e.g. int,real,string,true,false,bool)
  2544. case 1:
  2545. switch(tokId)
  2546. {
  2547. case kCommaTokId:
  2548. break;
  2549. case kIntTokId:
  2550. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kIntTId : fieldTypeTokId;
  2551. case kRealTokId:
  2552. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kRealTId : fieldTypeTokId;
  2553. case kTrueTokId:
  2554. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kTrueTId : fieldTypeTokId;
  2555. case kFalseTokId:
  2556. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kFalseTId : fieldTypeTokId;
  2557. case kBoolTokId:
  2558. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kFalseTId : fieldTypeTokId;
  2559. case kStringTokId:
  2560. fieldTypeTokId = (fieldTypeTokId==kInvalidTId) ? kStringTId : fieldTypeTokId;
  2561. // create and intitialize a new field
  2562. field_t* rp = cmMemAllocZ( field_t, 1 );
  2563. rp->fieldLabel = NULL;
  2564. rp->typeId = fieldTypeTokId;
  2565. rp->linkPtr = NULL;
  2566. // and add it to the end of the field list
  2567. if( fieldList == NULL )
  2568. fieldList = rp;
  2569. else
  2570. fieldPtr->linkPtr = rp;
  2571. // fieldPtr points to the end of the list
  2572. fieldPtr = rp;
  2573. break;
  2574. default:
  2575. rc = _cmJsonRptCsvTokErr( p, 1, lexH, iFn );
  2576. goto errLabel;
  2577. }
  2578. break;
  2579. // line 2 contains the field labels
  2580. case 2:
  2581. if( fieldIdx == 0 )
  2582. fieldPtr = fieldList;
  2583. ++fieldIdx;
  2584. switch(tokId)
  2585. {
  2586. case kCommaTokId:
  2587. break;
  2588. // all line 2 tokens must be identifiers or q-strings
  2589. case kIdentLexTId:
  2590. case kQStrLexTId:
  2591. if( fieldPtr == NULL )
  2592. {
  2593. rc = _cmJsonError( p, kCsvErrJsRC, "More fields on line 2 than type specifiers on line 1 of '%s'.",cmStringNullGuard(iFn));
  2594. goto errLabel;
  2595. }
  2596. else
  2597. {
  2598. // set the field name in the field list
  2599. unsigned n = cmLexTokenCharCount(lexH);
  2600. fieldPtr->fieldLabel = cmMemAllocZ( char, n+1 );
  2601. strncpy(fieldPtr->fieldLabel,cmLexTokenText(lexH),n);
  2602. fieldPtr->fieldLabel[n] = 0;
  2603. fieldPtr = fieldPtr->linkPtr;
  2604. }
  2605. break;
  2606. default:
  2607. rc = _cmJsonRptCsvTokErr( p, 2, lexH, iFn );
  2608. goto errLabel;
  2609. }
  2610. break;
  2611. // lines 3 to end of file contain data
  2612. default:
  2613. {
  2614. int ival = 0;
  2615. cmReal_t rval = 0;
  2616. // if we are starting a new line in the CSV file
  2617. if( lineNo != cmLexCurrentLineNumber(lexH) )
  2618. {
  2619. // verify that field ptr is pointing to the end of the field list
  2620. if( fieldPtr != NULL )
  2621. {
  2622. rc = _cmJsonError( p, kCsvErrJsRC, "Missing columns were detected on line %i in CSV file '%s'.", lineNo, cmStringNullGuard(iFn));
  2623. goto errLabel;
  2624. }
  2625. fieldPtr = fieldList;
  2626. lineNo = cmLexCurrentLineNumber(lexH);
  2627. // create the object to hold the fields on this line
  2628. if((objNodePtr = cmJsonCreateObject( h, arrayNodePtr )) == NULL )
  2629. {
  2630. rc = _cmJsonError( p, kCsvErrJsRC, "Object node create failed on line %i in CSV file '%s'.",lineNo,cmStringNullGuard(iFn));
  2631. goto errLabel;
  2632. }
  2633. }
  2634. if( tokId == kCommaTokId )
  2635. continue;
  2636. if( fieldPtr == NULL )
  2637. {
  2638. rc = _cmJsonError( p, kCsvErrJsRC, "More columns than fields on line %i in CSV file '%s'.", lineNo,cmStringNullGuard(iFn));
  2639. goto errLabel;
  2640. }
  2641. // given the tokens type convert the token string into a value
  2642. switch(tokId)
  2643. {
  2644. case kRealLexTId:
  2645. #ifdef CM_FLOAT_REAL
  2646. rval = cmLexTokenFloat(lexH);
  2647. #else
  2648. rval = cmLexTokenDouble(lexH);
  2649. #endif
  2650. ival = (int)rval;
  2651. if( fieldPtr->typeId == kStringTId )
  2652. {
  2653. rc = _cmJsonRptCsvTypeErr(p, lineNo, lexH, iFn, "numeric", fieldPtr->typeId );
  2654. goto errLabel;
  2655. }
  2656. break;
  2657. case kIntLexTId:
  2658. case kHexLexTId:
  2659. ival = cmLexTokenInt(lexH);
  2660. rval = ival;
  2661. if( fieldPtr->typeId == kStringTId )
  2662. {
  2663. rc = _cmJsonRptCsvTypeErr(p, lineNo, lexH, iFn, "numeric", fieldPtr->typeId );
  2664. goto errLabel;
  2665. }
  2666. break;
  2667. case kTrueTokId:
  2668. ival = 1;
  2669. rval = 1.0;
  2670. break;
  2671. case kFalseTokId:
  2672. ival = 0;
  2673. rval = 0.0;
  2674. break;
  2675. case kIdentLexTId:
  2676. case kQStrLexTId:
  2677. if( fieldPtr->typeId != kStringTId )
  2678. {
  2679. rc = _cmJsonRptCsvTypeErr(p, lineNo, lexH, iFn, "string", fieldPtr->typeId );
  2680. goto errLabel;
  2681. }
  2682. break;
  2683. default:
  2684. rc = _cmJsonRptCsvTokErr( p, lineNo, lexH, iFn );
  2685. goto errLabel;
  2686. }
  2687. // create the pair object from the current field label and value
  2688. switch(fieldPtr->typeId)
  2689. {
  2690. case kIntTId:
  2691. rc = cmJsonInsertPairInt( h, objNodePtr, fieldPtr->fieldLabel, ival );
  2692. break;
  2693. case kRealTId:
  2694. rc = cmJsonInsertPairReal( h, objNodePtr, fieldPtr->fieldLabel, rval );
  2695. break;
  2696. case kTrueTId:
  2697. case kFalseTId:
  2698. rc = cmJsonInsertPairBool( h, objNodePtr, fieldPtr->fieldLabel, ival );
  2699. break;
  2700. case kStringTId:
  2701. rc = cmJsonInsertPairStringN( h, objNodePtr, fieldPtr->fieldLabel, cmLexTokenText(lexH), cmLexTokenCharCount(lexH) );
  2702. break;
  2703. default:
  2704. {
  2705. assert(0);
  2706. goto errLabel;
  2707. }
  2708. }
  2709. if( rc != kOkJsRC )
  2710. goto errLabel;
  2711. fieldPtr = fieldPtr->linkPtr;
  2712. }
  2713. break;
  2714. }
  2715. }
  2716. errLabel:
  2717. if( cmLexFinal(&lexH) != kOkLexRC )
  2718. {
  2719. rc = _cmJsonError( p, kLexErrJsRC, "Lexer finalize failed on CSV parse of '%s'.",cmStringNullGuard(iFn));
  2720. goto errLabel;
  2721. }
  2722. lp = fieldList;
  2723. while( lp!=NULL )
  2724. {
  2725. field_t* pp = lp->linkPtr;
  2726. cmMemPtrFree(&lp->fieldLabel);
  2727. cmMemPtrFree(&lp);
  2728. lp = pp;
  2729. }
  2730. if( rc != kOkJsRC )
  2731. _cmJsonRemoveNode( p, arrayNodePtr, true, true );
  2732. if( rc == kOkJsRC && arrayNodePtrPtr != NULL )
  2733. *arrayNodePtrPtr = arrayNodePtr;
  2734. return rc;
  2735. }
  2736. cmJsRC_t cmJsonToCSV( cmJsonH_t h, const char* oFn, const cmJsonNode_t* arrayNodePtr )
  2737. {
  2738. assert( arrayNodePtr->typeId == kArrayTId );
  2739. typedef struct r_str
  2740. {
  2741. const char* fieldLabel;
  2742. unsigned typeId;
  2743. struct r_str* linkPtr;
  2744. } field_t;
  2745. cmJs_t* p = _cmJsonHandleToPtr(h);
  2746. cmJsRC_t rc = kOkJsRC;
  2747. unsigned arrayCnt = cmJsonChildCount(arrayNodePtr);
  2748. field_t* fieldList = NULL;
  2749. FILE* fp = NULL;
  2750. field_t* lp = NULL;
  2751. unsigned i,j;
  2752. // for each object in the array
  2753. for(i=0; i<arrayCnt; ++i)
  2754. {
  2755. const cmJsonNode_t* objNodePtr = cmJsonArrayElementC( arrayNodePtr, i );
  2756. assert( objNodePtr->typeId == kObjectTId );
  2757. // for each pair in the object
  2758. for(j=0; j<cmJsonChildCount(objNodePtr); ++j)
  2759. {
  2760. const cmJsonNode_t* pairNodePtr = cmJsonArrayElementC( objNodePtr, j );
  2761. const char* pairLabel = cmJsonPairLabel(pairNodePtr);
  2762. lp = fieldList;
  2763. // find this field in the field list
  2764. for(; lp != NULL; lp = lp->linkPtr )
  2765. if( strcmp(lp->fieldLabel,pairLabel) == 0)
  2766. {
  2767. unsigned typeId = cmJsonPairTypeId(pairNodePtr);
  2768. switch( typeId )
  2769. {
  2770. case kIntTId:
  2771. case kRealTId:
  2772. case kTrueTId:
  2773. case kFalseTId:
  2774. case kStringTId:
  2775. break;
  2776. default:
  2777. rc = _cmJsonError( p, kInvalidNodeTypeJsRC, "Field '%s' has type '%s' which cannot be written by cmJsonToCSV().",cmStringNullGuard(pairLabel),_cmJsonNodeTypeIdToLabel(typeId) );
  2778. goto errLabel;
  2779. }
  2780. if( typeId != lp->typeId )
  2781. {
  2782. rc = _cmJsonError( p, kInvalidNodeTypeJsRC, "All nodes for a field label '%s' do not have the same type. '%s' != '%s'",cmStringNullGuard(pairLabel), _cmJsonNodeTypeIdToLabel(typeId), _cmJsonNodeTypeIdToLabel(lp->typeId) );
  2783. goto errLabel;
  2784. }
  2785. break;
  2786. }
  2787. // if this field was not found then insert it
  2788. if( lp == NULL )
  2789. {
  2790. field_t* rp = (field_t*)cmLHeapAlloc(p->heapH,sizeof(field_t));
  2791. rp->fieldLabel = pairLabel;
  2792. rp->linkPtr = fieldList;
  2793. rp->typeId = cmJsonPairTypeId(pairNodePtr);
  2794. fieldList = rp;
  2795. }
  2796. }
  2797. }
  2798. // create the output file
  2799. if((fp = fopen(oFn,"wt")) == NULL )
  2800. {
  2801. rc = _cmJsonError( p, kFileCreateErrJsRC, "CSV file '%s' create failed.", oFn );
  2802. goto errLabel;
  2803. }
  2804. // write the field type
  2805. lp = fieldList;
  2806. for(; lp!=NULL; lp=lp->linkPtr)
  2807. {
  2808. fprintf(fp,"%s", _cmJsonNodeTypeIdToLabel(lp->typeId));
  2809. if( lp->linkPtr != NULL )
  2810. fprintf(fp,",");
  2811. }
  2812. fprintf(fp,"\n");
  2813. // write the field label
  2814. lp = fieldList;
  2815. for(; lp!=NULL; lp=lp->linkPtr)
  2816. {
  2817. fprintf(fp,"\"%s\"", lp->fieldLabel);
  2818. if( lp->linkPtr != NULL )
  2819. fprintf(fp,",");
  2820. }
  2821. fprintf(fp,"\n");
  2822. // for each object in the array
  2823. for(i=0; i<arrayCnt; ++i)
  2824. {
  2825. unsigned j;
  2826. const cmJsonNode_t* objNodePtr = cmJsonArrayElementC( arrayNodePtr, i );
  2827. unsigned fieldCnt = cmJsonChildCount(objNodePtr);
  2828. lp = fieldList;
  2829. // for each field ...
  2830. for(j=0; lp!=NULL; lp=lp->linkPtr,++j)
  2831. {
  2832. cmJsonNode_t* valNodePtr;
  2833. // ... locate the pair given the field label
  2834. if((valNodePtr = cmJsonFindValue(h,lp->fieldLabel, objNodePtr, lp->typeId )) == NULL)
  2835. {
  2836. // no pair was found for the field label - output a NULL value
  2837. switch( lp->typeId )
  2838. {
  2839. case kIntTId:
  2840. fprintf(fp,"%i",0);
  2841. break;
  2842. case kRealTId:
  2843. fprintf(fp,"%f",0.0);
  2844. break;
  2845. case kTrueTId:
  2846. case kFalseTId:
  2847. fprintf(fp,"%i",0);
  2848. break;
  2849. case kStringTId:
  2850. fprintf(fp,"\"\"");
  2851. break;
  2852. default:
  2853. assert(0);
  2854. break;
  2855. }
  2856. //rc = _cmJsonError( p, kNodeNotFoundJsRC,"No field with label '%s' was found.", lp->fieldLabel);
  2857. //goto errLabel;
  2858. }
  2859. else
  2860. {
  2861. switch( valNodePtr->typeId )
  2862. {
  2863. case kIntTId:
  2864. fprintf(fp,"%i", valNodePtr->u.intVal);
  2865. break;
  2866. case kRealTId:
  2867. fprintf(fp,"%e", valNodePtr->u.realVal);
  2868. break;
  2869. case kTrueTId:
  2870. case kFalseTId:
  2871. fprintf(fp,"%i", valNodePtr->u.boolVal);
  2872. break;
  2873. case kStringTId:
  2874. fprintf(fp,"\"%s\"", valNodePtr->u.stringVal);
  2875. break;
  2876. default:
  2877. assert(0);
  2878. break;
  2879. }
  2880. }
  2881. if( j < fieldCnt-1 )
  2882. fprintf(fp,",");
  2883. }
  2884. fprintf(fp,"\n");
  2885. }
  2886. errLabel:
  2887. if( fp != NULL )
  2888. fclose(fp);
  2889. lp = fieldList;
  2890. while( lp!=NULL )
  2891. {
  2892. field_t* pp = lp->linkPtr;
  2893. cmLHeapFree(p->heapH,lp);
  2894. lp = pp;
  2895. }
  2896. return rc;
  2897. }
  2898. void _cmJsonPrintIndent( cmRpt_t* rpt, unsigned indent )
  2899. {
  2900. if( indent )
  2901. {
  2902. char spaces[indent+1];
  2903. spaces[indent]=0;
  2904. memset(spaces,' ',indent);
  2905. cmRptPrint(rpt,spaces);
  2906. }
  2907. }
  2908. void _cmJsonPrintNode( const cmJsonNode_t* np, cmRpt_t* rpt, unsigned indent )
  2909. {
  2910. unsigned childCnt = 0;
  2911. char eoObjStr[] = "}";
  2912. char eoArrStr[] = "]";
  2913. char eoPairStr[] = "\n";
  2914. char commaStr[] = ",\n";
  2915. char colonStr[] = ": ";
  2916. const char* eleStr = NULL;
  2917. const char* lastEleStr = NULL;
  2918. const char* eoStr = NULL;
  2919. unsigned localIndent = 0;
  2920. switch(np->typeId)
  2921. {
  2922. case kObjectTId:
  2923. cmRptPrint(rpt,"\n");
  2924. _cmJsonPrintIndent(rpt,indent);
  2925. cmRptPrint(rpt,"{\n");
  2926. childCnt = cmJsonChildCount(np);
  2927. eoStr = eoObjStr;
  2928. localIndent = 2;
  2929. break;
  2930. case kArrayTId:
  2931. cmRptPrint(rpt,"\n");
  2932. _cmJsonPrintIndent(rpt,indent);
  2933. cmRptPrint(rpt,"[\n");
  2934. childCnt = cmJsonChildCount(np);
  2935. eoStr = eoArrStr;
  2936. localIndent = 2;
  2937. eleStr = commaStr;
  2938. lastEleStr = "\n";
  2939. break;
  2940. case kPairTId:
  2941. childCnt = cmJsonChildCount(np);
  2942. eleStr = colonStr;
  2943. eoStr = eoPairStr;
  2944. break;
  2945. case kStringTId:
  2946. {
  2947. const char* fmt0 = "\"%s\" ";
  2948. const char* fmt1 = "%s";
  2949. const char* fmt = fmt0;
  2950. // if this string is the label part of a pair
  2951. if( np->u.stringVal != NULL && np->ownerPtr != NULL && cmJsonIsPair(np->ownerPtr) && np->ownerPtr->u.childPtr == np )
  2952. {
  2953. // and the label has no white space
  2954. char* cp = np->u.stringVal;
  2955. while( *cp!=0 && isspace(*cp)==false )
  2956. ++cp;
  2957. // then print without quotes
  2958. if( *cp == 0 )
  2959. fmt = fmt1;
  2960. }
  2961. cmRptPrintf(rpt,fmt,np->u.stringVal==NULL ? "" : np->u.stringVal);
  2962. }
  2963. break;
  2964. case kIntTId:
  2965. cmRptPrintf(rpt,"%i ",np->u.intVal);
  2966. break;
  2967. case kRealTId:
  2968. cmRptPrintf(rpt,"%f ",np->u.realVal);
  2969. break;
  2970. case kNullTId:
  2971. cmRptPrint(rpt,"null ");
  2972. break;
  2973. case kTrueTId:
  2974. cmRptPrint(rpt,"true ");
  2975. break;
  2976. case kFalseTId:
  2977. cmRptPrint(rpt,"false ");
  2978. break;
  2979. }
  2980. if( childCnt )
  2981. {
  2982. indent += localIndent;
  2983. unsigned i;
  2984. cmJsonNode_t* cnp = np->u.childPtr;
  2985. for(i=0; i<childCnt; ++i)
  2986. {
  2987. assert(cnp != NULL);
  2988. if( np->typeId != kPairTId )
  2989. _cmJsonPrintIndent(rpt,indent);
  2990. _cmJsonPrintNode(cnp,rpt,indent);
  2991. cnp = cnp->siblingPtr;
  2992. if( i < childCnt-1 && eleStr != NULL )
  2993. cmRptPrint(rpt,eleStr);
  2994. if( i == childCnt-1 && lastEleStr != NULL )
  2995. cmRptPrint(rpt,lastEleStr);
  2996. }
  2997. indent -= localIndent;
  2998. }
  2999. if( eoStr != NULL )
  3000. {
  3001. _cmJsonPrintIndent(rpt,indent);
  3002. cmRptPrint(rpt,eoStr);
  3003. }
  3004. }
  3005. void cmJsonPrintTree( const cmJsonNode_t* np, cmRpt_t* rpt )
  3006. {
  3007. _cmJsonPrintNode(np,rpt,0);
  3008. }
  3009. void _cmJsPrintFile(void* cmRptUserPtr, const cmChar_t* text)
  3010. {
  3011. cmFileH_t* hp = (cmFileH_t*)cmRptUserPtr;
  3012. cmFilePrint(*hp,text);
  3013. }
  3014. cmJsRC_t cmJsonWrite( cmJsonH_t h, const cmJsonNode_t* np, const cmChar_t* fn )
  3015. {
  3016. cmRpt_t rpt;
  3017. cmFileH_t fh = cmFileNullHandle;
  3018. cmJs_t* p = _cmJsonHandleToPtr(h);
  3019. if( np == NULL )
  3020. np = cmJsonRoot(h);
  3021. // create the output file
  3022. if( cmFileOpen(&fh,fn,kWriteFileFl,p->err.rpt) != kOkFileRC )
  3023. return _cmJsonError( p, kFileCreateErrJsRC, "Output file '%s' create failed.", fn );
  3024. // setup a reporter to write to the file
  3025. cmRptSetup(&rpt,_cmJsPrintFile,_cmJsPrintFile,&fh);
  3026. // print the tree to the file
  3027. cmJsonPrintTree(np,&rpt);
  3028. // close the file
  3029. if( cmFileClose(&fh) != kOkFileRC )
  3030. return _cmJsonError( p, kFileCloseErrJsRC, "Output file '%s' close failed.", fn );
  3031. return kOkJsRC;
  3032. }
  3033. cmJsRC_t cmJsonReport( cmJsonH_t h )
  3034. {
  3035. cmJsRC_t rc;
  3036. cmJs_t* p = _cmJsonHandleToPtr(h);
  3037. if((rc = cmJsonValidateTree(h)) != kOkJsRC )
  3038. return rc;
  3039. if(p->rootPtr != NULL )
  3040. _cmJsonPrintNode(p->rootPtr,p->err.rpt,0);
  3041. return rc;
  3042. }
  3043. cmJsRC_t cmJsonErrorCode( cmJsonH_t h )
  3044. {
  3045. cmJs_t* p = _cmJsonHandleToPtr(h);
  3046. return p->rc;
  3047. }
  3048. void cmJsonClearErrorCode( cmJsonH_t h )
  3049. {
  3050. cmJs_t* p = _cmJsonHandleToPtr(h);
  3051. p->rc = kOkJsRC;
  3052. }
  3053. void _cmJsonTestVPrint( void* rptDataPtr, const char* fmt, va_list vl )
  3054. {
  3055. vfprintf(stdout,fmt,vl);
  3056. }
  3057. void _cmJsonTestPrint( void* userPtr, const cmChar_t* text )
  3058. {
  3059. fputs(text,stdout);
  3060. }
  3061. //{ { label:cmJsonEx }
  3062. //(
  3063. // cmJsonTest() demonstrates some JSON tree operations.
  3064. //)
  3065. //[
  3066. cmJsRC_t cmJsonTest( const char* fn, cmCtx_t* ctx )
  3067. {
  3068. cmJsRC_t rc = kOkJsRC;
  3069. cmJsRC_t rc1 = kOkJsRC;
  3070. cmJsonH_t h = cmJsonNullHandle;
  3071. cmJsonH_t h1 = cmJsonNullHandle;
  3072. void* sbp = NULL;
  3073. unsigned sbn = 0;
  3074. cmJsonNode_t* np = NULL;
  3075. cmRpt_t* rpt = &ctx->rpt;
  3076. // initialize an empty JSON tree
  3077. if((rc = cmJsonInitialize(&h,ctx)) != kOkJsRC )
  3078. goto errLabel;
  3079. // load the tree from a file
  3080. if((rc = cmJsonParseFile(h,fn,NULL)) != kOkJsRC )
  3081. goto errLabel;
  3082. // print the tree
  3083. cmJsonReport(h);
  3084. // find an array member named 'mem14'
  3085. if((np = cmJsonFindValue(h,"mem14",NULL,kArrayTId)) == NULL )
  3086. cmRptPrint(rpt,"'mem14' not found.\n");
  3087. else
  3088. {
  3089. cmRptPrint(rpt,"'mem14' found.\n");
  3090. cmJsonPrintTree(np,rpt);
  3091. }
  3092. // remove the array node from the tree
  3093. cmJsonRemoveNode(h,np, true);
  3094. cmRptPrint(rpt,"mem14 removed.\n");
  3095. // print the tree with the array node removed
  3096. cmJsonPrintTree( cmJsonRoot(h), rpt );
  3097. // serialize the tree into a dynamically allocated
  3098. // buffer sbp[sbn].
  3099. if((rc = cmJsonSerializeTree(h,NULL,&sbp,&sbn)) != kOkJsRC )
  3100. goto errLabel;
  3101. else
  3102. cmRptPrint(rpt,"***Serialize Ok.****\n");
  3103. // initialize an empty JSON tree
  3104. if((rc = cmJsonInitialize(&h1,ctx)) != kOkJsRC )
  3105. goto errLabel;
  3106. // deserialize sbp[sbn] into the empty tree
  3107. if((rc = cmJsonDeserialize(h1,sbp,NULL)) != kOkJsRC )
  3108. goto errLabel;
  3109. else
  3110. {
  3111. cmJsonPrintTree( cmJsonRoot(h1),rpt);
  3112. cmRptPrint(rpt,"***Deserialize Ok.****\n");
  3113. }
  3114. // find an member node named 'mem5'
  3115. if((np = cmJsonFindValue(h,"mem5",NULL,0)) == NULL )
  3116. cmRptPrint(rpt,"mem5 not found.");
  3117. // merge two sub-trees
  3118. if( cmJsonMergeObjectNodes( h, np->u.childPtr,
  3119. np->u.childPtr->siblingPtr) != kOkJsRC )
  3120. {
  3121. cmRptPrint(rpt,"merge failed.");
  3122. }
  3123. else
  3124. {
  3125. cmJsonReport(h);
  3126. }
  3127. errLabel:
  3128. // release the JSON trees
  3129. rc = cmJsonFinalize(&h);
  3130. rc1 = cmJsonFinalize(&h1);
  3131. return rc == kOkJsRC ? rc1 : rc;
  3132. }
  3133. //]
  3134. //}