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