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