VES EVEL Library VES 5.4.1 enhancements
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / VESreporting_fault / jsmn.c
1 /*************************************************************************//**
2  *
3  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
4  *
5  * Unless otherwise specified, all software contained herein is
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and 
15  * limitations under the License.
16  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
17  ****************************************************************************/
18 #include<stdio.h>
19 #include<stdlib.h>
20 #include<string.h>
21 #include "jsmn.h"
22
23 /**
24  * Allocates a fresh unused token from the token pull.
25  */
26 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
27                 jsmntok_t *tokens, size_t num_tokens) {
28         jsmntok_t *tok;
29         if (parser->toknext >= num_tokens) {
30                 return NULL;
31         }
32         tok = &tokens[parser->toknext++];
33         tok->start = tok->end = -1;
34         tok->size = 0;
35 //#ifdef JSMN_PARENT_LINKS
36         tok->parent = -1;
37 //#endif
38         return tok;
39 }
40
41 /**
42  * Fills token type and boundaries.
43  */
44 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
45                             int start, int end) {
46 //printf("jsmn_fill_token:: start-%d, end-%d\n", start, end);
47         token->type = type;
48         token->start = start;
49         token->end = end;
50         token->size = 0;
51 }
52
53 /**
54  * Fills next available token with JSON primitive.
55  */
56 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
57                 size_t len, jsmntok_t *tokens, size_t num_tokens) {
58         jsmntok_t *token;
59         int start;
60
61         start = parser->pos;
62
63         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
64 //printf("jsmn_parse_primitive:: the char is - %c\n", js[parser->pos]);
65                 switch (js[parser->pos]) {
66 #ifndef JSMN_STRICT
67                         /* In strict mode primitive must be followed by "," or "}" or "]" */
68                         case ':':
69 #endif
70                         case '\t' : case '\r' : case '\n' : case ' ' :
71                         case ','  : case ']'  : case '}' :
72                                 goto found;
73                 }
74                 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
75                         parser->pos = start;
76                         return JSMN_ERROR_INVAL;
77                 }
78         }
79 #ifdef JSMN_STRICT
80         /* In strict mode primitive must be followed by a comma/object/array */
81         parser->pos = start;
82         return JSMN_ERROR_PART;
83 #endif
84
85 found:
86         if (tokens == NULL) {
87                 parser->pos--;
88                 return 0;
89         }
90         token = jsmn_alloc_token(parser, tokens, num_tokens);
91         if (token == NULL) {
92                 parser->pos = start;
93                 return JSMN_ERROR_NOMEM;
94         }
95         jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
96 //#ifdef JSMN_PARENT_LINKS
97         token->parent = parser->toksuper;
98 //#endif
99         parser->pos--;
100         return 0;
101 }
102
103 /**
104  * Fills next token with JSON string.
105  */
106 static int jsmn_parse_string(jsmn_parser *parser, const char *js,
107                 size_t len, jsmntok_t *tokens, size_t num_tokens) {
108         jsmntok_t *token;
109
110         int start = parser->pos;
111
112         parser->pos++;
113
114         /* Skip starting quote */
115         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
116                 char c = js[parser->pos];
117                 char d = js[parser->pos + 1];
118 //              char e = js[parser->pos + 2];
119 //printf("jsmn_parse_string: value-%c, pos-%d\n", c,parser->pos);
120
121                 /* Quote: end of string */
122 //              if (c == '\"') {
123                 if (d == '\"') {
124 //              if ((d == '\"')&&((e == ' ')||(e == ','))) {
125 parser->pos++;
126 //printf("jsmn_parse_string: end of string\n");
127                         if (tokens == NULL) {
128 //printf("jsmn_parse_string: end tokens is NULL\n");
129                                 return 0;
130                         }
131                         token = jsmn_alloc_token(parser, tokens, num_tokens);
132 //printf("jsmn_parse_string: Allocated tokens \n");
133                         if (token == NULL) {
134 //printf("jsmn_parse_string: Allocated tokens is NULL\n");
135                                 parser->pos = start;
136                                 return JSMN_ERROR_NOMEM;
137                         }
138                         jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
139 //printf("jsmn_parse_string: Allocated tokens is filled\n");
140 //#ifdef JSMN_PARENT_LINKS
141                         token->parent = parser->toksuper;
142 //#endif
143                         return 0;
144                 }
145
146                 /* Backslash: Quoted symbol expected */
147                 if (c == '\\' && parser->pos + 1 < len) {
148                         int i;
149                         parser->pos++;
150 //printf("jsmn_parse_string: value - %c, POS-%3d \n",c, js[parser->pos]);
151                         switch (js[parser->pos]) {
152                                 /* Allowed escaped symbols */
153                                 case '\"': case '/' : case '\\' : case 'b' :
154                                 case 'f' : case 'r' : case 'n'  : case 't' :
155                                         break;
156                                 /* Allows escaped symbol \uXXXX */
157                                 case 'u':
158                                         parser->pos++;
159                                         for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
160                                                 /* If it isn't a hex character we have an error */
161                                                 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
162                                                                         (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
163                                                                         (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
164                                                         parser->pos = start;
165                                                         return JSMN_ERROR_INVAL;
166                                                 }
167                                                 parser->pos++;
168                                         }
169                                         parser->pos--;
170                                         break;
171                                 /* Unexpected symbol */
172                                 default:
173                                         parser->pos = start;
174                                         return JSMN_ERROR_INVAL;
175                         }
176                 }
177         }
178         parser->pos = start;
179 printf("jsmn_parse_string: exiting with ERROR_PART, pos-%d", parser->pos);
180         return JSMN_ERROR_PART;
181 }
182
183 /**
184  * Parse JSON string and fill tokens.
185  */
186 int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
187                 jsmntok_t *tokens, unsigned int num_tokens) {
188         int r;
189         int i;
190         jsmntok_t *token;
191         int count = parser->toknext;
192
193         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
194                 char c;
195                 jsmntype_t type;
196
197                 c = js[parser->pos];
198 //printf("jsmn_parse: value of c - %c\n",c);
199                 switch (c) {
200                         case '{': case '[':
201                                 count++;
202                                 if (tokens == NULL) {
203                                         break;
204                                 }
205                                 token = jsmn_alloc_token(parser, tokens, num_tokens);
206                                 if (token == NULL)
207                                         return JSMN_ERROR_NOMEM;
208                                 if (parser->toksuper != -1) {
209                                         tokens[parser->toksuper].size++;
210 //#ifdef JSMN_PARENT_LINKS
211                                         token->parent = parser->toksuper;
212 //#endif
213                                 }
214                                 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
215                                 token->start = parser->pos;
216                                 parser->toksuper = parser->toknext - 1;
217                                 break;
218                         case '}': case ']':
219                                 if (tokens == NULL)
220                                         break;
221                                 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
222 //#ifdef JSMN_PARENT_LINKS
223                                 if (parser->toknext < 1) {
224                                         return JSMN_ERROR_INVAL;
225                                 }
226                                 token = &tokens[parser->toknext - 1];
227                                 for (;;) {
228                                         if (token->start != -1 && token->end == -1) {
229                                                 if (token->type != type) {
230                                                         return JSMN_ERROR_INVAL;
231                                                 }
232                                                 token->end = parser->pos + 1;
233                                                 parser->toksuper = token->parent;
234                                                 break;
235                                         }
236                                         if (token->parent == -1) {
237                                                 break;
238                                         }
239                                         token = &tokens[token->parent];
240                                 }
241 //#else
242 //                              for (i = parser->toknext - 1; i >= 0; i--) {
243 //                                      token = &tokens[i];
244 //                                      if (token->start != -1 && token->end == -1) {
245 //                                              if (token->type != type) {
246 //                                                      return JSMN_ERROR_INVAL;
247 //                                              }
248 //                                              parser->toksuper = -1;
249 //                                              token->end = parser->pos + 1;
250 //                                              break;
251 //                                      }
252 //                              }
253 //                              /* Error if unmatched closing bracket */
254 //                              if (i == -1) return JSMN_ERROR_INVAL;
255 //                              for (; i >= 0; i--) {
256 //                                      token = &tokens[i];
257 //                                      if (token->start != -1 && token->end == -1) {
258 //                                              parser->toksuper = i;
259 //                                              break;
260 //                                      }
261 //                              }
262 //#endif
263                                 break;
264                         case '\"':
265                                 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
266                                 if (r < 0) return r;
267                                 count++;
268                                 if (parser->toksuper != -1 && tokens != NULL)
269                                         tokens[parser->toksuper].size++;
270                                 break;
271                         case '\t' : case '\r' : case '\n' : case ' ':
272                                 break;
273                         case ':':
274                                 parser->toksuper = parser->toknext - 1;
275 //printf("jsmn_parse: value of c is :: - %c\n",c);
276                                 break;
277                         case ',':
278                                 if (tokens != NULL && parser->toksuper != -1 &&
279                                                 tokens[parser->toksuper].type != JSMN_ARRAY &&
280                                                 tokens[parser->toksuper].type != JSMN_OBJECT) {
281 //#ifdef JSMN_PARENT_LINKS
282                                         parser->toksuper = tokens[parser->toksuper].parent;
283 //#else
284 //                                      for (i = parser->toknext - 1; i >= 0; i--) {
285 //                                              if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
286 //                                                      if (tokens[i].start != -1 && tokens[i].end == -1) {
287 //                                                              parser->toksuper = i;
288 //                                                              break;
289 //                                                      }
290 //                                              }
291 //                                      }
292 //#endif
293                                 }
294                                 break;
295 #ifdef JSMN_STRICT
296                         /* In strict mode primitives are: numbers and booleans */
297                         case '-': case '0': case '1' : case '2': case '3' : case '4':
298                         case '5': case '6': case '7' : case '8': case '9':
299                         case 't': case 'f': case 'n' :
300                                 /* And they must not be keys of the object */
301                                 if (tokens != NULL && parser->toksuper != -1) {
302                                         jsmntok_t *t = &tokens[parser->toksuper];
303                                         if (t->type == JSMN_OBJECT ||
304                                                         (t->type == JSMN_STRING && t->size != 0)) {
305                                                 return JSMN_ERROR_INVAL;
306                                         }
307                                 }
308 #else
309                         /* In non-strict mode every unquoted value is a primitive */
310                         default:
311 #endif
312                                 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
313                                 if (r < 0) return r;
314                                 count++;
315                                 if (parser->toksuper != -1 && tokens != NULL)
316                                         tokens[parser->toksuper].size++;
317                                 break;
318
319 #ifdef JSMN_STRICT
320                         /* Unexpected char in strict mode */
321                         default:
322                                 return JSMN_ERROR_INVAL;
323 #endif
324                 }
325         }
326
327         if (tokens != NULL) {
328                 for (i = parser->toknext - 1; i >= 0; i--) {
329 //printf("index -%2d, start is %3d, end is %3d\n", i, tokens[i].start, tokens[i].end);
330                         /* Unmatched opened object or array */
331                         if (tokens[i].start != -1 && tokens[i].end == -1) {
332                                 return JSMN_ERROR_PART;
333                         }
334                 }
335         }
336
337         return count;
338 }
339
340 /**
341  * Creates a new parser based over a given  buffer with an array of tokens
342  * available.
343  */
344 void jsmn_init(jsmn_parser *parser) {
345         parser->pos = 0;
346         parser->toknext = 0;
347         parser->toksuper = -1;
348 }
349
350 int jsoneq(const char *json, jsmntok_t *tok, const char *s) 
351 {
352    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
353        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
354           return 0;
355    }
356    return -1;
357 }
358
359 void printToken(char * js, jsmntok_t * tokens, int numToken)
360 {
361   for (int i = 1; i < numToken; i++)
362   {
363      printf("Token number-%2d, parent-%2d, type-%d size-%2d, parameter -", i, tokens[i].parent, tokens[i].type, tokens[i].size);
364      if (tokens[i].type == JSMN_STRING || tokens[i].type == JSMN_PRIMITIVE) {
365         printf("%.*s\n", tokens[i].end - tokens[i].start, js + tokens[i].start);
366      } else if (tokens[i].type == JSMN_ARRAY) {
367         printf("[%d elems]\n", tokens[i].size);
368      } else if (tokens[i].type == JSMN_OBJECT) {
369         printf("{%d elems}\n", tokens[i].size);
370      } else {
371         printf("value?? - ");
372         TOKEN_PRINT(tokens[i]);
373      }
374   }
375 }
376
377 int getStringToken(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, char * value, int maxValueSize)
378 {
379   int i = 0;
380   int dpToken = 0;
381
382   memset(value, 0, maxValueSize);
383
384   for (i = 1; i < numToken; i++)
385   {
386      if(jsoneq(js, &tokens[i], pParam) == 0)
387         break;
388   }
389   if (i < numToken)
390   {
391     dpToken = ++i;
392   }
393   else
394   {
395     printf("The parameter %s is not present in JSON file\n", pParam);
396     return 1; //Parent token not seen
397   }
398   for (i=1; i < numToken; i++)
399   {
400      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
401      {
402         if(jsoneq(js, &tokens[i], param) != 0)
403            continue;
404         TOKEN_COPY(js, tokens[i+1], value);
405
406         return 0; //Success
407      }
408   }
409   printf("The parameter %s is not present in JSON file\n", param);
410   return 2; //parameter not found
411 }
412
413
414 int getStringTokenV2(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, char * gParam,char * value, int maxValueSize)
415 {
416   int i = 0;
417   int dpToken = 0;
418
419   memset(value, 0, maxValueSize);
420
421   for (i = 1; i < numToken; i++)
422   {
423      if(jsoneq(js, &tokens[i], gParam) == 0)
424         break;
425   }
426   if (i < numToken)
427   {
428     dpToken = ++i;
429   }
430   else
431   {
432     printf("The parameter %s is not present in JSON file\n", pParam);
433     return 1; //Grand Parent token not seen
434   }
435
436   for (i=dpToken; i < numToken; i++)
437   {
438      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
439      {
440         if(jsoneq(js, &tokens[i], pParam) == 0)
441            break;
442      }
443   }
444   if (i < numToken)
445   {
446     dpToken = ++i;
447   }
448   else
449   {
450     printf("The parameter %s is not present in JSON file\n", pParam);
451     return 2; //Parent token not seen
452   }
453
454   for (i=dpToken; i < numToken; i++)
455   {
456      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
457      {
458         if(jsoneq(js, &tokens[i], param) != 0)
459            continue;
460         TOKEN_COPY(js, tokens[i+1], value);
461
462         return 0; //Success
463      }
464   }
465
466   printf("The parameter %s is not present in JSON file\n", param);
467   return 2; //parameter not found
468 }
469
470 int getIntToken(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, int * value)
471 {
472   int i = 0;
473   int dpToken = 0;
474   char  val[128];
475
476   memset(val, 0, 128);
477   for (i = 1; i < numToken; i++)
478   {
479      if(jsoneq(js, &tokens[i], pParam) == 0)
480         break;
481   }
482   if (i < numToken)
483   {
484     dpToken = ++i;
485   }
486   else
487   {
488     printf("The parameter %s is not present in JSON file\n", pParam);
489     return 1; //Parent token not seen
490   }
491   for (i=1; i < numToken; i++)
492   {
493      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
494      {
495         if(jsoneq(js, &tokens[i], param) != 0)
496         {
497            continue;
498         }
499
500         if(tokens[i+1].type != JSMN_PRIMITIVE)
501           return 3; //Wrong parameter type
502
503 //        printf("INT parameter / Value - %s", param);
504         TOKEN_COPY(js, tokens[i+1], val);
505         *value = atoi(val);
506 //        printf(" -  %d\n", *value);
507
508         return 0; //success
509      }
510   }
511   printf("The parameter %s is not present in JSON file\n", param);
512   return 2; //parameter not found
513 }
514
515 void parseDirectParameters(char * js, jsmntok_t * tokens, int numToken)
516 {
517   int i = 0;
518   int dpToken = 0;
519   char  param[128];
520   char  value[128];
521
522   for (i = 1; i < numToken; i++)
523   {
524      if(jsoneq(js, &tokens[i], "directParameters") == 0)
525         break;
526   }
527
528   if (i < numToken)
529   {
530     dpToken = ++i;
531   }
532
533   for (int i = 1; i < numToken; i++)
534   {
535      memset(param, 0, 128);
536      memset(value, 0, 128);
537      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
538      {
539         TOKEN_COPY(js, tokens[i], param);
540 //        printf("parameter / Value - %s", param);
541         TOKEN_COPY(js, tokens[i+1], value);
542 //        printf(" - %s\n", value);
543      }
544   }
545 }
546
547 int getArrayTokens(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, ARRAYVAL * arrayValue, int * numElements)
548 {
549   int i = 0;
550   int dpToken = 0;
551
552   for (i = 1; i < numToken; i++)
553   {
554      if(jsoneq(js, &tokens[i], pParam) == 0)
555         break;
556   }
557   if (i < numToken)
558   {
559     dpToken = ++i;
560   }
561   else
562   {    
563     printf("The parameter %s is not present in JSON file\n", pParam);
564     return 1; //Parent token not seen
565   }
566   for (i=1; i < numToken; i++)
567   {
568      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
569      {
570 //        printf("value of token %d\n", i);
571         if(jsoneq(js, &tokens[i], param) != 0)
572            continue;
573
574         if (tokens[i+1].type == JSMN_ARRAY)
575         {
576            *numElements = tokens[i+1].size;
577 //           printf("[%d elems]\n", *numElements);
578
579            for (int k = 0; k < *numElements; k++)
580            {
581               TOKEN_COPY(js, tokens[i+2+k], arrayValue[k].arrayString);
582 //              printf(" - %s\n", arrayValue[k].arrayString);
583            }
584            return 0; //Success
585         }
586      }
587   }
588   printf("The parameter %s is not present in JSON file\n", param);
589   return 2; //parameter not found
590 }
591
592 int isTokenPresent(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam)
593 {
594   int i = 0;
595   int dpToken = 0;
596   char  val[128];
597
598   memset(val, 0, 128);
599   for (i = 1; i < numToken; i++)
600   {
601      if(jsoneq(js, &tokens[i], pParam) == 0)
602         break;
603   }
604   if (i < numToken)
605   {
606     dpToken = ++i;
607   }
608   else
609   {
610     printf("The parameter %s is not present in JSON file\n", pParam);
611     return 1; //Parent token not seen
612   }
613   for (i=1; i < numToken; i++)
614   {
615      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING)
616      {
617         if(jsoneq(js, &tokens[i], param) == 0)
618         {
619            return 0; //Token present
620         }
621      }
622   }
623   printf("The parameter %s is not present in JSON file\n", param);
624   return 2; //Token Not present
625 }
626
627 int read_keyVal_params(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, KEYVALRESULT * keyValueResultList, int * numElements)
628 {
629   int i = 0;
630   int dpToken = 0;
631
632   for (i = 1; i < numToken; i++)
633   {
634      if(jsoneq(js, &tokens[i], pParam) == 0)
635         break;
636   }
637   if (i < numToken)
638   {
639     dpToken = ++i;
640   }
641   else
642   {
643     printf("The parameter %s is not present in JSON file\n", pParam);
644     return 1; //Parent token not seen
645   }
646   for (i=1; i < numToken; i++)
647   {
648      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
649      {
650 //        printf("value of token %d\n", i);
651         if(jsoneq(js, &tokens[i], param) != 0)
652            continue;
653
654         if (tokens[i+1].type == JSMN_OBJECT)
655         {
656            *numElements = tokens[i+1].size;
657 //           printf("{%d elems}\n", *numElements);
658
659            for (int k = 0; k < *numElements; k++)
660            {
661               TOKEN_COPY(js, tokens[i+2+k*2], keyValueResultList[k].keyStr);
662 //              printf("Key - %s", keyValueResultList[k].keyStr);
663               TOKEN_COPY(js, tokens[i+3+k*2], keyValueResultList[k].valStr);
664 //              printf("Value - %s\n", keyValueResultList[k].valStr);
665            }
666            return 0; //Success
667         }
668      }
669   }
670   printf("The parameter %s is not present in JSON file\n", param);
671   return 2; //parameter not found
672 }