Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
json.c
Go to the documentation of this file.
1 /* *************************************************************************************
2  Copyright (c) 2021, Lowell D. Thomas
3  All rights reserved.
4 
5  This file is part of APG Version 7.0.
6  APG Version 7.0 may be used under the terms of the BSD 2-Clause License.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 * *************************************************************************************/
62 #include <limits.h>
63 
64 #include "json.h"
65 #include "jsonp.h"
66 #include "json-grammar.h"
67 
71 #define CHARS_LINE_LEN 8
72 
73 static const void* s_vpJsonValid = (void*)"JSON";
74 static const void* s_vpIteratorValid = (void*)"iterator";
75 
76 static uint32_t s_uiaTrue[] = { 116, 114, 117, 101 };
77 static uint32_t s_uiaFalse[] = { 102, 97, 108, 115, 101 };
78 static uint32_t s_uiaNull[] = { 110, 117, 108, 108 };
79 static aint s_uiTrueLen = 4;
80 static aint s_uiFalseLen = 5;
81 static aint s_uiNullLen = 4;
82 static char* s_cpTrue = "true";
83 static char* s_cpFalse = "false";
84 static char* s_cpNull = "null";
85 static uint32_t s_uiOpenCurly = 123;
86 static uint32_t s_uiCloseCurly = 125;
87 static uint32_t s_uiOpenSquare = 91;
88 static uint32_t s_uiCloseSquare = 93;
89 static uint32_t s_uiColon = 58;
90 static uint32_t s_uiComma = 44;
91 static uint32_t s_uiSpace = 32;
92 static uint32_t s_uiLineEnd = 10;
93 static uint32_t s_uiQuote = 34;
94 static uint32_t s_uiReverseSolidus = 0x5C;
95 static uint32_t s_uiLowerU = 0x75;
96 
97 static void vParseInput(json* spJson);
98 static void vReintrantValueDisplay(json *spJson, struct json_value_tag *spValue);
99 static void vIndent(aint uiIndent);
100 static void vFindKeyValues(json* spJson, json_iterator* spIt, const uint32_t *uipKey, uint32_t uiLength, json_value* spValue);
101 static void vBreakIndent(json* spJson, aint uiIndent);
102 static void vPushObject(json* spJson, json_value* spValue, abool bArray);
103 static void vPushString(json* spJson, u32_phrase* spString);
104 static void vPushNumber(json* spJson, json_number* spNumber);
105 static void vPushValue(json* spJson, json_value* spValue);
106 static void vWalkCount(json* spJson, json_value* spValue);
107 
115 void* vpJsonCtor(exception* spEx){
116  if(!bExValidate(spEx)){
117  vExContext();
118  }
119  json* spJson = NULL;
120  void* vpMem = vpMemCtor(spEx);
121  spJson = (json*) vpMemAlloc(vpMem, sizeof(json));
122  memset((void*) spJson, 0, sizeof(json));
123 
124  // basics for input and output
125  spJson->vpVecInput = vpVecCtor(vpMem, sizeof(uint8_t), 4096);
126  spJson->vpVecOutput = vpVecCtor(vpMem, sizeof(uint32_t), 8192);
127 
128  // vectors used to give caller access to resulting values
129  spJson->vpVecTreeList = vpVecCtor(vpMem, sizeof(json_value*), 512);
130  spJson->vpVecChildList = vpVecCtor(vpMem, sizeof(json_value*), 512);
131  spJson->vpVecKeyList = vpVecCtor(vpMem, sizeof(json_value*), 512);
132  spJson->vpVecScratch32 = vpVecCtor(vpMem, sizeof(uint32_t), 4096);
133 
134  spJson->vpVecIterators = vpVecCtor(vpMem, sizeof(void*), 32);
135  spJson->vpVecBuilders = vpVecCtor(vpMem, sizeof(void*), 32);
136 
137  // vectors used by the parser for collecting data
138  spJson->vpVecChars = vpVecCtor(vpMem, sizeof(uint32_t), 4096);
139  spJson->vpVecAscii = vpVecCtor(vpMem, sizeof(uint8_t), 4096);
140  spJson->vpVecValuesr = vpVecCtor(vpMem, sizeof(value_r), 1024);
141  spJson->vpVecStringsr = vpVecCtor(vpMem, sizeof(string_r), 1024);
142  spJson->vpVecNumbers = vpVecCtor(vpMem, sizeof(json_number), 1024);
143  spJson->vpVecChildIndexes = vpVecCtor(vpMem, sizeof(aint), 1024);
144  spJson->vpVecFrames = vpVecCtor(vpMem, sizeof(frame), 128);
145  spJson->vpVecValues = vpVecCtor(vpMem, sizeof(json_value), 128);
146  spJson->vpVecStrings = vpVecCtor(vpMem, sizeof(u32_phrase), 128);
147  spJson->vpVecChildPointers = vpVecCtor(vpMem, sizeof(json_value*), 128);
148  spJson->vpFmt = vpFmtCtor(spEx);
149 
150  // success
151  spJson->vpMem = vpMem;
152  spJson->spException = spEx;
153  spJson->vpValidate = s_vpJsonValid;
154  return (void*) spJson;
155 }
156 
165 void vJsonDtor(void *vpCtx) {
166  json* spJson = (json*) vpCtx;
167  if (vpCtx) {
168  if (spJson->vpValidate == s_vpJsonValid) {
169  void* vpMem = spJson->vpMem;
170  if(spJson->spIn){
171  fclose(spJson->spIn);
172  }
173  vConvDtor(spJson->vpConv);
174  vFmtDtor(spJson->vpFmt);
175  vLinesDtor(spJson->vpLines);
176  memset((void*) spJson, 0, sizeof(json));
177  vMemDtor(vpMem);
178  }else{
179  vExContext();
180  }
181  }
182 }
183 
188 abool bJsonValidate(void* vpCtx){
189  if(vpCtx && (((json*)vpCtx)->vpValidate == s_vpJsonValid)){
190  return APG_TRUE;
191  }
192  return APG_FALSE;
193 }
194 
207 void* vpJsonReadFile(void *vpCtx, const char *cpFileName){
208  json* spJson = (json*) vpCtx;
209  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
210  vExContext();
211  }
212  char caBuf[PATH_MAX + 128];
213  size_t uiSize = PATH_MAX + 128;
214  uint8_t ucaBom[3];
215  int iaBom[3];
216  vVecClear(spJson->vpVecInput);
217  vLinesDtor(spJson->vpLines);
218  spJson->vpLines = NULL;
219  if(spJson->spIn){
220  fclose(spJson->spIn);
221  spJson->spIn = NULL;
222  }
223  if(!cpFileName || !cpFileName[0]){
224  XTHROW(spJson->spException, "file name cannot be NULL or empty");
225 
226  }
227  spJson->spIn = fopen(cpFileName, "rb");
228  if (!spJson->spIn) {
229  snprintf(caBuf, uiSize, "can't open input file: %s", cpFileName);
230  XTHROW(spJson->spException, caBuf);
231  }
232  // get the first 3 bytes and test for BOM
233  iaBom[0] = fgetc(spJson->spIn);
234  iaBom[1] = fgetc(spJson->spIn);
235  iaBom[2] = fgetc(spJson->spIn);
236  ucaBom[0] = (uint8_t) iaBom[0];
237  ucaBom[1] = (uint8_t) iaBom[1];
238  ucaBom[2] = (uint8_t) iaBom[2];
239  if (iaBom[0] == EOF) {
240  snprintf(caBuf, uiSize, "input file is empty: %s", cpFileName);
241  XTHROW(spJson->spException, caBuf);
242  }
243  if (iaBom[1] == EOF) {
244  // only one character - push and continue
245  vpVecPush(spJson->vpVecInput, &ucaBom[0]);
246  }else if (iaBom[2] == EOF) {
247  // only two characters - push and continue
248  vpVecPushn(spJson->vpVecInput, &ucaBom[0], 2);
249  }else{
250  if (!(ucaBom[0] == 0xEF && ucaBom[1] == 0xBB && ucaBom[2] == 0xBF)) {
251  // no BOM - save the first three characters and continue
252  vpVecPushn(spJson->vpVecInput, &ucaBom[0], 3);
253  }
254  uint8_t ucGotBuf[1024];
255  size_t uiGot = fread(ucGotBuf, 1, 1024, spJson->spIn);
256  while (uiGot != 0) {
257  vpVecPushn(spJson->vpVecInput, ucGotBuf, (aint)uiGot);
258  uiGot = fread(ucGotBuf, 1, 1024, spJson->spIn);
259  }
260  }
261  fclose(spJson->spIn);
262  spJson->spIn = NULL;
263  spJson->vpLines = vpLinesCtor(spJson->spException, (char*) vpVecFirst(spJson->vpVecInput), uiVecLen(spJson->vpVecInput));
264  vParseInput(spJson);
265  json_iterator* spIt = spJsonIteratorCtor(spJson);
266  json_value** sppValues = (json_value**)vpVecPushn(spIt->vpVec, NULL, spJson->uiValueCount);
267  aint ui = 0;
268  for(; ui < spJson->uiValueCount; ui++){
269  sppValues[ui] = &spJson->spValues[ui];
270  }
271  spIt->sppValues = sppValues;
272  spIt->uiCount = spJson->uiValueCount;
273  return (void*)spIt;
274 }
275 
289 void* vpJsonReadArray(void *vpCtx, uint8_t *ucpData, aint uiDataLen){
290  json* spJson = (json*) vpCtx;
291  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
292  vExContext();
293  }
294  vVecClear(spJson->vpVecInput);
295  vLinesDtor(spJson->vpLines);
296  spJson->vpLines = NULL;
297  // check for BOM
298  if (uiDataLen >= 3) {
299  if (ucpData[0] == 0xEF && ucpData[1] == 0xBB && ucpData[2] == 0xBF) {
300  ucpData += 3;
301  uiDataLen -= 3;
302  }
303  }
304  vpVecPushn(spJson->vpVecInput, ucpData, uiDataLen);
305  spJson->vpLines = vpLinesCtor(spJson->spException, (char*) vpVecFirst(spJson->vpVecInput),
306  uiVecLen(spJson->vpVecInput));
307  vParseInput(spJson);
308  json_iterator* spIt = spJsonIteratorCtor(spJson);
309  json_value** sppValues = (json_value**)vpVecPushn(spIt->vpVec, NULL, spJson->uiValueCount);
310  aint ui = 0;
311  for(; ui < spJson->uiValueCount; ui++){
312  sppValues[ui] = &spJson->spValues[ui];
313  }
314  spIt->sppValues = sppValues;
315  spIt->uiCount = spJson->uiValueCount;
316  return (void*)spIt;
317 }
318 
329 uint8_t* ucpJsonWrite(void* vpCtx, json_value* spValue, aint* uipCount) {
330  json* spJson = (json*) vpCtx;
331  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
332  vExContext();
333  }
334  uint8_t* ucpReturn = NULL;
335  if(!uipCount){
336  XTHROW(spJson->spException, "pointer for return count cannot be NULL");
337  }
338  *uipCount = 0;
339  spJson->uiCurrentDepth = 0;
340  vVecClear(spJson->vpVecOutput);
341  spJson->bFirstNode = APG_TRUE;
342  vPushValue(spJson, spValue);
343  // convert output to UTF-8 byte stream
344  if (!spJson->vpConv) {
345  spJson->vpConv = vpConvCtor(spJson->spException);
346  }
347  conv_dst sDst = { };
348  sDst.uiDataType = UTF_8;
349  vConvUseCodePoints(spJson->vpConv, (uint32_t*) vpVecFirst(spJson->vpVecOutput),
350  uiVecLen(spJson->vpVecOutput));
351  vConvEncode(spJson->vpConv, &sDst);
352  ucpReturn = sDst.ucpData;
353  *uipCount = sDst.uiDataLen;
354  return ucpReturn;
355 }
356 
365 void vJsonDisplayInput(void *vpCtx, abool bShowLines) {
366  json* spJson = (json*) vpCtx;
367  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
368  vExContext();
369  }
370  line* spLine;
371  aint ui, uiLines;
372  aint uiOffset, uiChars;
373  uint8_t* ucpChars = (uint8_t*) vpVecFirst(spJson->vpVecInput);
374  const char* cpNextLine;
375  spLine = spLinesFirst(spJson->vpLines);
376  uiLines = uiLinesCount(spJson->vpLines);
377  if (!ucpChars || !spLine || !uiLines) {
378  XTHROW(spJson->spException, "no JSON input");
379  }
380  if (bShowLines) {
381  for (ui = 0; ui < uiLines; ui++, spLine++) {
382  printf("%04"PRIuMAX" ", (luint) spLine->uiLineIndex);
383  uiOffset = spLine->uiCharIndex;
384  cpNextLine = cpFmtFirstBytes(spJson->vpFmt, &ucpChars[uiOffset], spLine->uiLineLength, FMT_CANONICAL, 0, 0);
385  vFmtIndent(spJson->vpFmt, 5);
386  while(cpNextLine){
387  printf("%s", cpNextLine);
388  cpNextLine = cpFmtNext(spJson->vpFmt);
389  }
390  vFmtIndent(spJson->vpFmt, 0);
391  }
392  } else {
393  uiChars = uiVecLen(spJson->vpVecInput);
394  cpNextLine = cpFmtFirstBytes(spJson->vpFmt, ucpChars, (long int)uiChars, FMT_CANONICAL, 0, 0);
395  vFmtIndent(spJson->vpFmt, 0);
396  while(cpNextLine){
397  printf("%s", cpNextLine);
398  cpNextLine = cpFmtNext(spJson->vpFmt);
399  }
400  }
401 }
402 
412 void vJsonDisplayValue(void *vpCtx, json_value *spValue, aint uiDepth) {
413  json* spJson = (json*) vpCtx;
414  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
415  vExContext();
416  }
417  spJson->uiMaxDepth = uiDepth ? uiDepth : APG_INFINITE;
418  spJson->uiCurrentDepth = 0;
419  vReintrantValueDisplay(spJson, spValue);
420 }
421 
434 void* vpJsonFindKeyA(void *vpCtx, const char *cpKey, json_value* spValue) {
435  void* vpReturn = NULL;
436  json* spJson = (json*) vpCtx;
437  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
438  vExContext();
439  }
440  uint32_t uiLength = (uint32_t) strlen(cpKey);
441  if(uiLength){
442  vVecClear(spJson->vpVecScratch32);
443  uint32_t* uipKey = (uint32_t*) vpVecPushn(spJson->vpVecScratch32, NULL, (aint)uiLength);
444  uint32_t ui = 0;
445  const uint8_t* ucpUnsignedKey = (uint8_t*)cpKey;
446  for (; ui < uiLength; ui++) {
447  uipKey[ui] = (uint32_t) ucpUnsignedKey[ui];
448  }
449  json_iterator* spIt = spJsonIteratorCtor(spJson);
450  vFindKeyValues(spJson, spIt, uipKey, uiLength, spValue);
451  spIt->uiCount = uiVecLen(spIt->vpVec);
452  if(spIt->uiCount){
453  spIt->sppValues = (json_value**)vpVecFirst(spIt->vpVec);
454  vpReturn = (void*)spIt;
455  }else{
456  vJsonIteratorDtor(spIt);
457  }
458  }
459  return vpReturn;
460 }
474 void* vpJsonFindKeyU(void *vpCtx, const uint32_t *uipKey, aint uiLength, json_value* spValue) {
475  void* vpReturn = NULL;
476  json* spJson = (json*) vpCtx;
477  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
478  vExContext();
479  }
480  json_iterator* spIt = spJsonIteratorCtor(spJson);
481  vFindKeyValues(spJson, spIt, uipKey, uiLength, spValue);
482  spIt->sppValues = (json_value**)vpVecFirst(spIt->vpVec);
483  spIt->uiCount = uiVecLen(spIt->vpVec);
484  vpReturn = (spIt->sppValues && spIt->uiCount) ? (void*)spIt : NULL;
485  return vpReturn;
486 }
487 
501 void* vpJsonTree(void* vpCtx, json_value* spValue){
502  void* vpReturn = NULL;
503  json* spJson = (json*) vpCtx;
504  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
505  vExContext();
506  }
507  spJson->uiWalkCount = 0;
508  vWalkCount(spJson, spValue);
509  if(spJson->uiWalkCount){
510  json_iterator* spIt = spJsonIteratorCtor(spJson);
511  spIt->sppValues = (json_value**)vpVecPushn(spIt->vpVec, NULL, spJson->uiWalkCount);
512  spIt->uiCount = spJson->uiWalkCount;
513  aint ui = 0;
514  for(; ui < spJson->uiWalkCount; ui++){
515  spIt->sppValues[ui] = &spValue[ui];
516  }
517  vpReturn = (void*)spIt;
518  }
519  return vpReturn;
520 }
530 void* vpJsonChildren(void* vpCtx, json_value* spValue){
531  void* vpReturn = NULL;
532  json* spJson = (json*) vpCtx;
533  if((vpCtx == NULL) || (spJson->vpValidate != s_vpJsonValid)){
534  vExContext();
535  }
536  if (!spValue) {
537  XTHROW(spJson->spException, "value pointer cannot be NULL");
538  }
539  if(spValue->uiChildCount){
540  json_iterator* spIt = spJsonIteratorCtor(spJson);
541  spIt->sppValues = (json_value**)vpVecPushn(spIt->vpVec, NULL, spValue->uiChildCount);
542  spIt->uiCount = spValue->uiChildCount;
543  aint ui = 0;
544  for(; ui < spValue->uiChildCount; ui++){
545  spIt->sppValues[ui] = spValue->sppChildren[ui];
546  }
547  vpReturn = (void*)spIt;
548  }
549  return vpReturn;
550 }
551 
562  json_iterator* spIt = (json_iterator*)vpMemAlloc(spJson->vpMem, sizeof(json_iterator));
563  memset(spIt, 0, sizeof(json_iterator));
564  spIt->vpVec = vpVecCtor(spJson->vpMem, sizeof(json_value*), 512);
565  spIt->spJson = spJson;
566  spIt->uiContextIndex = uiVecLen(spJson->vpVecIterators);
567  vpVecPush(spJson->vpVecIterators, &spIt);
568  spIt->vpValidate = s_vpIteratorValid;
569  return spIt;
570 }
591 void vJsonIteratorDtor(void* vpIteratorCtx){
592  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
593  if(vpIteratorCtx){
594  if(spIt->vpValidate == s_vpIteratorValid){
595  void** vppContext = (void**)vpVecFirst(spIt->spJson->vpVecIterators);
596  vppContext[spIt->uiContextIndex] = NULL;
597  void* vpMem = spIt->spJson->vpMem;
598  vVecDtor(spIt->vpVec);
599  memset(vpIteratorCtx, 0, sizeof(json_iterator));
600  vMemFree(vpMem, vpIteratorCtx);
601  }else{
602  vExContext();
603  }
604  }
605 }
606 
613 json_value* spJsonIteratorFirst(void* vpIteratorCtx){
614  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
615  if((vpIteratorCtx == NULL) || (spIt->vpValidate != s_vpIteratorValid)){
616  vExContext();
617  }
618  spIt->uiCurrent = 0;
619  return *spIt->sppValues;
620 }
627 json_value* spJsonIteratorLast(void* vpIteratorCtx){
628  json_value* spReturn = NULL;
629  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
630  if((vpIteratorCtx == NULL) || (spIt->vpValidate != s_vpIteratorValid)){
631  vExContext();
632  }
633  if(spIt->uiCount){
634  spIt->uiCurrent = spIt->uiCount - 1;
635  spReturn = spIt->sppValues[spIt->uiCurrent];
636  }
637  return spReturn;
638 }
647 json_value* spJsonIteratorNext(void* vpIteratorCtx){
648  json_value* spReturn = NULL;
649  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
650  if((vpIteratorCtx == NULL) || (spIt->vpValidate != s_vpIteratorValid)){
651  vExContext();
652  }
653  if(spIt->uiCount){
654  if(spIt->uiCurrent < spIt->uiCount){
655  spIt->uiCurrent++;
656  if(spIt->uiCurrent < spIt->uiCount){
657  spReturn = spIt->sppValues[spIt->uiCurrent];
658  }
659  }
660  }
661  return spReturn;
662 }
671 json_value* spJsonIteratorPrev(void* vpIteratorCtx){
672  json_value* spReturn = NULL;
673  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
674  if((vpIteratorCtx == NULL) || (spIt->vpValidate != s_vpIteratorValid)){
675  vExContext();
676  }
677  if(spIt->uiCount){
678  if(spIt->uiCurrent > 0){
679  spIt->uiCurrent--;
680  spReturn = spIt->sppValues[spIt->uiCurrent];
681  }
682  }
683  return spReturn;
684 }
691 aint uiJsonIteratorCount(void* vpIteratorCtx){
692  json_iterator* spIt = (json_iterator*)vpIteratorCtx;
693  if((vpIteratorCtx == NULL) || (spIt->vpValidate != s_vpIteratorValid)){
694  vExContext();
695  }
696  return spIt->uiCount;
697 }
698 
710 static void vParseInput(json* spJson) {
711  parser_state sState;
712  parser_config sInput;
713  aint uiCharCount;
714  aint ui;
715  uint8_t* ucpChars;
716 
717  // clear previous parsing data, if any
718  spJson->spCurrentFrame = NULL;
719  spJson->uiValueCount = 0;
720  spJson->uiStringCount = 0;
721  spJson->uiChar = 0;
722  spJson->bHasFrac = APG_FALSE;
723  spJson->bHasMinus = APG_FALSE;
724  if(spJson->vpParser){
725  vParserDtor(spJson->vpParser);
726  spJson->vpParser = NULL;
727  }
728  if(spJson->acpInput){
729  vMemFree(spJson->vpMem, spJson->acpInput);
730  spJson->acpInput = NULL;
731  }
732  ucpChars = (uint8_t*) vpVecFirst(spJson->vpVecInput);
733  uiCharCount = uiVecLen(spJson->vpVecInput);
734  if (!uiCharCount) {
735  XTHROW(spJson->spException, "JSON text is empty");
736  }
737  // construct the parser
738  if(spJson->vpParser){
739  vParserDtor(spJson->vpParser);
740  }
742 // if (spJson->cpTraceOut) {
743 // // attach the trace - no trace if NULL
744 // void* vpTrace = vpTraceCtor(spJson->vpParser);
745 // if(spJson->cpTraceOut[0] != 0){
746 // // use the specified file name
747 // vTraceSetOutput(vpTrace, spJson->cpTraceOut);
748 // }
749 // }
750 
751  // set the rule callback functions
753 
754  // configure the parser
755  spJson->acpInput = (achar*) vpMemAlloc(spJson->vpMem, ((aint) sizeof(achar) * uiCharCount));
756  for (ui = 0; ui < uiCharCount; ui++) {
757  // NOTE: since the input is a byte stream and sizeof(achar) >= 1 always, no data truncation is possible here
758  spJson->acpInput[ui] = (achar) ucpChars[ui];
759  }
760  memset((void*) &sInput, 0, sizeof(sInput));
761  sInput.acpInput = spJson->acpInput;
762  sInput.uiInputLength = uiCharCount;
763  sInput.uiStartRule = 0;
764  sInput.vpUserData = (void*) spJson;
765  sInput.bParseSubString = APG_FALSE;
766 
767  // parse the JSON text
768  vParserParse(spJson->vpParser, &sInput, &sState);
769  if (!sState.uiSuccess) {
770  // display the parser state
771  vUtilPrintParserState(&sState);
772  XTHROW(spJson->spException, "JSON parser failed");
773  }
774  vParserDtor(spJson->vpParser); // destroys vpTrace, if not NULL
775  spJson->vpParser = NULL;
776  vMemFree(spJson->vpMem, spJson->acpInput);
777  spJson->acpInput = NULL;
778 }
779 
780 // static functions
781 static abool bKeyComp(u32_phrase* spKey, const uint32_t *uipKey, uint32_t uiLength){
782  abool bReturn = APG_FALSE;
783  if(spKey->uiLength == uiLength){
784  uint32_t ui = 0;
785  for(; ui < uiLength; ui++){
786  if(spKey->uipPhrase[ui] != uipKey[ui]){
787  goto fail;
788  }
789  }
790  bReturn = APG_TRUE;
791  }
792  fail:;
793  return bReturn;
794 }
795 static void vFindKeyValues(json* spJson, json_iterator* spIt, const uint32_t *uipKey, uint32_t uiLength, json_value* spValue){
796  if(spValue->spKey && bKeyComp(spValue->spKey, uipKey, uiLength)){
797  vpVecPush(spIt->vpVec, &spValue);
798  }
799  if ((spValue->uiId == JSON_ID_OBJECT) || (spValue->uiId == JSON_ID_ARRAY)) {
800  json_value** sppChildren = spValue->sppChildren;
801  json_value** sppEnd = sppChildren + spValue->uiChildCount;
802  for (; sppChildren < sppEnd; sppChildren++) {
803  vFindKeyValues(spJson, spIt, uipKey, uiLength, *sppChildren);
804  }
805  }
806 }
807 static void vIndent(aint uiIndent) {
808  aint ui = 0;
809  for (; ui < uiIndent; ui++) {
810  printf(" ");
811  }
812 }
813 static void vReintrantValueDisplay(json *spJson, struct json_value_tag *spValue) {
814  spJson->uiCurrentDepth++;
815  if (spJson->uiCurrentDepth > spJson->uiMaxDepth) {
816  return;
817  }
818  char caBuf[128];
819  aint uiIndent = 2 * (spJson->uiCurrentDepth - 1);
820  u32_phrase* spString;
821  json_number* spNumber;
822  aint uiChildCount;
823  struct json_value_tag** sppChildren;
824  aint ui;
825  const char* cpNextLine;
826  char* cpStr;
827  if (spValue->spKey) {
828  vIndent(uiIndent);
829  if (bIsPhrase32Ascii(spValue->spKey)) {
830  cpStr = (char*)vpVecPushn(spJson->vpVecAscii, NULL, spValue->spKey->uiLength);
831  cpPhrase32ToStr(spValue->spKey, cpStr);
832  printf("key: \"%s\"\n", cpStr);
833  vVecClear(spJson->vpVecAscii);
834  } else {
835  printf("key: (some or all not printable ASCII)\n");
836  vFmtIndent(spJson->vpFmt, (int)uiIndent);
837  cpNextLine = cpFmtFirstUnicode(spJson->vpFmt, spValue->spKey->uipPhrase, (long int)spValue->spKey->uiLength, 0, 0);
838  while(cpNextLine){
839  printf("%s", cpNextLine);
840  cpNextLine = cpFmtNext(spJson->vpFmt);
841  }
842  }
843  }
844  switch (spValue->uiId) {
845  case JSON_ID_ARRAY:
846  uiChildCount = spValue->uiChildCount;
847  sppChildren = spValue->sppChildren;
848  vIndent(uiIndent);
849  printf("[ values: %"PRIuMAX"\n", (luint) uiChildCount);
850  for (ui = 0; ui < uiChildCount; ui++, sppChildren++) {
851  vReintrantValueDisplay(spJson, *sppChildren);
852  spJson->uiCurrentDepth--;
853  }
854  vIndent(uiIndent);
855  printf("] values: %"PRIuMAX"\n", (luint) uiChildCount);
856  break;
857  case JSON_ID_OBJECT:
858  uiChildCount = spValue->uiChildCount;
859  sppChildren = spValue->sppChildren;
860  vIndent(uiIndent);
861  printf("{ values: %"PRIuMAX"\n", (luint) uiChildCount);
862  for (ui = 0; ui < uiChildCount; ui++, sppChildren++) {
863  vReintrantValueDisplay(spJson, *sppChildren);
864  spJson->uiCurrentDepth--;
865  }
866  vIndent(uiIndent);
867  printf("} values: %"PRIuMAX"\n", (luint) uiChildCount);
868  break;
869  case JSON_ID_STRING:
870  spString = spValue->spString;
871  vIndent(uiIndent);
872  if (bIsPhrase32Ascii(spString)) {
873  char* cpStr = (char*)vpVecPushn(spJson->vpVecAscii, NULL, (spString->uiLength + 1));
874  cpPhrase32ToStr(spString, cpStr);
875  printf("string: \"%s\"\n", cpStr);
876  vVecClear(spJson->vpVecAscii);
877  } else {
878  printf("string: (some or all not printable ASCII)\n");
879  vFmtIndent(spJson->vpFmt, (int)uiIndent);
880  cpNextLine = cpFmtFirstUnicode(spJson->vpFmt, spString->uipPhrase, (long int)spString->uiLength, 0, 0);
881  while(cpNextLine){
882  printf("%s", cpNextLine);
883  cpNextLine = cpFmtNext(spJson->vpFmt);
884  }
885  }
886  break;
887  case JSON_ID_NUMBER:
888  spNumber = spValue->spNumber;
889  vIndent(uiIndent);
890  switch (spNumber->uiType) {
891  case JSON_ID_UNSIGNED:
892  printf("number: unsigned int: %"PRIuMAX"\n", (luint) spNumber->uiUnsigned);
893  break;
894  case JSON_ID_SIGNED:
895  printf("number: signed int: %"PRIiMAX"\n", (intmax_t) spNumber->iSigned);
896  break;
897  case JSON_ID_FLOAT:
898  printf("number: float: %g\n", spNumber->dFloat);
899  break;
900  }
901  break;
902  case JSON_ID_TRUE:
903  vIndent(uiIndent);
904  printf("literal: %s\n", s_cpTrue);
905  break;
906  case JSON_ID_FALSE:
907  vIndent(uiIndent);
908  printf("literal: %s\n", s_cpFalse);
909  break;
910  case JSON_ID_NULL:
911  vIndent(uiIndent);
912  printf("literal: %s\n", s_cpNull);
913  break;
914  default:
915  snprintf(caBuf, 128, "unknown record type ID: %"PRIuMAX"", (luint) spValue->uiId);
916  XTHROW(spJson->spException, caBuf);
917  }
918 }
919 
920 static void vBreakIndent(json* spJson, aint uiIndent) {
921  aint ui;
922  vpVecPush(spJson->vpVecOutput, &s_uiLineEnd);
923  if (uiIndent) {
924  for (ui = 0; ui < uiIndent; ui++) {
925  vpVecPush(spJson->vpVecOutput, &s_uiSpace);
926  }
927  }
928 }
929 static void vPushObject(json* spJson, json_value* spValue, abool bArray) {
930  uint32_t uiOpen = bArray ? s_uiOpenSquare : s_uiOpenCurly;
931  uint32_t uiClose = bArray ? s_uiCloseSquare : s_uiCloseCurly;
932  aint ui;
933  vpVecPush(spJson->vpVecOutput, &uiOpen);
934  spJson->uiCurrentDepth += 2;
935  vBreakIndent(spJson, spJson->uiCurrentDepth);
936  for (ui = 0; ui < spValue->uiChildCount; ui++) {
937  if (ui) {
938  vpVecPush(spJson->vpVecOutput, &s_uiComma);
939  vBreakIndent(spJson, spJson->uiCurrentDepth);
940  }
941  vPushValue(spJson, spValue->sppChildren[ui]);
942  }
943  spJson->uiCurrentDepth -= 2;
944  vBreakIndent(spJson, spJson->uiCurrentDepth);
945  vpVecPush(spJson->vpVecOutput, &uiClose);
946 }
947 static void vPushString(json* spJson, u32_phrase* spString) {
948  aint ui;
949  char caBuf[64];
950  vpVecPush(spJson->vpVecOutput, &s_uiQuote);
951  uint32_t uiChar;
952  for (ui = 0; ui < spString->uiLength; ui++) {
953  uiChar = spString->uipPhrase[ui];
954  if(uiChar == 0x5C){
955  // escape reverse solidus
956  vpVecPush(spJson->vpVecOutput, &uiChar);
957  vpVecPush(spJson->vpVecOutput, &uiChar);
958  }else if(uiChar == 0x22){
959  // escape quote
960  vpVecPush(spJson->vpVecOutput, &s_uiReverseSolidus);
961  vpVecPush(spJson->vpVecOutput, &uiChar);
962  }else if(uiChar >= 0 && uiChar < 0x20){
963  // escape control characters
964  vpVecPush(spJson->vpVecOutput, &s_uiReverseSolidus);
965  vpVecPush(spJson->vpVecOutput, &s_uiLowerU);
966  snprintf(caBuf, 64, "%04X", uiChar);
967  uiChar = (uint32_t)caBuf[0];
968  vpVecPush(spJson->vpVecOutput, &uiChar);
969  uiChar = (uint32_t)caBuf[1];
970  vpVecPush(spJson->vpVecOutput, &uiChar);
971  uiChar = (uint32_t)caBuf[2];
972  vpVecPush(spJson->vpVecOutput, &uiChar);
973  uiChar = (uint32_t)caBuf[3];
974  vpVecPush(spJson->vpVecOutput, &uiChar);
975  }else if(uiChar >= 0xD800 && uiChar < 0xDFFF){
976  // escape control characters
977  XTHROW(spJson->spException, "string has code point value in surrogate pair range ([0xD800 - 0xDFFF])");
978  }else if(uiChar > 0x10FFFF){
979  // escape control characters
980  XTHROW(spJson->spException, "string has code point out of range (<0x10FFFF)");
981  }else{
982  vpVecPush(spJson->vpVecOutput, &uiChar);
983  }
984  }
985  vpVecPush(spJson->vpVecOutput, &s_uiQuote);
986 }
987 static void vPushNumber(json* spJson, json_number* spNumber) {
988  aint uiLen;
989  char caBuf[64];
990  uint32_t uiBuf[64];
991  if (spNumber->uiType == JSON_ID_FLOAT) {
992  snprintf(caBuf, 64, "%.16G", spNumber->dFloat);
993  } else if (spNumber->uiType == JSON_ID_UNSIGNED) {
994  snprintf(caBuf, 64, "%"PRIuMAX"", spNumber->uiUnsigned);
995  } else if (spNumber->uiType == JSON_ID_SIGNED) {
996  snprintf(caBuf, 64, "%"PRIiMAX"", spNumber->iSigned);
997  }
998  uint32_t* uip = uiBuf;
999  char* cp = caBuf;
1000  uiLen = 0;
1001  while (*cp) {
1002  *uip++ = (uint32_t) *cp++;
1003  uiLen++;
1004  }
1005  vpVecPushn(spJson->vpVecOutput, uiBuf, uiLen);
1006 }
1007 
1008 static void vPushValue(json* spJson, json_value* spValue) {
1009  if(spJson->bFirstNode){
1010  spJson->bFirstNode = APG_FALSE;
1011  }else{
1012  if (spValue->spKey) {
1013  vPushString(spJson, spValue->spKey);
1014  vpVecPush(spJson->vpVecOutput, &s_uiColon);
1015  vpVecPush(spJson->vpVecOutput, &s_uiSpace);
1016  }
1017  }
1018  if (spValue->uiId == JSON_ID_OBJECT) {
1019  vPushObject(spJson, spValue, APG_FALSE);
1020  } else if (spValue->uiId == JSON_ID_ARRAY) {
1021  vPushObject(spJson, spValue, APG_TRUE);
1022  } else {
1023  switch (spValue->uiId) {
1024  case JSON_ID_STRING:
1025  vPushString(spJson, spValue->spString);
1026  break;
1027  case JSON_ID_NUMBER:
1028  vPushNumber(spJson, spValue->spNumber);
1029  break;
1030  case JSON_ID_TRUE:
1031  vpVecPushn(spJson->vpVecOutput, s_uiaTrue, s_uiTrueLen);
1032  break;
1033  case JSON_ID_FALSE:
1034  vpVecPushn(spJson->vpVecOutput, s_uiaFalse, s_uiFalseLen);
1035  break;
1036  case JSON_ID_NULL:
1037  vpVecPushn(spJson->vpVecOutput, s_uiaNull, s_uiNullLen);
1038  break;
1039  default:
1040  XTHROW(spJson->spException, "unrecognized value type");
1041  break;
1042  }
1043  }
1044 }
1045 static void vWalkCount(json* spJson, json_value* spValue){
1046  aint ui;
1047  switch(spValue->uiId){
1048  case JSON_ID_STRING:
1049  case JSON_ID_NUMBER:
1050  case JSON_ID_TRUE:
1051  case JSON_ID_FALSE:
1052  case JSON_ID_NULL:
1053  spJson->uiWalkCount++;
1054  break;
1055  case JSON_ID_OBJECT:
1056  case JSON_ID_ARRAY:
1057  spJson->uiWalkCount++;
1058  for(ui = 0; ui < spValue->uiChildCount; ui++){
1059  vWalkCount(spJson, spValue->sppChildren[ui]);
1060  }
1061  break;
1062  default:
1063  XTHROW(spJson->spException, "tree walk sanity check: unrecognized value id");
1064  break;
1065  }
1066 }
1067 
json_number::iSigned
int64_t iSigned
If uiType = JSON_ID_SIGNED, the signed int value.
Definition: json.h:82
line::uiLineLength
aint uiLineLength
The number of characters in the line, including the line end characters.
Definition: lines.h:43
spJsonIteratorCtor
json_iterator * spJsonIteratorCtor(json *spJson)
Private function for internal object use only. Never called by the application.
Definition: json.c:561
json_number::dFloat
double dFloat
If uiType = JSON_ID_FLOAT, the floating point value.
Definition: json.h:80
APG_INFINITE
#define APG_INFINITE
Definition: apg.h:320
json_value_tag::spString
u32_phrase * spString
Pointer to the string value if uiId = JSON_ID_STRING.
Definition: json.h:110
vpParserCtor
void * vpParserCtor(exception *spException, void *vpParserInit)
The parser's constructor for file initialization data.
Definition: parser.c:67
json::vpVecAscii
void * vpVecAscii
A scratch vector for constructing ASCII strings on the fly.
Definition: jsonp.h:110
json::vpVecIterators
void * vpVecIterators
A vector of iterator context pointers remembered for destruction.
Definition: jsonp.h:101
vpLinesCtor
void * vpLinesCtor(exception *spEx, const char *cpInput, aint uiLength)
The lines object constructor.
Definition: lines.c:85
parser_state::uiSuccess
aint uiSuccess
True (>0) if the input string was matched in its entirety, false (0) otherwise.
Definition: parser.h:184
vpJsonChildren
void * vpJsonChildren(void *vpCtx, json_value *spValue)
Initialize the iterator over the children of the given value as the parent node.
Definition: json.c:530
vMemDtor
void vMemDtor(void *vpCtx)
Destroys a Memory component. Frees all memory allocated.
Definition: memory.c:141
json
The object context. For intenrnal use only.
Definition: jsonp.h:95
vpJsonFindKeyA
void * vpJsonFindKeyA(void *vpCtx, const char *cpKey, json_value *spValue)
Find JSON values with a specified ASCII key.
Definition: json.c:434
vpJsonReadFile
void * vpJsonReadFile(void *vpCtx, const char *cpFileName)
The JSON file reader.
Definition: json.c:207
json_iterator
A JSON interator object context.
Definition: jsonp.h:157
json_number
The structure of a JSON number value.
Definition: json.h:73
vVecDtor
void vVecDtor(void *vpCtx)
The vector component destructor.
Definition: vector.c:161
u32_phrase::uiLength
uint32_t uiLength
The number of integers in the array.
Definition: lib.h:75
cpFmtFirstBytes
const char * cpFmtFirstBytes(void *vpCtx, const uint8_t *ucpBytes, uint64_t uiLength, int iStyle, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over an array of 8-bit byte data.
Definition: format.c:210
json::spCurrentFrame
frame * spCurrentFrame
Points to the current stack frame.
Definition: jsonp.h:126
cpPhrase32ToStr
char * cpPhrase32ToStr(u32_phrase *spPhrase, char *cpStr)
Convert a 32-bit phrase to a null-terminated ASCII string.
Definition: tools.c:382
vJsonDisplayInput
void vJsonDisplayInput(void *vpCtx, abool bShowLines)
Display the input JSON byte stream.
Definition: json.c:365
json::spException
exception * spException
Pointer to the exception structure for reporting errors to the application catch block.
Definition: jsonp.h:97
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
json::spValues
json_value * spValues
an array of absolute values.
Definition: jsonp.h:113
bIsPhrase32Ascii
abool bIsPhrase32Ascii(u32_phrase *spPhrase)
Determine if a 32-bit phrase consists entirely of printable ASCII characters.
Definition: tools.c:405
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
vpConvCtor
void * vpConvCtor(exception *spEx)
The data conversion object constructor.
Definition: conv.c:134
FMT_CANONICAL
#define FMT_CANONICAL
Display lines with both FMT_HEX and FMT_ASCII formats.
Definition: format.h:55
json::uiCurrentDepth
aint uiCurrentDepth
Used to keep track of the current tree depth for display of the tree of values.
Definition: jsonp.h:150
frame
Each value is a node in the parse tree.
Definition: jsonp.h:85
cpFmtNext
const char * cpFmtNext(void *vpCtx)
Formats the next line of data.
Definition: format.c:386
JSON_ID_STRING
#define JSON_ID_STRING
String value.
Definition: json.h:50
json_iterator::spJson
json * spJson
Pointer to the parent JSON object context.
Definition: jsonp.h:159
json-grammar.h
cpFmtFirstUnicode
const char * cpFmtFirstUnicode(void *vpCtx, const uint32_t *uipChars, uint64_t uiLength, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over an array of 32-bit Unicode code points.
Definition: format.c:341
json_iterator::uiContextIndex
aint uiContextIndex
Definition: jsonp.h:164
u32_phrase::uipPhrase
const uint32_t * uipPhrase
Pointer to an array of 32-bit unsigned integers.
Definition: lib.h:74
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
json::vpConv
void * vpConv
Context pointer for a conversion object.
Definition: jsonp.h:148
JSON_ID_ARRAY
#define JSON_ID_ARRAY
Array value.
Definition: json.h:49
value_r
This is the "relative" value developed during parsing.
Definition: jsonp.h:68
vpJsonFindKeyU
void * vpJsonFindKeyU(void *vpCtx, const uint32_t *uipKey, aint uiLength, json_value *spValue)
Find JSON values with the specified 32-bit Unicode key.
Definition: json.c:474
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
json_value_tag::uiId
aint uiId
The type of value. One of.
Definition: json.h:100
JSON_ID_FALSE
#define JSON_ID_FALSE
Literal value is false.
Definition: json.h:53
parser_config
Defines the input string and other configuration parameters for the parser,.
Definition: parser.h:198
JSON_ID_OBJECT
#define JSON_ID_OBJECT
Object value.
Definition: json.h:48
json::vpVecInput
void * vpVecInput
The UTF-8-encoded input byte stream. BOM, if any, removed.
Definition: jsonp.h:105
conv_dst::uiDataType
aint uiDataType
[in] One of the encoding type identifiers, UTF_8, etc.
Definition: conv.h:121
json::bFirstNode
abool bFirstNode
Set to true before each call to sJsonWrite() to prevent writing a key for the first node of a sub-tre...
Definition: jsonp.h:149
json_iterator::vpVec
void * vpVec
Work vector.
Definition: jsonp.h:160
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
json::bHasFrac
abool bHasFrac
A working value signaling presence of fractional value for a number value.
Definition: jsonp.h:129
uiVecLen
aint uiVecLen(void *vpCtx)
Get the vector length. That is, the number of elements on the vector.
Definition: vector.c:385
json::vpMem
void * vpMem
Pointer to a memory object used for all memory allocations.
Definition: jsonp.h:99
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
conv_dst
Defines the output data type, location, length and whether or not to preface with a Byte Order Mark (...
Definition: conv.h:120
JSON_ID_TRUE
#define JSON_ID_TRUE
Literal value is true.
Definition: json.h:52
vJsonDisplayValue
void vJsonDisplayValue(void *vpCtx, json_value *spValue, aint uiDepth)
Display a value and optionally the values in the branch below, if any.
Definition: json.c:412
parser_state
The parser's final state.
Definition: parser.h:183
json::uiChar
uint32_t uiChar
A working value to hold the value of a single character. Higher level rules will move it to vpVecChar...
Definition: jsonp.h:127
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
bJsonValidate
abool bJsonValidate(void *vpCtx)
Validate a JSON context pointer.
Definition: json.c:188
string_r
This is the "relative" string developed during parsing.
Definition: jsonp.h:55
ucpJsonWrite
uint8_t * ucpJsonWrite(void *vpCtx, json_value *spValue, aint *uipCount)
Converts a sub-tree of values into UTF-8 byte stream of JSON text.
Definition: json.c:329
json::uiStringCount
aint uiStringCount
The number of strings in the array.
Definition: jsonp.h:118
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
spJsonIteratorFirst
json_value * spJsonIteratorFirst(void *vpIteratorCtx)
Find the first value in the list represented by this iterator.
Definition: json.c:613
json_value_tag::uiChildCount
aint uiChildCount
The number of child values if uiId is JSON_ID_OBJECT or JSON_ID_ARRAY.
Definition: json.h:115
line::uiLineIndex
aint uiLineIndex
The zero-based line index.
Definition: lines.h:41
bExValidate
abool bExValidate(exception *spException)
Test an exception structure for validity.
Definition: exception.c:70
exception::vpValidate
const void * vpValidate
Used by the memory object to validate the exception structure.
Definition: exception.h:48
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
JSON_ID_FLOAT
#define JSON_ID_FLOAT
Number value is a double floating point number.
Definition: json.h:62
vpVecPushn
void * vpVecPushn(void *vpCtx, void *vpElement, aint uiCount)
Adds one or more elements to the end of the array.
Definition: vector.c:221
json::uiMaxDepth
aint uiMaxDepth
The maximum tree depth of values to display.
Definition: jsonp.h:151
json_value_tag::spNumber
json_number * spNumber
Pointer to the number value if uiId = JSON_ID_NUMBER.
Definition: json.h:111
line
Defines the characteristics of a single line.
Definition: lines.h:40
jsonp.h
Private JSON component header file.
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
json::uiValueCount
aint uiValueCount
The number of values in the array.
Definition: jsonp.h:114
json::vpVecScratch32
void * vpVecScratch32
A vector of 32-bit integer scratch space.
Definition: jsonp.h:136
spJsonIteratorNext
json_value * spJsonIteratorNext(void *vpIteratorCtx)
Find the next value in the list represented by this iterator.
Definition: json.c:647
json::vpVecOutput
void * vpVecOutput
Vector of 32-bit code points for generating output of value tree to JSON-text.
Definition: jsonp.h:147
vConvEncode
void vConvEncode(void *vpCtx, conv_dst *spDst)
Encode the 32-bit Unicode code points to a byte stream.
Definition: conv.c:302
json::vpLines
void * vpLines
pointer to a lines object context
Definition: jsonp.h:106
json_iterator::uiCount
aint uiCount
The number of pointers in the list.
Definition: jsonp.h:162
uiJsonIteratorCount
aint uiJsonIteratorCount(void *vpIteratorCtx)
Find the number of values in the list represented by this iterator.
Definition: json.c:691
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
json_iterator::sppValues
json_value ** sppValues
List of pointers to values.
Definition: jsonp.h:161
json::acpInput
achar * acpInput
Buffer to hold the input converted from uint8_t to achar units.
Definition: jsonp.h:145
spLinesFirst
line * spLinesFirst(void *vpCtx)
Initialize an iterator over the lines.
Definition: lines.c:170
json_value_tag::spKey
u32_phrase * spKey
Points to the associated key string if this is a member of a JSON object. Otherwise,...
Definition: json.h:108
vLinesDtor
void vLinesDtor(void *vpCtx)
The lines object destructor.
Definition: lines.c:123
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
vJsonIteratorDtor
void vJsonIteratorDtor(void *vpIteratorCtx)
The JSON iterator destructor.
Definition: json.c:591
json_number::uiUnsigned
uint64_t uiUnsigned
If uiType = JSON_ID_UNSIGNED, the unsigned int value.
Definition: json.h:81
UTF_8
#define UTF_8
Data type macro for UTF-8 encoding/decoding.
Definition: conv.h:77
json_iterator::vpValidate
const void * vpValidate
Must be the "magic number" to be a valid context.
Definition: jsonp.h:158
json::vpValidate
const void * vpValidate
Must be the "magic number" to be a valid context.
Definition: jsonp.h:96
conv_dst::uiDataLen
aint uiDataLen
[out] Number of bytes in the byte stream.
Definition: conv.h:124
vpJsonReadArray
void * vpJsonReadArray(void *vpCtx, uint8_t *ucpData, aint uiDataLen)
The JSON array reader.
Definition: json.c:289
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
json.h
Header file for the JSON component. Defines API prototypes.
JSON_ID_SIGNED
#define JSON_ID_SIGNED
Number value is a 64-bit signed integer.
Definition: json.h:63
vpJsonCtor
void * vpJsonCtor(exception *spEx)
The JSON constructor.
Definition: json.c:115
vJsonDtor
void vJsonDtor(void *vpCtx)
The JSON Parser component destructor.
Definition: json.c:165
JSON_ID_UNSIGNED
#define JSON_ID_UNSIGNED
Number value is a 64-bit unsigned integer.
Definition: json.h:64
json::vpFmt
void * vpFmt
Pointer to a hexdump-style formatter object.
Definition: jsonp.h:146
spJsonIteratorPrev
json_value * spJsonIteratorPrev(void *vpIteratorCtx)
Find the prev value in the list represented by this iterator.
Definition: json.c:671
json_value_tag::sppChildren
struct json_value_tag ** sppChildren
Points to a list of child value pointers if uiId is JSON_ID_OBJECT or JSON_ID_ARRAY.
Definition: json.h:113
vFmtDtor
void vFmtDtor(void *vpCtx)
The object destructor.
Definition: format.c:146
json_number::uiType
aint uiType
Identifies the number type. One of.
Definition: json.h:74
json::uiWalkCount
aint uiWalkCount
An accumulator for counting sub-tree nodes and child nodes.
Definition: jsonp.h:139
json::bHasMinus
abool bHasMinus
A working value signaling a minus sign for a number value.
Definition: jsonp.h:130
u32_phrase
Defines a pointer to an array of 32-bit unsigned integers plus its length. Typically needed by Unicod...
Definition: lib.h:73
JSON_ID_NULL
#define JSON_ID_NULL
Literal value is null.
Definition: json.h:54
vpJsonTree
void * vpJsonTree(void *vpCtx, json_value *spValue)
Initialize the iterator to walk a value tree.
Definition: json.c:501
json_value_tag
The structure of a JSON value.
Definition: json.h:99
vConvDtor
void vConvDtor(void *vpCtx)
Conversion object destructor.
Definition: conv.c:161
vFmtIndent
void vFmtIndent(void *vpCtx, int iIndent)
Set the an indentation for the display.
Definition: format.c:181
spJsonIteratorLast
json_value * spJsonIteratorLast(void *vpIteratorCtx)
Find the last value in the list represented by this iterator.
Definition: json.c:627
json::spIn
FILE * spIn
File I/O handle for the input file. Maintained here so that it can be closed in the destructor if nec...
Definition: jsonp.h:142
json::vpParser
void * vpParser
Pointer to the parser context if exception thrown during parsing.
Definition: jsonp.h:144
conv_dst::ucpData
uint8_t * ucpData
[out] Pointer to the output byte stream. Valid until another function call on the context handle.
Definition: conv.h:123
vpFmtCtor
void * vpFmtCtor(exception *spEx)
The object constructor.
Definition: format.c:118
vpJsonGrammarInit
void * vpJsonGrammarInit
Definition: json-grammar.c:1631
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
json_iterator::uiCurrent
aint uiCurrent
The current iterator value index.
Definition: jsonp.h:163
vConvUseCodePoints
void vConvUseCodePoints(void *vpCtx, uint32_t *uipSrc, aint uiSrcLen)
Insert a stream of 32-bit Unicode code points as the intermediate data.
Definition: conv.c:395
JSON_ID_NUMBER
#define JSON_ID_NUMBER
Number value.
Definition: json.h:51
vVecClear
void vVecClear(void *vpCtx)
Clears all used elements in a vector component.
Definition: vector.c:420
vUtilPrintParserState
void vUtilPrintParserState(parser_state *spState)
Display the parser state in human-readable format to stdout.
Definition: utilities.c:727
line::uiCharIndex
aint uiCharIndex
The zero-based index of the first character of the line.
Definition: lines.h:42
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
vJsonGrammarRuleCallbacks
void vJsonGrammarRuleCallbacks(void *vpParserCtx)
Definition: parser-callbacks.c:718
vParserParse
void vParserParse(void *vpCtx, parser_config *spConfig, parser_state *spState)
Parse an input string of alphabet characters.
Definition: parser.c:268
uiLinesCount
aint uiLinesCount(void *vpCtx)
Returns the number of lines of text.
Definition: lines.c:202
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.