14022ca07c1f606bb939ee6e26aab1e38c566663
[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             free(key);
313             json_set_error(error, lex, "':' expected");
314             goto error;
315         }
316
317         json_lex_scan(lex);
318
319         value = json_parse(lex, error);
320         if(!value) {
321             free(key);
322             goto error;
323         }
324
325         if(json_object_set(object, key, value)) {
326             free(key);
327             json_decref(value);
328             goto error;
329         }
330
331         json_decref(value);
332         free(key);
333
334         if(lex->token != ',')
335             break;
336
337         json_lex_scan(lex);
338     }
339
340     if(lex->token != '}') {
341         json_set_error(error, lex, "'}' expected");
342         goto error;
343     }
344
345     return object;
346
347 error:
348     json_decref(object);
349     return NULL;
350 }
351
352 static json_t *json_parse_array(json_lex *lex, json_error_t *error)
353 {
354     json_t *array = json_array();
355     if(!array)
356         return NULL;
357
358     json_lex_scan(lex);
359     if(lex->token != ']') {
360         while(1) {
361             json_t *elem = json_parse(lex, error);
362             if(!elem)
363                 goto error;
364
365             if(json_array_append(array, elem)) {
366                 json_decref(elem);
367                 goto error;
368             }
369             json_decref(elem);
370
371             if(lex->token != ',')
372                 break;
373
374             json_lex_scan(lex);
375         }
376     }
377
378     if(lex->token != ']') {
379         json_set_error(error, lex, "']' expected");
380         goto error;
381     }
382
383     return array;
384
385 error:
386     json_decref(array);
387     return NULL;
388 }
389
390 static json_t *json_parse(json_lex *lex, json_error_t *error)
391 {
392     json_t *json;
393
394     switch(lex->token) {
395         case JSON_TOKEN_STRING: {
396             json = json_string(lex->value.string);
397             break;
398         }
399
400         case JSON_TOKEN_NUMBER: {
401             json = json_number(lex->value.number);
402             break;
403         }
404
405         case JSON_TOKEN_TRUE:
406             json = json_true();
407             break;
408
409         case JSON_TOKEN_FALSE:
410             json = json_false();
411             break;
412
413         case JSON_TOKEN_NULL:
414             json = json_null();
415             break;
416
417         case '{':
418           json = json_parse_object(lex, error);
419             break;
420
421         case '[':
422             json = json_parse_array(lex, error);
423             break;
424
425         case JSON_TOKEN_INVALID:
426             json_set_error(error, lex, "invalid token");
427             return NULL;
428
429         default:
430             json_set_error(error, lex, "unexpected token");
431             return NULL;
432     }
433
434     if(!json)
435         return NULL;
436
437     json_lex_scan(lex);
438     return json;
439 }
440
441 json_t *json_load(const char *path, json_error_t *error)
442 {
443     json_t *result;
444     FILE *fp;
445
446     fp = fopen(path, "r");
447     if(!fp)
448     {
449         json_set_error(error, NULL, "unable to open %s: %s",
450                        path, strerror(errno));
451         return NULL;
452     }
453
454     result = json_loadf(fp, error);
455
456     fclose(fp);
457     return result;
458 }
459
460 json_t *json_loads(const char *string, json_error_t *error)
461 {
462     json_lex lex;
463     json_t *result = NULL;
464
465     if(json_lex_init(&lex, string))
466         return NULL;
467
468     if(lex.token != '[' && lex.token != '{') {
469         json_set_error(error, &lex, "'[' or '{' expected");
470         goto out;
471     }
472
473     result = json_parse(&lex, error);
474     if(!result)
475         goto out;
476
477     if(lex.token != JSON_TOKEN_EOF) {
478         json_set_error(error, &lex, "end of file expected");
479         json_decref(result);
480         result = NULL;
481     }
482
483 out:
484     json_lex_close(&lex);
485     return result;
486 }
487
488 #define BUFFER_SIZE 4096
489
490 json_t *json_loadf(FILE *input, json_error_t *error)
491 {
492     strbuffer_t strbuff;
493     char buffer[BUFFER_SIZE];
494     size_t length;
495     json_t *result = NULL;
496
497     strbuffer_init(&strbuff);
498
499     while(1)
500     {
501         length = fread(buffer, 1, BUFFER_SIZE, input);
502         if(length == 0)
503         {
504             if(ferror(input))
505             {
506                 json_set_error(error, NULL, "read error");
507                 goto out;
508             }
509             break;
510         }
511         if(strbuffer_append_bytes(&strbuff, buffer, length))
512             goto out;
513     }
514
515     result = json_loads(strbuffer_value(&strbuff), error);
516
517 out:
518     strbuffer_close(&strbuff);
519     return result;
520 }
521
522 json_t *json_loadfd(int fd, json_error_t *error)
523 {
524     strbuffer_t strbuff;
525     char buffer[BUFFER_SIZE];
526     ssize_t length;
527     json_t *result = NULL;
528
529     strbuffer_init(&strbuff);
530
531     while(1)
532     {
533         length = read(fd, buffer, BUFFER_SIZE);
534         if(length == -1)
535         {
536             json_set_error(error, NULL, "read error: %s", strerror(errno));
537             goto out;
538         }
539         else if(length == 0)
540             break;
541
542         if(strbuffer_append_bytes(&strbuff, buffer, length))
543         {
544             json_set_error(error, NULL, "error allocating memory");
545             goto out;
546         }
547     }
548
549     result = json_loads(strbuffer_value(&strbuff), error);
550
551 out:
552     strbuffer_close(&strbuff);
553     return result;
554 }