Unify naming in parser
[jansson.git] / src / load.c
1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdarg.h>
8 #include <unistd.h>
9 #include <assert.h>
10
11 #include <jansson.h>
12 #include "strbuffer.h"
13
14 #define TOKEN_INVALID         -1
15 #define TOKEN_EOF              0
16 #define TOKEN_STRING         256
17 #define TOKEN_INTEGER        257
18 #define TOKEN_REAL           258
19 #define TOKEN_TRUE           259
20 #define TOKEN_FALSE          260
21 #define TOKEN_NULL           261
22
23 typedef struct {
24     const char *input;
25     const char *start;
26     int token;
27     int line, column;
28     union {
29         char *string;
30         int integer;
31         double real;
32     } value;
33 } lex_t;
34
35
36 /*** error reporting ***/
37
38 static void error_set(json_error_t *error, const lex_t *lex,
39                       const char *msg, ...)
40 {
41     va_list ap;
42     char text[JSON_ERROR_TEXT_LENGTH];
43
44     if(!error)
45         return;
46
47     va_start(ap, msg);
48     vsnprintf(text, JSON_ERROR_TEXT_LENGTH, msg, ap);
49     va_end(ap);
50
51     if(lex)
52     {
53         error->line = lex->line;
54         if(*lex->start)
55         {
56             int n = (int)(lex->input - lex->start);
57             snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
58                      "%s near '%.*s'", text, n, lex->start);
59         }
60         else
61         {
62             snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
63                      "%s near end of file", text);
64         }
65     }
66     else
67     {
68         error->line = -1;
69         snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
70     }
71 }
72
73
74 /*** lexical analyzer ***/
75
76 static void lex_scan_string(lex_t *lex)
77 {
78     /* skip the " */
79     const char *p = lex->input + 1;
80     char *t;
81
82     lex->token = TOKEN_INVALID;
83
84     while(*p != '"') {
85         if(*p == '\0') {
86             /* unterminated string literal */
87             goto out;
88         }
89
90         if(0 <= *p && *p <= 0x1F) {
91             /* control character */
92             goto out;
93         }
94         else if(*p == '\\') {
95             p++;
96             if(*p == 'u') {
97                 p++;
98                 for(int i = 0; i < 4; i++, p++) {
99                     if(!isxdigit(*p))
100                         goto out;
101                 }
102             }
103             else if(*p == '"' || *p == '\\' || *p == '/' || *p == 'b' ||
104                     *p == 'f' || *p == 'n' || *p == 'r' || *p == 't')
105                 p++;
106             else
107                 goto out;
108         }
109         else
110             p++;
111     }
112
113     /* the actual value is at most of the same length as the source
114        string */
115     lex->value.string = malloc(p - lex->start);
116     if(!lex->value.string) {
117         /* this is not very nice, since TOKEN_INVALID is returned */
118         goto out;
119     }
120
121     /* the target */
122     t = lex->value.string;
123
124     p = lex->input + 1;
125     while(*p != '"') {
126         if(*p == '\\') {
127             p++;
128             if(*p == 'u') {
129                 /* TODO: \uXXXX not supported yet */
130                 free(lex->value.string);
131                 lex->value.string = NULL;
132                 goto out;
133             } else {
134                 switch(*p) {
135                     case '"': case '\\': case '/':
136                         *t = *p; break;
137                     case 'b': *t = '\b'; break;
138                     case 'f': *t = '\f'; break;
139                     case 'n': *t = '\n'; break;
140                     case 'r': *t = '\r'; break;
141                     case 't': *t = '\t'; break;
142                     default: assert(0);
143                 }
144             }
145         }
146         else
147             *t = *p;
148
149         t++;
150         p++;
151     }
152     /* skip the " */
153     p++;
154
155     *t = '\0';
156     lex->token = TOKEN_STRING;
157
158 out:
159     lex->input = p;
160 }
161
162 static void lex_scan_number(lex_t *lex)
163 {
164     const char *p = lex->input;
165     char *end;
166
167     lex->token = TOKEN_INVALID;
168
169     if(*p == '-')
170         p++;
171
172     if(*p == '0') {
173         p++;
174         if(isdigit(*p))
175           goto out;
176     }
177     else /* *p != '0' */ {
178         p++;
179         while(isdigit(*p))
180             p++;
181     }
182
183     if(*p != '.' && *p != 'E' && *p != 'e') {
184         lex->token = TOKEN_INTEGER;
185
186         lex->value.integer = strtol(lex->start, &end, 10);
187         assert(end == p);
188
189         goto out;
190     }
191
192     if(*p == '.') {
193         p++;
194         if(!isdigit(*p))
195             goto out;
196
197         p++;
198         while(isdigit(*p))
199             p++;
200     }
201
202     if(*p == 'E' || *p == 'e') {
203         p++;
204         if(*p == '+' || *p == '-')
205             p++;
206
207         if(!isdigit(*p))
208             goto out;
209
210         p++;
211         while(isdigit(*p))
212             p++;
213     }
214
215     lex->token = TOKEN_REAL;
216
217     lex->value.real = strtod(lex->start, &end);
218     assert(end == p);
219
220 out:
221     lex->input = p;
222 }
223
224 static int lex_scan(lex_t *lex)
225 {
226     char c;
227
228     if(lex->token == TOKEN_STRING) {
229       free(lex->value.string);
230       lex->value.string = NULL;
231     }
232
233     c = *lex->input;
234     while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
235     {
236         if(c == '\n')
237             lex->line++;
238
239         lex->input++;
240         c = *lex->input;
241     }
242
243     lex->start = lex->input;
244     c = *lex->input;
245
246     if(c == '\0')
247         lex->token = TOKEN_EOF;
248
249     else if(c == '{' || c == '}' || c == '[' || c == ']' ||
250             c == ':' || c == ',')
251     {
252         lex->token = c;
253         lex->input++;
254     }
255
256     else if(c == '"')
257         lex_scan_string(lex);
258
259     else if(isdigit(c) || c == '-')
260         lex_scan_number(lex);
261
262     else if(isupper(c) || islower(c)) {
263         /* eat up the whole identifier for clearer error messages */
264         int len;
265
266         while(isupper(*lex->input) || islower(*lex->input))
267             lex->input++;
268         len = lex->input - lex->start;
269
270         if(strncmp(lex->start, "true", len) == 0)
271             lex->token = TOKEN_TRUE;
272         else if(strncmp(lex->start, "false", len) == 0)
273             lex->token = TOKEN_FALSE;
274         else if(strncmp(lex->start, "null", len) == 0)
275             lex->token = TOKEN_NULL;
276         else
277             lex->token = TOKEN_INVALID;
278     }
279
280     else {
281         lex->token = TOKEN_INVALID;
282         lex->input++;
283     }
284
285     return lex->token;
286 }
287
288 static int lex_init(lex_t *lex, const char *input)
289 {
290     lex->input = input;
291     lex->token = TOKEN_INVALID;
292     lex->line = 1;
293
294     lex_scan(lex);
295     return 0;
296 }
297
298 static void lex_close(lex_t *lex)
299 {
300     if(lex->token == TOKEN_STRING)
301         free(lex->value.string);
302 }
303
304
305 /*** parser ***/
306
307 static json_t *parse(lex_t *lex, json_error_t *error);
308
309 static json_t *parse_object(lex_t *lex, json_error_t *error)
310 {
311     json_t *object = json_object();
312     if(!object)
313         return NULL;
314
315     lex_scan(lex);
316     if(lex->token == '}')
317         return object;
318
319     while(lex->token) {
320         char *key;
321         json_t *value;
322
323         if(lex->token != TOKEN_STRING) {
324             error_set(error, lex, "string expected");
325             goto error;
326         }
327
328         key = strdup(lex->value.string);
329         if(!key)
330             return NULL;
331
332         lex_scan(lex);
333         if(lex->token != ':') {
334             free(key);
335             error_set(error, lex, "':' expected");
336             goto error;
337         }
338
339         lex_scan(lex);
340
341         value = parse(lex, error);
342         if(!value) {
343             free(key);
344             goto error;
345         }
346
347         if(json_object_set(object, key, value)) {
348             free(key);
349             json_decref(value);
350             goto error;
351         }
352
353         json_decref(value);
354         free(key);
355
356         if(lex->token != ',')
357             break;
358
359         lex_scan(lex);
360     }
361
362     if(lex->token != '}') {
363         error_set(error, lex, "'}' expected");
364         goto error;
365     }
366
367     return object;
368
369 error:
370     json_decref(object);
371     return NULL;
372 }
373
374 static json_t *parse_array(lex_t *lex, json_error_t *error)
375 {
376     json_t *array = json_array();
377     if(!array)
378         return NULL;
379
380     lex_scan(lex);
381     if(lex->token == ']')
382         return array;
383
384     while(lex->token) {
385         json_t *elem = parse(lex, error);
386         if(!elem)
387             goto error;
388
389         if(json_array_append(array, elem)) {
390             json_decref(elem);
391             goto error;
392         }
393         json_decref(elem);
394
395         if(lex->token != ',')
396             break;
397
398         lex_scan(lex);
399     }
400
401
402     if(lex->token != ']') {
403         error_set(error, lex, "']' expected");
404         goto error;
405     }
406
407     return array;
408
409 error:
410     json_decref(array);
411     return NULL;
412 }
413
414 static json_t *parse(lex_t *lex, json_error_t *error)
415 {
416     json_t *json;
417
418     switch(lex->token) {
419         case TOKEN_STRING: {
420             json = json_string(lex->value.string);
421             break;
422         }
423
424         case TOKEN_INTEGER: {
425             json = json_integer(lex->value.integer);
426             break;
427         }
428
429         case TOKEN_REAL: {
430             json = json_real(lex->value.real);
431             break;
432         }
433
434         case TOKEN_TRUE:
435             json = json_true();
436             break;
437
438         case TOKEN_FALSE:
439             json = json_false();
440             break;
441
442         case TOKEN_NULL:
443             json = json_null();
444             break;
445
446         case '{':
447           json = parse_object(lex, error);
448             break;
449
450         case '[':
451             json = parse_array(lex, error);
452             break;
453
454         case TOKEN_INVALID:
455             error_set(error, lex, "invalid token");
456             return NULL;
457
458         default:
459             error_set(error, lex, "unexpected token");
460             return NULL;
461     }
462
463     if(!json)
464         return NULL;
465
466     lex_scan(lex);
467     return json;
468 }
469
470 json_t *json_load(const char *path, json_error_t *error)
471 {
472     json_t *result;
473     FILE *fp;
474
475     fp = fopen(path, "r");
476     if(!fp)
477     {
478         error_set(error, NULL, "unable to open %s: %s",
479                        path, strerror(errno));
480         return NULL;
481     }
482
483     result = json_loadf(fp, error);
484
485     fclose(fp);
486     return result;
487 }
488
489 json_t *json_loads(const char *string, json_error_t *error)
490 {
491     lex_t lex;
492     json_t *result = NULL;
493
494     if(lex_init(&lex, string))
495         return NULL;
496
497     if(lex.token != '[' && lex.token != '{') {
498         error_set(error, &lex, "'[' or '{' expected");
499         goto out;
500     }
501
502     result = parse(&lex, error);
503     if(!result)
504         goto out;
505
506     if(lex.token != TOKEN_EOF) {
507         error_set(error, &lex, "end of file expected");
508         json_decref(result);
509         result = NULL;
510     }
511
512 out:
513     lex_close(&lex);
514     return result;
515 }
516
517 #define BUFFER_SIZE 4096
518
519 json_t *json_loadf(FILE *input, json_error_t *error)
520 {
521     strbuffer_t strbuff;
522     char buffer[BUFFER_SIZE];
523     size_t length;
524     json_t *result = NULL;
525
526     if(strbuffer_init(&strbuff))
527       return NULL;
528
529     while(1)
530     {
531         length = fread(buffer, 1, BUFFER_SIZE, input);
532         if(length == 0)
533         {
534             if(ferror(input))
535             {
536                 error_set(error, NULL, "read error");
537                 goto out;
538             }
539             break;
540         }
541         if(strbuffer_append_bytes(&strbuff, buffer, length))
542             goto out;
543     }
544
545     result = json_loads(strbuffer_value(&strbuff), error);
546
547 out:
548     strbuffer_close(&strbuff);
549     return result;
550 }
551
552 json_t *json_loadfd(int fd, json_error_t *error)
553 {
554     strbuffer_t strbuff;
555     char buffer[BUFFER_SIZE];
556     ssize_t length;
557     json_t *result = NULL;
558
559     if(strbuffer_init(&strbuff))
560       return NULL;
561
562     while(1)
563     {
564         length = read(fd, buffer, BUFFER_SIZE);
565         if(length == -1)
566         {
567             error_set(error, NULL, "read error: %s", strerror(errno));
568             goto out;
569         }
570         else if(length == 0)
571             break;
572
573         if(strbuffer_append_bytes(&strbuff, buffer, length))
574         {
575             error_set(error, NULL, "error allocating memory");
576             goto out;
577         }
578     }
579
580     result = json_loads(strbuffer_value(&strbuff), error);
581
582 out:
583     strbuffer_close(&strbuff);
584     return result;
585 }