Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
main.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 * *************************************************************************************/
71 #include "main.h"
72 
73 #include "source.h"
74 
75 static char* cpMakeFileName(char* cpBuffer, const char* cpBase, const char* cpDivider, const char* cpName){
76  strcpy(cpBuffer, cpBase);
77  strcat(cpBuffer, cpDivider);
78  strcat(cpBuffer, cpName);
79  return cpBuffer;
80 }
81 
82 static char s_caBuf[2*PATH_MAX];
83 
84 static char* s_cpDescription =
85  "Example demonstrating the use and usefulness of the AST.";
86 
87 static char* s_cppCases[] = {
88  "Display application information.",
89  "Build the JSON test file from the XML test file using the APG XML parser. Must be run before other tests.",
90  "Parse all of the valid tests.",
91  "Parse all of the invalid tests.",
92  "Trace test with JSON ID number = arg2.",
93 };
94 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
95 
96 static int iHelp(void){
97  long int i = 0;
99  printf("description: %s\n", s_cpDescription);
100  printf(" usage: ex-trace [arg]\n");
101  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
102  printf(" execute case number n\n");
103  printf(" arg = anything else, or nothing at all\n");
104  printf(" print this help screen\n");
105  printf("\n");
106  for(; i < s_iCaseCount; i++){
107  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
108  }
109  return EXIT_SUCCESS;
110 }
111 
112 static int iApp() {
113  // print the current working directory
115  printf("\n");
116 
117  // display the current APG sizes and macros
118  vUtilApgInfo();
119  return EXIT_SUCCESS;
120 }
121 static abool bMatchU32PhraseAscii(const char* cpString, u32_phrase* spPhrase){
122  abool bReturn = APG_FALSE;
123  if(strlen(cpString) == (size_t)spPhrase->uiLength){
124  aint ui = 0;
125  for(; ui < spPhrase->uiLength; ui++){
126  if(spPhrase->uipPhrase[ui] != (uint32_t)cpString[ui]){
127  return bReturn;
128  }
129  }
130  bReturn = APG_TRUE;
131  }
132  return bReturn;
133 }
134 static abool bMatchU32PhraseAchar(const achar* acpString, u32_phrase* spPhrase){
135  abool bReturn = APG_FALSE;
136  aint ui = 0;
137  for(; ui < spPhrase->uiLength; ui++){
138  if(spPhrase->uipPhrase[ui] != (uint32_t)acpString[ui]){
139  return bReturn;
140  }
141  }
142  bReturn = APG_TRUE;
143  return bReturn;
144 }
145 static void* vpGetConstraintsIterator(exception* spException, void* vpJson, void* vpItRoot){
146  // set up the constraints iterator
147  void* vpItKey = vpJsonFindKeyA(vpJson, "constraints", spJsonIteratorFirst(vpItRoot));
148  if(!vpItKey){
149  XTHROW(spException, "could not find \"constraints\" key");
150  }
151  json_value* spArray = spJsonIteratorFirst(vpItKey);
152  if(spArray->uiId != JSON_ID_ARRAY){
153  XTHROW(spException, "\"constraints\" member not an array");
154  }
155  void* vpItConstraints = vpJsonChildren(vpJson, spArray);
156  if(!vpItConstraints){
157  XTHROW(spException, "could not find \"constraint\" members");
158  }
159  return vpItConstraints;
160 }
161 
162 static aint uiGetTestId(exception* spEx, void* vpJson, json_value* spTest){
163  void* vpItKey;
164  json_value* spChild, *spChildEnd;
165  spChild = *spTest->sppChildren;
166  spChildEnd = spChild + spTest->uiChildCount;
167  for(; spChild < spChildEnd; spChild++){
168  if(bMatchU32PhraseAscii("ID", spChild->spKey)){
169  // found ruleId
170  goto foundruleid;
171  }
172  }
173  XTHROW(spEx, "expected key ID not found");
174  foundruleid:;
175  if((spChild->uiId != JSON_ID_NUMBER) || (spChild->spNumber->uiType != JSON_ID_UNSIGNED)){
176  XTHROW(spEx, "ID value not unsigned int");
177  }
178  if(spChild->spNumber->uiUnsigned > APG_MAX_AINT){
179  XTHROW(spEx, "ID value too big - > APG_MAX_AINT");
180  }
181  return (aint)spChild->spNumber->uiUnsigned;
182 }
183 static aint uiGetRuleId(exception* spEx, void* vpJson, json_value* spTest){
184  void* vpItKey;
185  json_value* spChild, *spChildEnd;
186  spChild = *spTest->sppChildren;
187  spChildEnd = spChild + spTest->uiChildCount;
188  for(; spChild < spChildEnd; spChild++){
189  if(bMatchU32PhraseAscii("ruleId", spChild->spKey)){
190  // found ruleId
191  goto foundruleid;
192  }
193  }
194  XTHROW(spEx, "expected key ruleId not found");
195  foundruleid:;
196  if((spChild->uiId != JSON_ID_NUMBER) || (spChild->spNumber->uiType != JSON_ID_UNSIGNED)){
197  XTHROW(spEx, "ruleId value not unsigned int");
198  }
199  if(spChild->spNumber->uiUnsigned > APG_MAX_AINT){
200  XTHROW(spEx, "ruleId value too big - > APG_MAX_AINT");
201  }
202  return (aint)spChild->spNumber->uiUnsigned;
203 }
204 static aint uiGetInput(exception* spEx, void* vpJson, json_value* spTest, achar* acpBuf, aint uiBufLen){
205  void* vpItKey;
206  json_value* spChild, *spChildEnd;
207  spChild = *spTest->sppChildren;
208  spChildEnd = spChild + spTest->uiChildCount;
209  for(; spChild < spChildEnd; spChild++){
210  if(bMatchU32PhraseAscii("input", spChild->spKey)){
211  // found ruleId
212  goto foundruleid;
213  }
214  }
215  XTHROW(spEx, "expected key input not found");
216  foundruleid:;
217  if((spChild->uiId != JSON_ID_STRING)){
218  XTHROW(spEx, "input value not string");
219  }
220  if(spChild->spString->uiLength > uiBufLen){
221  XTHROW(spEx, "input string too long - larger than uiBufLen - increase buffer size and try again");
222  }
223  aint ui = 0;
224  for(; ui < spChild->spString->uiLength; ui++){
225  acpBuf[ui] = (achar)spChild->spString->uipPhrase[ui];
226  }
227  return (aint)spChild->spString->uiLength;
228 }
229 static void pfnConstraintCallback(callback_data* spData){
230  void* vpIt = ((user_data*)spData->vpUserData)->vpIt;
231  abool bTrace = ((user_data*)spData->vpUserData)->bTrace;
232  void* vpItValue = NULL;
233  json_value* spValue;
234  aint ui, uj, uiCount, uiRuleIndex;
235  const uint32_t* uipString;
236  const achar *acpPhrase;
237  json_value* spChild, *spChildEnd;
238  json_value* spMatch, *spMatchEnd;
239  if(spData->uiParserState != ID_ACTIVE){
240  // see if the rule index is in the map
241  json_value* spConstraint = spJsonIteratorFirst(vpIt);
242  while(spConstraint){
243  if(spConstraint->uiId != JSON_ID_OBJECT){
244  XTHROW(spData->spException, "bad constraint");
245  }
246  // find the rule index
247  spChild = *spConstraint->sppChildren;
248  spChildEnd = spChild + spConstraint->uiChildCount;
249  for(; spChild < spChildEnd; spChild++){
250  if(spChild->uiId == JSON_ID_NUMBER && bMatchU32PhraseAscii("ruleId", spChild->spKey)){
251  uiRuleIndex = (aint)spChild->spNumber->uiUnsigned;
252  goto foundruleid;
253  }
254  }
255  XTHROW(spData->spException, "ruleId key not found in constraint object");
256  foundruleid:;
257  if(uiRuleIndex == spData->uiRuleIndex){
258  // find the matched strings
259  spChild = *spConstraint->sppChildren;
260  spChildEnd = spChild + spConstraint->uiChildCount;
261  for(; spChild < spChildEnd; spChild++){
262  if(spChild->uiId == JSON_ID_ARRAY && bMatchU32PhraseAscii("match", spChild->spKey)){
263  // find the string in the matched array
264  acpPhrase = spData->acpString + spData->uiParserOffset;
265  spMatch = *spChild->sppChildren;
266  spMatchEnd = spMatch + spChild->uiChildCount;
267  for(; spMatch < spMatchEnd; spMatch++){
268  if(spMatch->spString->uiLength == (uint32_t)spData->uiParserPhraseLength){
269  if(bMatchU32PhraseAchar(acpPhrase, spMatch->spString)){
270  // match found
271  return;
272  }
273  }
274  }
275  // match not found
276  if(bTrace){
277  printf("=> for rule index %d the parsed phrase did not match any strings in the list\n", (int)uiRuleIndex);
278  }
279  spData->uiCallbackPhraseLength = 0;
280  spData->uiCallbackState = ID_NOMATCH;
281  return;
282  }
283  // keep looking for match key
284  }
285  XTHROW(spData->spException, "match key not found in constraint object");
286  }
287  // keep looking for a rule index match
288  spConstraint = spJsonIteratorNext(vpIt);
289  }
290  }
291 }
292 static void vParseTests(exception* spEx, void* vpParser, void* vpJson, abool bValid, void* vpItConstraints, void* vpItTests){
293  char* cpTestName = bValid ? "valid" : "invalid";
294  printf("Parsing tests: %s\n", cpTestName);
295  parser_config sConfig = {};
296  parser_state sState;
297  aint uiTestId, uiRuleId, uiInputLen;
298  aint uiCount = 0;
299  aint uiSuccessCount = 0;
300  aint uiFailCount = 0;
301  achar acaBuf[1024];
302  aint uiBufLen = 1024;
303  aint ui = 0;
304  for(; ui < RULE_COUNT_ODATA; ui++){
305  vParserSetRuleCallback(vpParser, ui, pfnConstraintCallback);
306  }
307  json_value* spTest = spJsonIteratorFirst(vpItTests);
308  while(spTest){
309  uiTestId = uiGetTestId(spEx, vpJson, spTest);
310  uiRuleId = uiGetRuleId(spEx, vpJson, spTest);
311  uiInputLen = uiGetInput(spEx, vpJson, spTest, acaBuf, uiBufLen);
312  sConfig.acpInput = acaBuf;
313  sConfig.uiInputLength = uiInputLen;
314  sConfig.uiStartRule = uiRuleId;
315  user_data sUserData = {vpItConstraints, APG_FALSE};
316  sConfig.vpUserData = &sUserData;
317  vParserParse(vpParser, &sConfig, &sState);
318  if(sState.uiSuccess){
319  uiSuccessCount++;
320  if(!bValid){
321  printf("test ID: %d: succeeded\n", (int)uiTestId);
322  }
323  }else{
324  if(bValid){
325  printf("test ID: %d: failed\n", (int)uiTestId);
326  }
327  uiFailCount++;
328  }
329  uiCount++;
330  spTest = spJsonIteratorNext(vpItTests);
331  }
332  printf("count: %d: success: %d: fail: %d\n", (int)uiCount, (int)uiSuccessCount, (int)uiFailCount);
333 
334 }
335 static int iTraceTestId(aint uiTraceId){
336  int iReturn = EXIT_SUCCESS;
337  static void* vpJson = NULL;
338  static void* vpParser = NULL;
339  static void* vpTrace = NULL;
340  void* vpItRoot, *vpItKey, *vpItTests, *vpItConstraints;
341  char* cpWhich;
342  parser_config sConfig = {};
343  parser_state sState;
344  json_value* spTest;
345  aint uiTestId, uiRuleId, uiInputLen;
346  achar acaBuf[1024];
347  aint uiBufLen = 1024;
348  exception e;
349  XCTOR(e);
350  if(e.try){
351  // try block - construct the API object
352  char* cpDesc = "This program will read the JSON file built in case 2 and parse all of the valid tests.\n";
353  printf("\n");
354  printf("%s", cpDesc);
355  printf("\n");
356 
357  // setup
358  vpParser = vpParserCtor(&e, vpOdataInit);
359  vpTrace = vpTraceCtor(vpParser);
360 // vTraceSetOutput(vpTrace, cpMakeFileName(&s_caBuf[0], SOURCE_DIR, "/../output/", "odata-trace.txt"));
361  aint ui = 0;
362  for(; ui < RULE_COUNT_ODATA; ui++){
363  vParserSetRuleCallback(vpParser, ui, pfnConstraintCallback);
364  }
365  vpJson = vpJsonCtor(&e);
366  char* cpJsonName = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "odata-abnf-testcases.json");
367  vpItRoot = vpJsonReadFile(vpJson, cpJsonName);
368  vpItConstraints = vpGetConstraintsIterator(&e, vpJson, vpItRoot);
369  cpWhich = "valid";
370  vpItKey = vpJsonFindKeyA(vpJson, "valid", spJsonIteratorFirst(vpItRoot));
371  if(!vpItKey){
372  XTHROW(&e, "could not find \"valid\" key");
373  }
374  json_value* spArray = spJsonIteratorFirst(vpItKey);
375  if(spArray->uiId != JSON_ID_ARRAY){
376  XTHROW(&e, "\"valid\" member not an array");
377  }
378  vpItTests = vpJsonChildren(vpJson, spArray);
379  if(!vpItTests){
380  XTHROW(&e, "could not find \"valid\" tests");
381  }
382  spTest = spJsonIteratorFirst(vpItTests);
383  while(spTest){
384  uiTestId = uiGetTestId(&e, vpJson, spTest);
385  if(uiTestId == uiTraceId){
386  printf("Trace test: tracing %s test id %d\n", cpWhich, (int)uiTraceId);
387  uiRuleId = uiGetRuleId(&e, vpJson, spTest);
388  uiInputLen = uiGetInput(&e, vpJson, spTest, acaBuf, uiBufLen);
389  sConfig.acpInput = acaBuf;
390  sConfig.uiInputLength = uiInputLen;
391  sConfig.uiStartRule = uiRuleId;
392  user_data sUserData = {vpItConstraints, APG_TRUE};
393  sConfig.vpUserData = &sUserData;
394  vParserParse(vpParser, &sConfig, &sState);
395  if(sState.uiSuccess){
396  printf("TRACE TEST: %d: success\n", (int)uiTraceId);
397  }else{
398  printf("TRACE TEST: %d: failure\n", (int)uiTraceId);
399  }
400  return iReturn;
401  }
402  spTest = spJsonIteratorNext(vpItTests);
403  }
404  // not found in valid tests
405  cpWhich = "invalid";
406  vpItKey = vpJsonFindKeyA(vpJson, "invalid", spJsonIteratorFirst(vpItRoot));
407  if(!vpItKey){
408  XTHROW(&e, "could not find \"invalid\" key");
409  }
410  spArray = spJsonIteratorFirst(vpItKey);
411  if(spArray->uiId != JSON_ID_ARRAY){
412  XTHROW(&e, "\"valid\" member not an array");
413  }
414  vpItTests = vpJsonChildren(vpJson, spArray);
415  if(!vpItTests){
416  XTHROW(&e, "could not find \"invalid\" tests");
417  }
418  spTest = spJsonIteratorFirst(vpItTests);
419  while(spTest){
420  uiTestId = uiGetTestId(&e, vpJson, spTest);
421  if(uiTestId == uiTraceId){
422  printf("Trace test: tracing %s test id %d\n", cpWhich, (int)uiTraceId);
423  uiRuleId = uiGetRuleId(&e, vpJson, spTest);
424  uiInputLen = uiGetInput(&e, vpJson, spTest, acaBuf, uiBufLen);
425  sConfig.acpInput = acaBuf;
426  sConfig.uiInputLength = uiInputLen;
427  sConfig.uiStartRule = uiRuleId;
428  user_data sUserData = {vpItConstraints, APG_TRUE};
429  sConfig.vpUserData = &sUserData;
430  vParserParse(vpParser, &sConfig, &sState);
431  if(sState.uiSuccess){
432  printf("TRACE TEST: %d: success\n", (int)uiTraceId);
433  }else{
434  printf("TRACE TEST: %d: failure\n", (int)uiTraceId);
435  }
436  return iReturn;
437  }
438  spTest = spJsonIteratorNext(vpItTests);
439  }
440  printf("TRACE TEST: test id %d not found\n", (int)uiTraceId);
441  }else{
442  // catch block - display the exception location and message
444  iReturn = EXIT_FAILURE;
445  }
446 
447  vParserDtor(vpParser);
448  vJsonDtor(vpJson);
449  return iReturn;
450 }
451 
452 static int iParseValid(){
453  int iReturn = EXIT_SUCCESS;
454  static void* vpJson = NULL;
455  static void* vpParser = NULL;
456  void* vpItRoot, *vpItKey, *vpItTests, *vpItConstraints;
457  json_value* spArray;
458  exception e;
459  XCTOR(e);
460  if(e.try){
461  // try block - construct the API object
462  char* cpDesc = "This program will read the JSON file built in case 2 and parse all of the valid tests.\n";
463  printf("\n");
464  printf("%s", cpDesc);
465  printf("\n");
466 
467  // setup
468  vpParser = vpParserCtor(&e, vpOdataInit);
469  vpJson = vpJsonCtor(&e);
470  char* cpJsonName = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "odata-abnf-testcases.json");
471  vpItRoot = vpJsonReadFile(vpJson, cpJsonName);
472  vpItConstraints = vpGetConstraintsIterator(&e, vpJson, vpItRoot);
473 
474  // set up the valid tests iterator
475  vpItKey = vpJsonFindKeyA(vpJson, "valid", spJsonIteratorFirst(vpItRoot));
476  if(!vpItKey){
477  XTHROW(&e, "could not find \"valid\" key");
478  }
479  spArray = spJsonIteratorFirst(vpItKey);
480  if(spArray->uiId != JSON_ID_ARRAY){
481  XTHROW(&e, "\"valid\" member not an array");
482  }
483  vpItTests = vpJsonChildren(vpJson, spArray);
484  if(!vpItTests){
485  XTHROW(&e, "could not find \"valid\" tests");
486  }
487  vParseTests(&e, vpParser, vpJson, APG_TRUE, vpItConstraints, vpItTests);
488  }else{
489  // catch block - display the exception location and message
491  iReturn = EXIT_FAILURE;
492  }
493 
494  vParserDtor(vpParser);
495  vJsonDtor(vpJson);
496  return iReturn;
497 }
498 
499 static int iParseInvalid(){
500  int iReturn = EXIT_SUCCESS;
501  static void* vpJson = NULL;
502  static void* vpParser = NULL;
503  void* vpItRoot, *vpItKey, *vpItTests, *vpItConstraints;
504  exception e;
505  XCTOR(e);
506  if(e.try){
507  // try block - construct the API object
508  char* cpDesc = "This program will read the JSON file built in case 2 and parse all of the valid tests.\n";
509  printf("\n");
510  printf("%s", cpDesc);
511  printf("\n");
512 
513  // setup
514  vpParser = vpParserCtor(&e, vpOdataInit);
515  vpJson = vpJsonCtor(&e);
516  char* cpJsonName = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "odata-abnf-testcases.json");
517  vpItRoot = vpJsonReadFile(vpJson, cpJsonName);
518  vpItConstraints = vpGetConstraintsIterator(&e, vpJson, vpItRoot);
519  vpItKey = vpJsonFindKeyA(vpJson, "invalid", spJsonIteratorFirst(vpItRoot));
520  if(!vpItKey){
521  XTHROW(&e, "could not find \"valid\" key");
522  }
523  json_value* spArray = spJsonIteratorFirst(vpItKey);
524  if(spArray->uiId != JSON_ID_ARRAY){
525  XTHROW(&e, "\"invalid\" member not an array");
526  }
527  vpItTests = vpJsonChildren(vpJson, spArray);
528  if(!vpItTests){
529  XTHROW(&e, "could not find \"invalid\" tests");
530  }
531  vParseTests(&e, vpParser, vpJson, APG_FALSE, vpItConstraints, vpItTests);
532  }else{
533  // catch block - display the exception location and message
535  iReturn = EXIT_FAILURE;
536  }
537 
538  vParserDtor(vpParser);
539  vJsonDtor(vpJson);
540  return iReturn;
541 }
542 static abool bCompU32(u32_phrase* spL, u32_phrase* spR){
543  abool bReturn = APG_FALSE;
544  if(spL->uiLength == spR->uiLength){
545  uint32_t ui = 0;
546  for(;ui < spL->uiLength; ui++){
547  if(spL->uipPhrase[ui] != spR->uipPhrase[ui]){
548  goto fail;
549  }
550  }
551  bReturn = APG_TRUE;
552  }
553  fail:;
554  return bReturn;
555 }
556 static void vStartTag(u32_phrase* spName, u32_phrase* spAttNames, u32_phrase* spAttValues, uint32_t uiAttCount, void* vpCtx){
557  xml_context* spCtx = (xml_context*)vpCtx;
558  if(bCompU32(spName, spCtx->spConstraint)){
559  if(bCompU32(spAttNames, spCtx->spRule)){
560  cpUint32ToStr((uint32_t*)spAttValues->uipPhrase, (aint)spAttValues->uiLength, spCtx->caBuf);
561  aint uiRuleId = uiParserRuleLookup(spCtx->vpOdataParser, spCtx->caBuf);
562  if(uiRuleId >= spCtx->uiRuleCount){
563  XTHROW(spCtx->spException, "rule name not found");
564  }
565  spCtx->spCurrentConstraint = (rule_constraint*)vpVecAt(spCtx->vpVecContraintRules, uiRuleId);
566  spCtx->spCurrentConstraint->uiRuleIndex = uiRuleId;
567  spCtx->spCurrentConstraint->cpRuleName = cpParserRuleName(spCtx->vpOdataParser, uiRuleId);
569  spCtx->spCurrentConstraint->uiCount = 0;
570  }else{
571  XTHROW(spCtx->spException, "vStartTag: Constraint node must have a \"Rule\" attribute");
572  }
573  }else if(bCompU32(spName, spCtx->spTestCase)){
574  abool bName = APG_FALSE;
575  abool bRule = APG_FALSE;
576  spCtx->spCurrentTest = (test*)vpVecPush(spCtx->vpVecTests, NULL);
577  uint32_t ui = 0;
578  for(; ui < uiAttCount; ui++, spAttNames++, spAttValues++){
579  if(bCompU32(spAttNames, spCtx->spName)){
580  bName = APG_TRUE;
581  spCtx->spCurrentTest->sName.uiIndex = uiVecLen(spCtx->vpVec32);
582  spCtx->spCurrentTest->sName.uiLength = spAttValues->uiLength;
583  vpVecPushn(spCtx->vpVec32, (uint32_t*)spAttValues->uipPhrase, spAttValues->uiLength);
584  }
585  if(bCompU32(spAttNames, spCtx->spRule)){
586  bRule = APG_TRUE;
587  spCtx->spCurrentTest->sRule.uiIndex = uiVecLen(spCtx->vpVec32);
588  spCtx->spCurrentTest->sRule.uiLength = spAttValues->uiLength;
589  vpVecPushn(spCtx->vpVec32, (uint32_t*)spAttValues->uipPhrase, spAttValues->uiLength);
590  if(spAttValues->uiLength >= sizeof(spCtx->caBuf)){
591  XTHROW(spCtx->spException, "character buffer too small for name conversion to string");
592  }
593  cpUint32ToStr((uint32_t*)spAttValues->uipPhrase, (aint)spAttValues->uiLength, spCtx->caBuf);
594  spCtx->spCurrentTest->uiRuleId = uiParserRuleLookup(spCtx->vpOdataParser, spCtx->caBuf);
595  if(spCtx->spCurrentTest->uiRuleId >= spCtx->uiRuleCount){
596  XTHROW(spCtx->spException, "rule name not found");
597  }
598  }
599  if(bCompU32(spAttNames, spCtx->spFailAt)){
600  spCtx->spCurrentTest->bFail = APG_TRUE;
601  const uint32_t* uipDigit = spAttValues->uipPhrase;
602  const uint32_t* uipDigitEnd = uipDigit + spAttValues->uiLength;
603  uint32_t uiNum = *uipDigit++ - 48;
604  for(; uipDigit < uipDigitEnd; uipDigit++){
605  uiNum = 10 * uiNum + (aint)(*uipDigit - 48);
606  }
607  spCtx->spCurrentTest->uiFailAt = (aint)uiNum;
608  }
609  }
610  if(!bName){
611  XTHROW(spCtx->spException, "expected Name attribute not found");
612  }
613  if(!bRule){
614  XTHROW(spCtx->spException, "expected Rule attribute not found");
615  }
616  }
617 }
618 
619 static void vEndTag(u32_phrase* spName, u32_phrase* spContent, void* vpCtx){
620  xml_context* spCtx = (xml_context*)vpCtx;
621  if(bCompU32(spName, spCtx->spConstraint)){
622  spCtx->spCurrentConstraint = NULL;
623 
624  }else if(bCompU32(spName, spCtx->spMatch)){
625  if(!spCtx->spCurrentConstraint){
626  XTHROW(spCtx->spException, "vStartTag: \"Match\" node not child of \"Constraint\" node");
627  }
628  spCtx->spCurrentConstraint->uiCount++;
629  // push a U32_phrase on vpVecConstraints
630  u32_phrase* spPhrase = (u32_phrase*)vpVecPush(spCtx->vpVecConstraints, NULL);
631  uint32_t* uipMem = (uint32_t*)vpMemAlloc(spCtx->vpMem, (sizeof(uint32_t) * spContent->uiLength));
632  memcpy((void*)uipMem, (void*)spContent->uipPhrase, (sizeof(uint32_t) * spContent->uiLength));
633  spPhrase->uipPhrase = (const uint32_t*)uipMem;
634  spPhrase->uiLength = spContent->uiLength;
635  }else if(bCompU32(spName, spCtx->spInput)){
636  spCtx->spCurrentTest->sContent.uiIndex = uiVecLen(spCtx->vpVec32);
637  spCtx->spCurrentTest->sContent.uiLength = spContent->uiLength;
638  vpVecPushn(spCtx->vpVec32, (uint32_t*)spContent->uipPhrase, spContent->uiLength);
639  }
640 }
641 
642 static xml_context* spSetup(exception* spEx, void* vpMem, void* vpParser){
643  xml_context* spCtx = (xml_context*)vpMemAlloc(vpMem, sizeof(xml_context));
644  memset(spCtx, 0, sizeof(xml_context));
645  spCtx->vpMem = vpMem;
646  spCtx->spException = spEx;
647  spCtx->vpOdataParser = vpParser;
648  spCtx->vpVec32 = vpVecCtor(vpMem, sizeof(uint32_t), 8192);
649  spCtx->vpVecTests = vpVecCtor(vpMem, sizeof(test), 1000);
650  spCtx->vpVecContraintRules = vpVecCtor(vpMem, sizeof(rule_constraint), 1000);
651  spCtx->vpVecConstraints = vpVecCtor(vpMem, sizeof(u32_phrase), 2000);
652  spCtx->cpXmlName = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../input/", "odata-abnf-testcases.xml");
653  spCtx->cpJsonName = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "odata-abnf-testcases.json");
654 // printf("XML INPUT: %s\n", spCtx->cpXmlName);
655 // printf("JSON OUTPUT: %s\n", spCtx->cpJsonName);
656  spCtx->spTestCase = spUtilStrToPhrase32(vpMem, "TestCase");
657  spCtx->spConstraint = spUtilStrToPhrase32(vpMem, "Constraint");
658  spCtx->spMatch = spUtilStrToPhrase32(vpMem, "Match");
659  spCtx->spInput = spUtilStrToPhrase32(vpMem, "Input");
660  spCtx->spRule = spUtilStrToPhrase32(vpMem, "Rule");
661  spCtx->spName = spUtilStrToPhrase32(vpMem, "Name");
662  spCtx->spFailAt = spUtilStrToPhrase32(vpMem, "FailAt");
663  spCtx->uiRuleCount = RULE_COUNT_ODATA;
664 
665  // initialize all of the constraints
666  rule_constraint* spConstraint;
667  spConstraint = (rule_constraint*)vpVecPushn(spCtx->vpVecContraintRules, NULL, spCtx->uiRuleCount);
668  aint ui = 0;
669  for(; ui < spCtx->uiRuleCount; ui++, spConstraint++){
670  spConstraint->uiRuleIndex = ui;
671  spConstraint->uiCount = 0;
672  spConstraint->uiOffset = 0;
673  }
674  return spCtx;
675 }
676 
677 static int iMakeJsonApgXml() {
678  int iReturn = EXIT_SUCCESS;
679  static void* vpMem = NULL;
680  static void* vpXml = NULL;
681  static void* vpParser = NULL;
682  static void* vpJson = NULL;
683  static void* vpBuilder = NULL;
684 
685  char* cpDesc = "This program will build a JSON file that will be used for the parsing tests.\n"
686  "It first reads the complete list of ABNF grammar rules for the OData grammar.\n"
687  "It then reads the XML file of test cases and an APG XML parser is used to extract the test information.\n"
688  "The XML file has valid tests and invalid tests with an attribute that indicates that the test is to fail.\n"
689  "The valid and invalid tests are interspersed. This program will separate the valid and invalid tests.\n"
690  "The root JSON object will have two members - an array of valid test object and an array of invalid test objects.\n";
691  exception e;
692  XCTOR(e);
693  if(e.try){
694  // try block - construct the API object
695  printf("\n");
696  printf("%s", cpDesc);
697  printf("\n");
698 
699  // setup
700  vpMem = vpMemCtor(&e);
701  vpXml = vpXmlCtor(&e);
702  vpJson = vpJsonCtor(&e);
703  vpBuilder = vpJsonBuildCtor(vpJson);
704  vpParser = vpParserCtor(&e, vpOdataInit);
705  xml_context* spCtx = spSetup(&e, vpMem, vpParser);
706 
707  // get the test cases from the original XML format
708  vXmlGetFile(vpXml, spCtx->cpXmlName);
709  vXmlSetStartTagCallback(vpXml, vStartTag, (void*)spCtx);
710  vXmlSetEndTagCallback(vpXml, vEndTag, (void*)spCtx);
711  vXmlParse(vpXml);
712 
713  // count the number of successful visits to the A node.
714  aint uiRoot, uiKey, uiValue, uiObj, uiMatchArray, uiConstraintsArray, uiValidArray, uiInvalidArray;
716  rule_constraint* spConstraintEnd = spConstraint + uiVecLen(spCtx->vpVecContraintRules);
717  test* spTest = (test*)vpVecFirst(spCtx->vpVecTests);
718  test* spTestEnd = spTest + uiVecLen(spCtx->vpVecTests);
719  void* vpIt;
720  json_value* spValue;
721  uint32_t* uipData;
722  aint uiCount;
723  uint64_t ui64;
724 
725  // set up the root and arrays
726  uiRoot = uiJsonBuildMakeObject(vpBuilder);
727  uiConstraintsArray = uiJsonBuildMakeArray(vpBuilder);
728  uiValidArray = uiJsonBuildMakeArray(vpBuilder);
729  uiInvalidArray = uiJsonBuildMakeArray(vpBuilder);
730 
731  // set up the keys
732  aint uiMatch = uiJsonBuildMakeStringA(vpBuilder, "match");
733  aint uiID = uiJsonBuildMakeStringA(vpBuilder, "ID");
734  aint uiName = uiJsonBuildMakeStringA(vpBuilder, "name");
735  aint uiRule = uiJsonBuildMakeStringA(vpBuilder, "rule");
736  aint uiRuleId = uiJsonBuildMakeStringA(vpBuilder, "ruleId");
737  aint uiInput = uiJsonBuildMakeStringA(vpBuilder, "input");
738  aint uiFailAt = uiJsonBuildMakeStringA(vpBuilder, "failAt");
739 
740  // make the constraint objects
741  for(; spConstraint < spConstraintEnd; spConstraint++){
742  if(spConstraint->cpRuleName){
743  uiObj = uiJsonBuildMakeObject(vpBuilder);
744  uiMatchArray = uiJsonBuildMakeArray(vpBuilder);
745  // add the rule name
746  uiValue = uiJsonBuildMakeStringA(vpBuilder, spConstraint->cpRuleName);
747  uiJsonBuildAddToObject(vpBuilder, uiObj, uiRule, uiValue);
748  // add the rule index
749  uiValue = uiJsonBuildMakeNumberU(vpBuilder, (uint64_t)spConstraint->uiRuleIndex);
750  uiJsonBuildAddToObject(vpBuilder, uiObj, uiRuleId, uiValue);
751  // add the match strings to this rule
752  u32_phrase* spPhrase = (u32_phrase*)vpVecAt(spCtx->vpVecConstraints, spConstraint->uiOffset);
753  u32_phrase* spPhraseEnd = spPhrase + spConstraint->uiCount;
754  for(; spPhrase < spPhraseEnd; spPhrase++){
755  uiValue = uiJsonBuildMakeStringU(vpBuilder, spPhrase->uipPhrase, spPhrase->uiLength);
756  uiJsonBuildAddToArray(vpBuilder, uiMatchArray, uiValue);
757  }
758  // add the match array
759  uiJsonBuildAddToObject(vpBuilder, uiObj, uiMatch, uiMatchArray);
760  // add the rule constraint object to the constraint array
761  uiJsonBuildAddToArray(vpBuilder, uiConstraintsArray, uiObj);
762  }
763  }
764 
765  // make the the valid and invalid test objects
766  for(ui64 = 0;spTest < spTestEnd; spTest++, ui64++){
767  // make a test object
768  uiObj = uiJsonBuildMakeObject(vpBuilder);
769  uiValue = uiJsonBuildMakeNumberU(vpBuilder, ui64);
770  uiJsonBuildAddToObject(vpBuilder, uiObj, uiID, uiValue);
771  // name
772  uipData = (uint32_t*)vpVecAt(spCtx->vpVec32, spTest->sName.uiIndex);
773  uiValue = uiJsonBuildMakeStringU(vpBuilder, uipData, spTest->sName.uiLength);
774  uiJsonBuildAddToObject(vpBuilder, uiObj, uiName, uiValue);
775  // rule name
776  uipData = (uint32_t*)vpVecAt(spCtx->vpVec32, spTest->sRule.uiIndex);
777  uiValue = uiJsonBuildMakeStringU(vpBuilder, uipData, spTest->sRule.uiLength);
778  uiJsonBuildAddToObject(vpBuilder, uiObj, uiRule, uiValue);
779  // rule ID
780  uiValue = uiJsonBuildMakeNumberU(vpBuilder, (uint64_t)spTest->uiRuleId);
781  uiJsonBuildAddToObject(vpBuilder, uiObj, uiRuleId, uiValue);
782  // input
783  uipData = (uint32_t*)vpVecAt(spCtx->vpVec32, spTest->sContent.uiIndex);
784  uiValue = uiJsonBuildMakeStringU(vpBuilder, uipData, spTest->sContent.uiLength);
785  uiJsonBuildAddToObject(vpBuilder, uiObj, uiInput, uiValue);
786  if(spTest->bFail){
787  // fail at
788  uiValue = uiJsonBuildMakeNumberU(vpBuilder, (uint64_t)spTest->uiFailAt);
789  uiJsonBuildAddToObject(vpBuilder, uiObj, uiFailAt, uiValue);
790  // add the test object to the "invalid" array
791  uiJsonBuildAddToArray(vpBuilder, uiInvalidArray, uiObj);
792  }else{
793  // add the test object to the "valid" array
794  uiJsonBuildAddToArray(vpBuilder, uiValidArray, uiObj);
795  }
796  }
797  // add the "constraints" array to the root object
798  uiKey = uiJsonBuildMakeStringA(vpBuilder, "constraints");
799  uiJsonBuildAddToObject(vpBuilder, uiRoot, uiKey, uiConstraintsArray);
800 
801  // add the "valid" array to the root object
802  uiKey = uiJsonBuildMakeStringA(vpBuilder, "valid");
803  uiJsonBuildAddToObject(vpBuilder, uiRoot, uiKey, uiValidArray);
804 
805  // add the "invalid" array to the root object
806  uiKey = uiJsonBuildMakeStringA(vpBuilder, "invalid");
807  uiJsonBuildAddToObject(vpBuilder, uiRoot, uiKey, uiInvalidArray);
808 
809  // make a single JSON object file which holds ALL of the tests
810  vpIt = vpJsonBuild(vpBuilder, uiRoot);
811  spValue = spJsonIteratorFirst(vpIt);
812 
813  // write the JSON (root) object to a byte stream (uint8_t array)
814  uint8_t* ucpBytes = ucpJsonWrite(vpJson, spValue, &uiCount);
815 
816  // display
817 // vJsonDisplayValue(vpJson, spValue, 0);
818 
819  // write the UTF-8 byte stream to a file
820  vUtilFileWrite(spCtx->vpMem, spCtx->cpJsonName, ucpBytes, uiCount);
821  printf("\nJSON file written to %s\n", spCtx->cpJsonName);
822 
823  }else{
824  // catch block - display the exception location and message
826  iReturn = EXIT_FAILURE;
827  }
828 
829  vParserDtor(vpParser);
830  vXmlDtor(vpXml);
831  vJsonDtor(vpJson);
832  vMemDtor(vpMem);
833  return iReturn;
834 }
835 
846 int main(int argc, char **argv) {
847  long int iCase = 0;
848  long int iTestId = 0;
849  // NOTE: sizeof(achar) must == sizeof(uint8_t)
850  if(sizeof(achar) != sizeof(uint8_t)){
851  char* cpMsg = "For these tests, sizeof(achar) == sizeof(uint8_t) must be true.\n"
852  "Insure that in the build the symbol APG_ACHAR is undefined or defined with a value of 8.\n";
853  printf("%s", cpMsg);
854  return EXIT_SUCCESS;
855  }
856  if(argc > 1){
857  iCase = atol(argv[1]);
858  }
859  if((iCase > 0) && (iCase <= s_iCaseCount)){
860  printf("%s\n", s_cppCases[iCase -1]);
861  }
862  switch(iCase){
863  case 1:
864  return iApp();
865  case 2:
866  return iMakeJsonApgXml();
867  case 3:
868  return iParseValid();
869  case 4:
870  return iParseInvalid();
871  case 5:
872  if(argc > 2){
873  iTestId = atol(argv[2]);
874  return iTraceTestId((aint)iTestId);
875  }
876  iHelp();
877  break;
878  default:
879  return iHelp();
880  }
881 }
test::sName
data_id sName
Definition: main.h:41
vXmlParse
void vXmlParse(void *vpCtx)
Parse the XML data from vXmlGetFile or vXmlGetArray.
Definition: xml.c:500
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
data_id::uiLength
aint uiLength
Definition: main.h:37
rule_constraint::uiRuleIndex
aint uiRuleIndex
Definition: main.h:52
xml_context::spMatch
u32_phrase * spMatch
Definition: main.h:73
rule_constraint
Definition: main.h:49
vpParserCtor
void * vpParserCtor(exception *spException, void *vpParserInit)
The parser's constructor for file initialization data.
Definition: parser.c:67
xml_context::spCurrentConstraint
rule_constraint * spCurrentConstraint
Definition: main.h:79
vpXmlCtor
void * vpXmlCtor(exception *spEx)
The XML Parser constructor.
Definition: xml.c:159
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
exception::try
abool try
True for the try block, false for the catch block.
Definition: exception.h:49
user_data
Definition: main.h:56
test::bFail
abool bFail
Definition: main.h:46
vpJsonFindKeyA
void * vpJsonFindKeyA(void *vpCtx, const char *cpKey, json_value *spValue)
Find JSON values with a specified ASCII key.
Definition: json.c:434
test::sRule
data_id sRule
Definition: main.h:43
test
Definition: main.h:40
callback_data::uiParserOffset
aint uiParserOffset
[read only] Offset from acpString to the first character to match
Definition: parser.h:160
vpJsonReadFile
void * vpJsonReadFile(void *vpCtx, const char *cpFileName)
The JSON file reader.
Definition: json.c:207
callback_data::acpString
const achar * acpString
[read only] Pointer to the input sub-string,
Definition: parser.h:156
u32_phrase::uiLength
uint32_t uiLength
The number of integers in the array.
Definition: lib.h:75
parser_config::acpInput
const achar * acpInput
Pointer to the input string.
Definition: parser.h:199
callback_data::uiParserState
aint uiParserState
[read only] ID_ACTIVE if the parser is going down the tree. ID_MATCH or ID_NOMATCH if coming up the t...
Definition: parser.h:158
xml_context::spName
u32_phrase * spName
Definition: main.h:75
rule_constraint::uiCount
aint uiCount
Definition: main.h:51
uiParserRuleLookup
aint uiParserRuleLookup(void *vpCtx, const char *cpRuleName)
Find the rule index corresponding to a rule name.
Definition: parser.c:440
data_id::uiIndex
aint uiIndex
Definition: main.h:36
parser_config::vpUserData
void * vpUserData
Pointer to user data, if any. Not examined or used by the parser in any way. Presented to the user's ...
Definition: parser.h:210
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
uiJsonBuildMakeNumberU
aint uiJsonBuildMakeNumberU(void *vpBuildCtx, uint64_t uiNumber)
Make a JSON unsigned integer number value.
Definition: builder.c:383
cpUint32ToStr
char * cpUint32ToStr(uint32_t *uipBuf, aint uiLen, char *cpStr)
Convert an array of 32-bit unsigned integers to a null-terminated ASCII string.
Definition: tools.c:336
JSON_ID_STRING
#define JSON_ID_STRING
String value.
Definition: json.h:50
vParserSetRuleCallback
void vParserSetRuleCallback(void *vpCtx, aint uiRuleId, parser_callback pfnCallback)
Set a call back function for a specific rule.
Definition: parser.c:386
xml_context::vpVecContraintRules
void * vpVecContraintRules
Definition: main.h:67
callback_data::uiRuleIndex
aint uiRuleIndex
[read only] The rule index of this rule's callback. APG_UNDEFINED if this is a UDT callback.
Definition: parser.h:163
vpVecAt
void * vpVecAt(void *vpCtx, aint uiIndex)
Get a the indexed vector element. The vector is not altered.
Definition: vector.c:362
xml_context::spCurrentTest
test * spCurrentTest
Definition: main.h:78
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
xml_context::spRule
u32_phrase * spRule
Definition: main.h:76
xml_context::vpVecConstraints
void * vpVecConstraints
Definition: main.h:68
rule_constraint::cpRuleName
const char * cpRuleName
Definition: main.h:53
JSON_ID_ARRAY
#define JSON_ID_ARRAY
Array value.
Definition: json.h:49
xml_context
Definition: main.h:61
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
parser_config::uiInputLength
aint uiInputLength
Number of input string alphabet characters.
Definition: parser.h:200
vXmlGetFile
void vXmlGetFile(void *vpCtx, const char *cpFileName)
Gets the XML byte stream from a file.
Definition: xml.c:277
uiJsonBuildMakeStringA
aint uiJsonBuildMakeStringA(void *vpBuildCtx, const char *cpString)
Make a string value from a null-terminated ASCII string.
Definition: builder.c:283
vpTraceCtor
void * vpTraceCtor(void *vpCtx)
The trace object constructor.
Definition: trace.c:92
callback_data::uiParserPhraseLength
aint uiParserPhraseLength
[read only] The parser's matched phrase length if uiParserState is ID_MATCH or ID_NOMATCH....
Definition: parser.h:161
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
rule_constraint::uiOffset
aint uiOffset
Definition: main.h:50
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
callback_data::uiCallbackState
aint uiCallbackState
[input/output] Rule name (RNM) callback functions: If ID_ACTIVE, the parser takes no action....
Definition: parser.h:139
xml_context::caBuf
char caBuf[128]
Definition: main.h:80
test::uiFailAt
aint uiFailAt
Definition: main.h:45
main.h
vpOdataInit
void * vpOdataInit
Definition: odata.c:18718
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
xml_context::uiRuleCount
aint uiRuleCount
Definition: main.h:81
uiVecLen
aint uiVecLen(void *vpCtx)
Get the vector length. That is, the number of elements on the vector.
Definition: vector.c:385
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
xml_context::spConstraint
u32_phrase * spConstraint
Definition: main.h:72
parser_state
The parser's final state.
Definition: parser.h:183
xml_context::spTestCase
u32_phrase * spTestCase
Definition: main.h:71
test::uiRuleId
aint uiRuleId
Definition: main.h:44
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
uiJsonBuildMakeObject
aint uiJsonBuildMakeObject(void *vpBuildCtx)
Make a JSON object value.
Definition: builder.c:445
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
vXmlSetStartTagCallback
void vXmlSetStartTagCallback(void *vpCtx, pfnStartTagCallback pfnCallback, void *vpUserData)
Set the user's callback function for the start tags (<name attr="10">).
Definition: xml.c:600
ID_ACTIVE
#define ID_ACTIVE
indicates active parser state, parser has just entered the node and is moving down the parse tree
Definition: parser.h:72
vpJsonBuild
void * vpJsonBuild(void *vpBuildCtx, aint uiRoot)
Build the JSON object.
Definition: builder.c:603
uiJsonBuildMakeStringU
aint uiJsonBuildMakeStringU(void *vpBuildCtx, const uint32_t *uipData, aint uiLength)
Make a string value from UTF-32 code points.
Definition: builder.c:223
callback_data::uiCallbackPhraseLength
aint uiCallbackPhraseLength
[input/output] The phrase length of the matched phrase if the callback function returns ID_MATCH.
Definition: parser.h:145
uiJsonBuildAddToObject
aint uiJsonBuildAddToObject(void *vpBuildCtx, aint uiObject, aint uiKey, aint uiAdd)
Add a child value to a parent object value.
Definition: builder.c:479
spJsonIteratorFirst
json_value * spJsonIteratorFirst(void *vpIteratorCtx)
Find the first value in the list represented by this iterator.
Definition: json.c:613
callback_data
The data struct passed to each callback function.
Definition: parser.h:134
xml_context::vpVec32
void * vpVec32
Definition: main.h:65
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
vpVecPushn
void * vpVecPushn(void *vpCtx, void *vpElement, aint uiCount)
Adds one or more elements to the end of the array.
Definition: vector.c:221
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
xml_context::vpVecTests
void * vpVecTests
Definition: main.h:66
vXmlSetEndTagCallback
void vXmlSetEndTagCallback(void *vpCtx, pfnEndTagCallback pfnCallback, void *vpUserData)
Set the user's callback function for the end tags (</name>).
Definition: xml.c:656
spJsonIteratorNext
json_value * spJsonIteratorNext(void *vpIteratorCtx)
Find the next value in the list represented by this iterator.
Definition: json.c:647
RULE_COUNT_ODATA
#define RULE_COUNT_ODATA
Definition: odata.h:485
xml_context::spException
exception * spException
Definition: main.h:62
callback_data::vpUserData
void * vpUserData
[input/output] User-defined data passed to to the parser in parser_config.
Definition: parser.h:136
xml_context::cpXmlName
char * cpXmlName
Definition: main.h:69
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
uiJsonBuildMakeArray
aint uiJsonBuildMakeArray(void *vpBuildCtx)
Makea JSON array value.
Definition: builder.c:459
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
uiJsonBuildAddToArray
aint uiJsonBuildAddToArray(void *vpBuildCtx, aint uiArray, aint uiAdd)
Add a child value to a parent array value.
Definition: builder.c:550
APG_MAX_AINT
#define APG_MAX_AINT
Since the maximum unsigned integer value is used to indicate Infinite and Undefined values,...
Definition: apg.h:329
vUtilFileWrite
void vUtilFileWrite(void *vpMem, const char *cpFileName, uint8_t *ucpData, aint uiLen)
Write from the caller's data area to the given file name.
Definition: utilities.c:210
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
vpJsonCtor
void * vpJsonCtor(exception *spEx)
The JSON constructor.
Definition: json.c:115
parser_config::uiStartRule
aint uiStartRule
Index of the start rule. Any rule in the SABNF grammar may be used as the start rule.
Definition: parser.h:201
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
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
xml_context::vpOdataParser
void * vpOdataParser
Definition: main.h:64
xml_context::vpMem
void * vpMem
Definition: main.h:63
test::sContent
data_id sContent
Definition: main.h:42
u32_phrase
Defines a pointer to an array of 32-bit unsigned integers plus its length. Typically needed by Unicod...
Definition: lib.h:73
xml_context::cpJsonName
char * cpJsonName
Definition: main.h:70
vXmlDtor
void vXmlDtor(void *vpCtx)
The XML Parser component destructor.
Definition: xml.c:242
xml_context::spFailAt
u32_phrase * spFailAt
Definition: main.h:77
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
JSON_ID_NUMBER
#define JSON_ID_NUMBER
Number value.
Definition: json.h:51
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
spUtilStrToPhrase32
u32_phrase * spUtilStrToPhrase32(void *vpMem, const char *cpStr)
Convert a null-terminated ASCII string to a 32-bit phrase.
Definition: utilities.c:1031
xml_context::spInput
u32_phrase * spInput
Definition: main.h:74
cpParserRuleName
const char * cpParserRuleName(void *vpCtx, aint uiRuleIndex)
Find the rule name from the corresponding index.
Definition: parser.c:469
callback_data::spException
exception * spException
[read only] Use to throw exceptions back to the parser's catch block scope: e.g. XTHROW(spException,...
Definition: parser.h:165
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
vpJsonBuildCtor
void * vpJsonBuildCtor(void *vpJsonCtx)
The builder object constructor.
Definition: builder.c:124
vParserParse
void vParserParse(void *vpCtx, parser_config *spConfig, parser_state *spState)
Parse an input string of alphabet characters.
Definition: parser.c:268
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.