VES EVEL Library VES 5.4.1 enhancements
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / VESreporting_HB / 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 int getIntToken(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, int * value)
414 {
415   int i = 0;
416   int dpToken = 0;
417   char  val[128];
418
419   memset(val, 0, 128);
420   for (i = 1; i < numToken; i++)
421   {
422      if(jsoneq(js, &tokens[i], pParam) == 0)
423         break;
424   }
425   if (i < numToken)
426   {
427     dpToken = ++i;
428   }
429   else
430   {
431     printf("The parameter %s is not present in JSON file\n", pParam);
432     return 1; //Parent token not seen
433   }
434   for (i=1; i < numToken; i++)
435   {
436      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
437      {
438         if(jsoneq(js, &tokens[i], param) != 0)
439         {
440            continue;
441         }
442
443         if(tokens[i+1].type != JSMN_PRIMITIVE)
444           return 3; //Wrong parameter type
445
446 //        printf("INT parameter / Value - %s", param);
447         TOKEN_COPY(js, tokens[i+1], val);
448         *value = atoi(val);
449 //        printf(" -  %d\n", *value);
450
451         return 0; //success
452      }
453   }
454   printf("The parameter %s is not present in JSON file\n", param);
455   return 2; //parameter not found
456 }
457
458 void parseDirectParameters(char * js, jsmntok_t * tokens, int numToken)
459 {
460   int i = 0;
461   int dpToken = 0;
462   char  param[128];
463   char  value[128];
464
465   for (i = 1; i < numToken; i++)
466   {
467      if(jsoneq(js, &tokens[i], "directParameters") == 0)
468         break;
469   }
470
471   if (i < numToken)
472   {
473     dpToken = ++i;
474   }
475
476   for (int i = 1; i < numToken; i++)
477   {
478      memset(param, 0, 128);
479      memset(value, 0, 128);
480      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
481      {
482         TOKEN_COPY(js, tokens[i], param);
483 //        printf("parameter / Value - %s", param);
484         TOKEN_COPY(js, tokens[i+1], value);
485 //        printf(" - %s\n", value);
486      }
487   }
488 }
489
490 int getArrayTokens(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, ARRAYVAL * arrayValue, int * numElements)
491 {
492   int i = 0;
493   int dpToken = 0;
494
495   for (i = 1; i < numToken; i++)
496   {
497      if(jsoneq(js, &tokens[i], pParam) == 0)
498         break;
499   }
500   if (i < numToken)
501   {
502     dpToken = ++i;
503   }
504   else
505   {    
506     printf("The parameter %s is not present in JSON file\n", pParam);
507     return 1; //Parent token not seen
508   }
509   for (i=1; i < numToken; i++)
510   {
511      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
512      {
513 //        printf("value of token %d\n", i);
514         if(jsoneq(js, &tokens[i], param) != 0)
515            continue;
516
517         if (tokens[i+1].type == JSMN_ARRAY)
518         {
519            *numElements = tokens[i+1].size;
520 //           printf("[%d elems]\n", *numElements);
521
522            for (int k = 0; k < *numElements; k++)
523            {
524               TOKEN_COPY(js, tokens[i+2+k], arrayValue[k].arrayString);
525 //              printf(" - %s\n", arrayValue[k].arrayString);
526            }
527            return 0; //Success
528         }
529      }
530   }
531   printf("The parameter %s is not present in JSON file\n", param);
532   return 2; //parameter not found
533 }
534
535 int isTokenPresent(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam)
536 {
537   int i = 0;
538   int dpToken = 0;
539   char  val[128];
540
541   memset(val, 0, 128);
542   for (i = 1; i < numToken; i++)
543   {
544      if(jsoneq(js, &tokens[i], pParam) == 0)
545         break;
546   }
547   if (i < numToken)
548   {
549     dpToken = ++i;
550   }
551   else
552   {
553     printf("The parameter %s is not present in JSON file\n", pParam);
554     return 1; //Parent token not seen
555   }
556   for (i=1; i < numToken; i++)
557   {
558      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING)
559      {
560         if(jsoneq(js, &tokens[i], param) != 0)
561         {
562            return 0; //Token present
563         }
564      }
565   }
566   printf("The parameter %s is not present in JSON file\n", param);
567   return 2; //Token Not present
568 }
569
570 int read_keyVal_params(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, KEYVALRESULT * keyValueResultList, int * numElements)
571 {
572   int i = 0;
573   int dpToken = 0;
574
575   for (i = 1; i < numToken; i++)
576   {
577      if(jsoneq(js, &tokens[i], pParam) == 0)
578         break;
579   }
580   if (i < numToken)
581   {
582     dpToken = ++i;
583   }
584   else
585   {
586     printf("The parameter %s is not present in JSON file\n", pParam);
587     return 1; //Parent token not seen
588   }
589   for (i=1; i < numToken; i++)
590   {
591      if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
592      {
593 //        printf("value of token %d\n", i);
594         if(jsoneq(js, &tokens[i], param) != 0)
595            continue;
596
597         if (tokens[i+1].type == JSMN_OBJECT)
598         {
599            *numElements = tokens[i+1].size;
600 //           printf("{%d elems}\n", *numElements);
601
602            for (int k = 0; k < *numElements; k++)
603            {
604               TOKEN_COPY(js, tokens[i+2+k*2], keyValueResultList[k].keyStr);
605 //              printf("Key - %s", keyValueResultList[k].keyStr);
606               TOKEN_COPY(js, tokens[i+3+k*2], keyValueResultList[k].valStr);
607 //              printf("Value - %s\n", keyValueResultList[k].valStr);
608            }
609            return 0; //Success
610         }
611      }
612   }
613   printf("The parameter %s is not present in JSON file\n", param);
614   return 2; //parameter not found
615 }