1 /*************************************************************************//**
3 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
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
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 ****************************************************************************/
24 * Allocates a fresh unused token from the token pull.
26 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
27 jsmntok_t *tokens, size_t num_tokens) {
29 if (parser->toknext >= num_tokens) {
32 tok = &tokens[parser->toknext++];
33 tok->start = tok->end = -1;
35 //#ifdef JSMN_PARENT_LINKS
42 * Fills token type and boundaries.
44 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
46 //printf("jsmn_fill_token:: start-%d, end-%d\n", start, end);
54 * Fills next available token with JSON primitive.
56 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
57 size_t len, jsmntok_t *tokens, size_t num_tokens) {
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]) {
67 /* In strict mode primitive must be followed by "," or "}" or "]" */
70 case '\t' : case '\r' : case '\n' : case ' ' :
71 case ',' : case ']' : case '}' :
74 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
76 return JSMN_ERROR_INVAL;
80 /* In strict mode primitive must be followed by a comma/object/array */
82 return JSMN_ERROR_PART;
90 token = jsmn_alloc_token(parser, tokens, num_tokens);
93 return JSMN_ERROR_NOMEM;
95 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
96 //#ifdef JSMN_PARENT_LINKS
97 token->parent = parser->toksuper;
104 * Fills next token with JSON string.
106 static int jsmn_parse_string(jsmn_parser *parser, const char *js,
107 size_t len, jsmntok_t *tokens, size_t num_tokens) {
110 int start = parser->pos;
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);
121 /* Quote: end of string */
124 // if ((d == '\"')&&((e == ' ')||(e == ','))) {
126 //printf("jsmn_parse_string: end of string\n");
127 if (tokens == NULL) {
128 //printf("jsmn_parse_string: end tokens is NULL\n");
131 token = jsmn_alloc_token(parser, tokens, num_tokens);
132 //printf("jsmn_parse_string: Allocated tokens \n");
134 //printf("jsmn_parse_string: Allocated tokens is NULL\n");
136 return JSMN_ERROR_NOMEM;
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;
146 /* Backslash: Quoted symbol expected */
147 if (c == '\\' && parser->pos + 1 < len) {
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' :
156 /* Allows escaped symbol \uXXXX */
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 */
165 return JSMN_ERROR_INVAL;
171 /* Unexpected symbol */
174 return JSMN_ERROR_INVAL;
179 printf("jsmn_parse_string: exiting with ERROR_PART, pos-%d", parser->pos);
180 return JSMN_ERROR_PART;
184 * Parse JSON string and fill tokens.
186 int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
187 jsmntok_t *tokens, unsigned int num_tokens) {
191 int count = parser->toknext;
193 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
198 //printf("jsmn_parse: value of c - %c\n",c);
202 if (tokens == NULL) {
205 token = jsmn_alloc_token(parser, tokens, num_tokens);
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;
214 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
215 token->start = parser->pos;
216 parser->toksuper = parser->toknext - 1;
221 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
222 //#ifdef JSMN_PARENT_LINKS
223 if (parser->toknext < 1) {
224 return JSMN_ERROR_INVAL;
226 token = &tokens[parser->toknext - 1];
228 if (token->start != -1 && token->end == -1) {
229 if (token->type != type) {
230 return JSMN_ERROR_INVAL;
232 token->end = parser->pos + 1;
233 parser->toksuper = token->parent;
236 if (token->parent == -1) {
239 token = &tokens[token->parent];
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;
248 // parser->toksuper = -1;
249 // token->end = parser->pos + 1;
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;
265 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
268 if (parser->toksuper != -1 && tokens != NULL)
269 tokens[parser->toksuper].size++;
271 case '\t' : case '\r' : case '\n' : case ' ':
274 parser->toksuper = parser->toknext - 1;
275 //printf("jsmn_parse: value of c is :: - %c\n",c);
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;
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;
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;
309 /* In non-strict mode every unquoted value is a primitive */
312 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
315 if (parser->toksuper != -1 && tokens != NULL)
316 tokens[parser->toksuper].size++;
320 /* Unexpected char in strict mode */
322 return JSMN_ERROR_INVAL;
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;
341 * Creates a new parser based over a given buffer with an array of tokens
344 void jsmn_init(jsmn_parser *parser) {
347 parser->toksuper = -1;
350 int jsoneq(const char *json, jsmntok_t *tok, const char *s)
352 if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
353 strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
359 void printToken(char * js, jsmntok_t * tokens, int numToken)
361 for (int i = 1; i < numToken; i++)
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);
371 printf("value?? - ");
372 TOKEN_PRINT(tokens[i]);
377 int getStringToken(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, char * value, int maxValueSize)
382 memset(value, 0, maxValueSize);
384 for (i = 1; i < numToken; i++)
386 if(jsoneq(js, &tokens[i], pParam) == 0)
395 printf("The parameter %s is not present in JSON file\n", pParam);
396 return 1; //Parent token not seen
398 for (i=1; i < numToken; i++)
400 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
402 if(jsoneq(js, &tokens[i], param) != 0)
404 TOKEN_COPY(js, tokens[i+1], value);
409 printf("The parameter %s is not present in JSON file\n", param);
410 return 2; //parameter not found
414 int getStringTokenV2(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, char * gParam,char * value, int maxValueSize)
419 memset(value, 0, maxValueSize);
421 for (i = 1; i < numToken; i++)
423 if(jsoneq(js, &tokens[i], gParam) == 0)
432 printf("The parameter %s is not present in JSON file\n", pParam);
433 return 1; //Grand Parent token not seen
436 for (i=dpToken; i < numToken; i++)
438 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
440 if(jsoneq(js, &tokens[i], pParam) == 0)
450 printf("The parameter %s is not present in JSON file\n", pParam);
451 return 2; //Parent token not seen
454 for (i=dpToken; i < numToken; i++)
456 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
458 if(jsoneq(js, &tokens[i], param) != 0)
460 TOKEN_COPY(js, tokens[i+1], value);
466 printf("The parameter %s is not present in JSON file\n", param);
467 return 2; //parameter not found
470 int getIntToken(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, int * value)
477 for (i = 1; i < numToken; i++)
479 if(jsoneq(js, &tokens[i], pParam) == 0)
488 printf("The parameter %s is not present in JSON file\n", pParam);
489 return 1; //Parent token not seen
491 for (i=1; i < numToken; i++)
493 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
495 if(jsoneq(js, &tokens[i], param) != 0)
500 if(tokens[i+1].type != JSMN_PRIMITIVE)
501 return 3; //Wrong parameter type
503 // printf("INT parameter / Value - %s", param);
504 TOKEN_COPY(js, tokens[i+1], val);
506 // printf(" - %d\n", *value);
511 printf("The parameter %s is not present in JSON file\n", param);
512 return 2; //parameter not found
515 void parseDirectParameters(char * js, jsmntok_t * tokens, int numToken)
522 for (i = 1; i < numToken; i++)
524 if(jsoneq(js, &tokens[i], "directParameters") == 0)
533 for (int i = 1; i < numToken; i++)
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)
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);
547 int getArrayTokens(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, ARRAYVAL * arrayValue, int * numElements)
552 for (i = 1; i < numToken; i++)
554 if(jsoneq(js, &tokens[i], pParam) == 0)
563 printf("The parameter %s is not present in JSON file\n", pParam);
564 return 1; //Parent token not seen
566 for (i=1; i < numToken; i++)
568 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
570 // printf("value of token %d\n", i);
571 if(jsoneq(js, &tokens[i], param) != 0)
574 if (tokens[i+1].type == JSMN_ARRAY)
576 *numElements = tokens[i+1].size;
577 // printf("[%d elems]\n", *numElements);
579 for (int k = 0; k < *numElements; k++)
581 TOKEN_COPY(js, tokens[i+2+k], arrayValue[k].arrayString);
582 // printf(" - %s\n", arrayValue[k].arrayString);
588 printf("The parameter %s is not present in JSON file\n", param);
589 return 2; //parameter not found
592 int isTokenPresent(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam)
599 for (i = 1; i < numToken; i++)
601 if(jsoneq(js, &tokens[i], pParam) == 0)
610 printf("The parameter %s is not present in JSON file\n", pParam);
611 return 1; //Parent token not seen
613 for (i=1; i < numToken; i++)
615 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING)
617 if(jsoneq(js, &tokens[i], param) == 0)
619 return 0; //Token present
623 printf("The parameter %s is not present in JSON file\n", param);
624 return 2; //Token Not present
627 int read_keyVal_params(char * js, jsmntok_t * tokens, int numToken, char * param, char * pParam, KEYVALRESULT * keyValueResultList, int * numElements)
632 for (i = 1; i < numToken; i++)
634 if(jsoneq(js, &tokens[i], pParam) == 0)
643 printf("The parameter %s is not present in JSON file\n", pParam);
644 return 1; //Parent token not seen
646 for (i=1; i < numToken; i++)
648 if (tokens[i].parent == dpToken && tokens[i].type == JSMN_STRING && tokens[i].size == 1)
650 // printf("value of token %d\n", i);
651 if(jsoneq(js, &tokens[i], param) != 0)
654 if (tokens[i+1].type == JSMN_OBJECT)
656 *numElements = tokens[i+1].size;
657 // printf("{%d elems}\n", *numElements);
659 for (int k = 0; k < *numElements; k++)
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);
670 printf("The parameter %s is not present in JSON file\n", param);
671 return 2; //parameter not found