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