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