Cleanup code and correct License
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / evel_library / jsmn.c
1 /*************************************************************************//**
2  *
3  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and 
14  * limitations under the License.
15  *
16  ****************************************************************************/
17
18 #include "jsmn.h"
19
20 /**
21  * Allocates a fresh unused token from the token pull.
22  */
23 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
24                 jsmntok_t *tokens, size_t num_tokens) {
25         jsmntok_t *tok;
26         if (parser->toknext >= num_tokens) {
27                 return NULL;
28         }
29         tok = &tokens[parser->toknext++];
30         tok->start = tok->end = -1;
31         tok->size = 0;
32 #ifdef JSMN_PARENT_LINKS
33         tok->parent = -1;
34 #endif
35         return tok;
36 }
37
38 /**
39  * Fills token type and boundaries.
40  */
41 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
42                             int start, int end) {
43         token->type = type;
44         token->start = start;
45         token->end = end;
46         token->size = 0;
47 }
48
49 /**
50  * Fills next available token with JSON primitive.
51  */
52 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
53                 size_t len, jsmntok_t *tokens, size_t num_tokens) {
54         jsmntok_t *token;
55         int start;
56
57         start = parser->pos;
58
59         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
60                 switch (js[parser->pos]) {
61 #ifndef JSMN_STRICT
62                         /* In strict mode primitive must be followed by "," or "}" or "]" */
63                         case ':':
64 #endif
65                         case '\t' : case '\r' : case '\n' : case ' ' :
66                         case ','  : case ']'  : case '}' :
67                                 goto found;
68                 }
69                 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
70                         parser->pos = start;
71                         return JSMN_ERROR_INVAL;
72                 }
73         }
74 #ifdef JSMN_STRICT
75         /* In strict mode primitive must be followed by a comma/object/array */
76         parser->pos = start;
77         return JSMN_ERROR_PART;
78 #endif
79
80 found:
81         if (tokens == NULL) {
82                 parser->pos--;
83                 return 0;
84         }
85         token = jsmn_alloc_token(parser, tokens, num_tokens);
86         if (token == NULL) {
87                 parser->pos = start;
88                 return JSMN_ERROR_NOMEM;
89         }
90         jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
91 #ifdef JSMN_PARENT_LINKS
92         token->parent = parser->toksuper;
93 #endif
94         parser->pos--;
95         return 0;
96 }
97
98 /**
99  * Fills next token with JSON string.
100  */
101 static int jsmn_parse_string(jsmn_parser *parser, const char *js,
102                 size_t len, jsmntok_t *tokens, size_t num_tokens) {
103         jsmntok_t *token;
104
105         int start = parser->pos;
106
107         parser->pos++;
108
109         /* Skip starting quote */
110         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
111                 char c = js[parser->pos];
112
113                 /* Quote: end of string */
114                 if (c == '\"') {
115                         if (tokens == NULL) {
116                                 return 0;
117                         }
118                         token = jsmn_alloc_token(parser, tokens, num_tokens);
119                         if (token == NULL) {
120                                 parser->pos = start;
121                                 return JSMN_ERROR_NOMEM;
122                         }
123                         jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
124 #ifdef JSMN_PARENT_LINKS
125                         token->parent = parser->toksuper;
126 #endif
127                         return 0;
128                 }
129
130                 /* Backslash: Quoted symbol expected */
131                 if (c == '\\' && parser->pos + 1 < len) {
132                         int i;
133                         parser->pos++;
134                         switch (js[parser->pos]) {
135                                 /* Allowed escaped symbols */
136                                 case '\"': case '/' : case '\\' : case 'b' :
137                                 case 'f' : case 'r' : case 'n'  : case 't' :
138                                         break;
139                                 /* Allows escaped symbol \uXXXX */
140                                 case 'u':
141                                         parser->pos++;
142                                         for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
143                                                 /* If it isn't a hex character we have an error */
144                                                 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
145                                                                         (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
146                                                                         (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
147                                                         parser->pos = start;
148                                                         return JSMN_ERROR_INVAL;
149                                                 }
150                                                 parser->pos++;
151                                         }
152                                         parser->pos--;
153                                         break;
154                                 /* Unexpected symbol */
155                                 default:
156                                         parser->pos = start;
157                                         return JSMN_ERROR_INVAL;
158                         }
159                 }
160         }
161         parser->pos = start;
162         return JSMN_ERROR_PART;
163 }
164
165 /**
166  * Parse JSON string and fill tokens.
167  */
168 int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
169                 jsmntok_t *tokens, unsigned int num_tokens) {
170         int r;
171         int i;
172         jsmntok_t *token;
173         int count = parser->toknext;
174
175         for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
176                 char c;
177                 jsmntype_t type;
178
179                 c = js[parser->pos];
180                 switch (c) {
181                         case '{': case '[':
182                                 count++;
183                                 if (tokens == NULL) {
184                                         break;
185                                 }
186                                 token = jsmn_alloc_token(parser, tokens, num_tokens);
187                                 if (token == NULL)
188                                         return JSMN_ERROR_NOMEM;
189                                 if (parser->toksuper != -1) {
190                                         tokens[parser->toksuper].size++;
191 #ifdef JSMN_PARENT_LINKS
192                                         token->parent = parser->toksuper;
193 #endif
194                                 }
195                                 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
196                                 token->start = parser->pos;
197                                 parser->toksuper = parser->toknext - 1;
198                                 break;
199                         case '}': case ']':
200                                 if (tokens == NULL)
201                                         break;
202                                 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
203 #ifdef JSMN_PARENT_LINKS
204                                 if (parser->toknext < 1) {
205                                         return JSMN_ERROR_INVAL;
206                                 }
207                                 token = &tokens[parser->toknext - 1];
208                                 for (;;) {
209                                         if (token->start != -1 && token->end == -1) {
210                                                 if (token->type != type) {
211                                                         return JSMN_ERROR_INVAL;
212                                                 }
213                                                 token->end = parser->pos + 1;
214                                                 parser->toksuper = token->parent;
215                                                 break;
216                                         }
217                                         if (token->parent == -1) {
218                                                 break;
219                                         }
220                                         token = &tokens[token->parent];
221                                 }
222 #else
223                                 for (i = parser->toknext - 1; i >= 0; i--) {
224                                         token = &tokens[i];
225                                         if (token->start != -1 && token->end == -1) {
226                                                 if (token->type != type) {
227                                                         return JSMN_ERROR_INVAL;
228                                                 }
229                                                 parser->toksuper = -1;
230                                                 token->end = parser->pos + 1;
231                                                 break;
232                                         }
233                                 }
234                                 /* Error if unmatched closing bracket */
235                                 if (i == -1) return JSMN_ERROR_INVAL;
236                                 for (; i >= 0; i--) {
237                                         token = &tokens[i];
238                                         if (token->start != -1 && token->end == -1) {
239                                                 parser->toksuper = i;
240                                                 break;
241                                         }
242                                 }
243 #endif
244                                 break;
245                         case '\"':
246                                 r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
247                                 if (r < 0) return r;
248                                 count++;
249                                 if (parser->toksuper != -1 && tokens != NULL)
250                                         tokens[parser->toksuper].size++;
251                                 break;
252                         case '\t' : case '\r' : case '\n' : case ' ':
253                                 break;
254                         case ':':
255                                 parser->toksuper = parser->toknext - 1;
256                                 break;
257                         case ',':
258                                 if (tokens != NULL && parser->toksuper != -1 &&
259                                                 tokens[parser->toksuper].type != JSMN_ARRAY &&
260                                                 tokens[parser->toksuper].type != JSMN_OBJECT) {
261 #ifdef JSMN_PARENT_LINKS
262                                         parser->toksuper = tokens[parser->toksuper].parent;
263 #else
264                                         for (i = parser->toknext - 1; i >= 0; i--) {
265                                                 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
266                                                         if (tokens[i].start != -1 && tokens[i].end == -1) {
267                                                                 parser->toksuper = i;
268                                                                 break;
269                                                         }
270                                                 }
271                                         }
272 #endif
273                                 }
274                                 break;
275 #ifdef JSMN_STRICT
276                         /* In strict mode primitives are: numbers and booleans */
277                         case '-': case '0': case '1' : case '2': case '3' : case '4':
278                         case '5': case '6': case '7' : case '8': case '9':
279                         case 't': case 'f': case 'n' :
280                                 /* And they must not be keys of the object */
281                                 if (tokens != NULL && parser->toksuper != -1) {
282                                         jsmntok_t *t = &tokens[parser->toksuper];
283                                         if (t->type == JSMN_OBJECT ||
284                                                         (t->type == JSMN_STRING && t->size != 0)) {
285                                                 return JSMN_ERROR_INVAL;
286                                         }
287                                 }
288 #else
289                         /* In non-strict mode every unquoted value is a primitive */
290                         default:
291 #endif
292                                 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
293                                 if (r < 0) return r;
294                                 count++;
295                                 if (parser->toksuper != -1 && tokens != NULL)
296                                         tokens[parser->toksuper].size++;
297                                 break;
298
299 #ifdef JSMN_STRICT
300                         /* Unexpected char in strict mode */
301                         default:
302                                 return JSMN_ERROR_INVAL;
303 #endif
304                 }
305         }
306
307         if (tokens != NULL) {
308                 for (i = parser->toknext - 1; i >= 0; i--) {
309                         /* Unmatched opened object or array */
310                         if (tokens[i].start != -1 && tokens[i].end == -1) {
311                                 return JSMN_ERROR_PART;
312                         }
313                 }
314         }
315
316         return count;
317 }
318
319 /**
320  * Creates a new parser based over a given  buffer with an array of tokens
321  * available.
322  */
323 void jsmn_init(jsmn_parser *parser) {
324         parser->pos = 0;
325         parser->toknext = 0;
326         parser->toksuper = -1;
327 }
328