4fb8c1bc606c7ca0c245f78f2d991e81b351ad84
[jansson.git] / src / pack_unpack.c
1 /*
2  * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
3  * Copyright (c) 2011 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
4  *
5  * Jansson is free software; you can redistribute it and/or modify
6  * it under the terms of the MIT license. See LICENSE for details.
7  */
8
9 #include <jansson.h>
10 #include "jansson_private.h"
11
12 typedef struct {
13     const char *start;
14     const char *fmt;
15     char token;
16     json_error_t *error;
17     size_t flags;
18     int line;
19     int column;
20 } scanner_t;
21
22 static const char *type_names[] = {
23     "object",
24     "array",
25     "string",
26     "integer",
27     "real",
28     "true",
29     "false",
30     "null"
31 };
32
33 #define type_name(x) type_names[json_typeof(x)]
34
35 static void next_token(scanner_t *s)
36 {
37     const char *t = s->fmt;
38     s->column++;
39
40     /* skip space and ignored chars */
41     while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
42         if(*t == '\n') {
43             s->line++;
44             s->column = 1;
45         }
46         else
47             s->column++;
48
49         t++;
50     }
51
52     s->token = *t;
53
54     t++;
55     s->fmt = t;
56 }
57
58 static void set_error(scanner_t *s, const char *fmt, ...)
59 {
60     va_list ap;
61     size_t pos;
62     va_start(ap, fmt);
63
64     pos = (size_t)(s->fmt - s->start);
65     jsonp_error_vset(s->error, s->line, s->column, pos, fmt, ap);
66
67     va_end(ap);
68 }
69
70 static json_t *pack(scanner_t *s, va_list *ap);
71
72 static json_t *pack_object(scanner_t *s, va_list *ap)
73 {
74     json_t *object = json_object();
75     next_token(s);
76
77     while(s->token != '}') {
78         const char *key;
79         json_t *value;
80
81         if(!s->token) {
82             set_error(s, "Unexpected end of format string");
83             goto error;
84         }
85
86         if(s->token != 's') {
87             set_error(s, "Expected format 's', got '%c'\n", *s->fmt);
88             goto error;
89         }
90
91         key = va_arg(*ap, const char *);
92         if(!key) {
93             set_error(s, "NULL object key");
94             goto error;
95         }
96
97         next_token(s);
98
99         value = pack(s, ap);
100         if(!value)
101             goto error;
102
103         if(json_object_set_new(object, key, value)) {
104             set_error(s, "Unable to add key \"%s\"", key);
105             goto error;
106         }
107
108         next_token(s);
109     }
110
111     return object;
112
113 error:
114     json_decref(object);
115     return NULL;
116 }
117
118 static json_t *pack_array(scanner_t *s, va_list *ap)
119 {
120     json_t *array = json_array();
121     next_token(s);
122
123     while(s->token != ']') {
124         json_t *value;
125
126         if(!s->token) {
127             set_error(s, "Unexpected end of format string");
128             goto error;
129         }
130
131         value = pack(s, ap);
132         if(!value)
133             goto error;
134
135         if(json_array_append_new(array, value)) {
136             set_error(s, "Unable to append to array");
137             goto error;
138         }
139
140         next_token(s);
141     }
142     return array;
143
144 error:
145     json_decref(array);
146     return NULL;
147 }
148
149 static json_t *pack(scanner_t *s, va_list *ap)
150 {
151     switch(s->token) {
152         case '{':
153             return pack_object(s, ap);
154
155         case '[':
156             return pack_array(s, ap);
157
158         case 's': /* string */
159         {
160             const char *str = va_arg(*ap, const char *);
161             if(!str) {
162                 set_error(s, "NULL string");
163                 return NULL;
164             }
165             return json_string(str);
166         }
167
168         case 'n': /* null */
169             return json_null();
170
171         case 'b': /* boolean */
172             return va_arg(*ap, int) ? json_true() : json_false();
173
174         case 'i': /* integer from int */
175             return json_integer(va_arg(*ap, int));
176
177         case 'I': /* integer from json_int_t */
178             return json_integer(va_arg(*ap, json_int_t));
179
180         case 'f': /* real */
181             return json_real(va_arg(*ap, double));
182
183         case 'O': /* a json_t object; increments refcount */
184             return json_incref(va_arg(*ap, json_t *));
185
186         case 'o': /* a json_t object; doesn't increment refcount */
187             return va_arg(*ap, json_t *);
188
189         default:
190             set_error(s, "Unrecognized format character '%c'", s->token);
191             return NULL;
192     }
193 }
194
195 static int unpack(scanner_t *s, json_t *root, va_list *ap);
196
197 static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
198 {
199     int ret = -1;
200     int strict = 0;
201
202     /* Use a set (emulated by a hashtable) to check that all object
203        keys are accessed. Checking that the correct number of keys
204        were accessed is not enough, as the same key can be unpacked
205        multiple times.
206     */
207     hashtable_t key_set;
208
209     if(hashtable_init(&key_set, jsonp_hash_key, jsonp_key_equal, NULL, NULL)) {
210         set_error(s, "Out of memory");
211         return -1;
212     }
213
214     if(!json_is_object(root)) {
215         set_error(s, "Expected object, got %s", type_name(root));
216         goto out;
217     }
218     next_token(s);
219
220     while(s->token != '}') {
221         const char *key;
222         json_t *value;
223
224         if(strict != 0) {
225             set_error(s, "Expected '}' after '%c', got '%c'",
226                       (strict == 1 ? '!' : '*'), s->token);
227             goto out;
228         }
229
230         if(!s->token) {
231             set_error(s, "Unexpected end of format string");
232             goto out;
233         }
234
235         if(s->token == '!' || s->token == '*') {
236             strict = (s->token == '!' ? 1 : -1);
237             next_token(s);
238             continue;
239         }
240
241         if(s->token != 's') {
242             set_error(s, "Expected format 's', got '%c'\n", *s->fmt);
243             goto out;
244         }
245
246         key = va_arg(*ap, const char *);
247         if(!key) {
248             set_error(s, "NULL object key");
249             goto out;
250         }
251
252         next_token(s);
253
254         value = json_object_get(root, key);
255         if(unpack(s, value, ap))
256             goto out;
257
258         hashtable_set(&key_set, (void *)key, NULL);
259         next_token(s);
260     }
261
262     if(strict == 0 && (s->flags & JSON_STRICT))
263         strict = 1;
264
265     if(strict == 1 && key_set.size != json_object_size(root)) {
266         long diff = (long)json_object_size(root) - (long)key_set.size;
267         set_error(s, "%li object items left unpacked", diff);
268         goto out;
269     }
270
271     ret = 0;
272
273 out:
274     hashtable_close(&key_set);
275     return ret;
276 }
277
278 static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
279 {
280     size_t i = 0;
281     int strict = 0;
282
283     if(!json_is_array(root)) {
284         set_error(s, "Expected array, got %s", type_name(root));
285         return -1;
286     }
287     next_token(s);
288
289     while(s->token != ']') {
290         json_t *value;
291
292         if(strict != 0) {
293             set_error(s, "Expected ']' after '%c', got '%c'",
294                       (strict == 1 ? '!' : '*'),
295                       s->token);
296             return -1;
297         }
298
299         if(!s->token) {
300             set_error(s, "Unexpected end of format string");
301             return -1;
302         }
303
304         if(s->token == '!' || s->token == '*') {
305             strict = (s->token == '!' ? 1 : -1);
306             next_token(s);
307             continue;
308         }
309
310         value = json_array_get(root, i);
311         if(!value) {
312             set_error(s, "Array index %lu out of range", (unsigned long)i);
313             return -1;
314         }
315
316         if(unpack(s, value, ap))
317             return -1;
318
319         next_token(s);
320         i++;
321     }
322
323     if(strict == 0 && (s->flags & JSON_STRICT))
324         strict = 1;
325
326     if(strict == 1 && i != json_array_size(root)) {
327         long diff = (long)json_array_size(root) - (long)i;
328         set_error(s, "%li array items left upacked", diff);
329         return -1;
330     }
331
332     return 0;
333 }
334
335 static int unpack(scanner_t *s, json_t *root, va_list *ap)
336 {
337     switch(s->token)
338     {
339         case '{':
340             return unpack_object(s, root, ap);
341
342         case '[':
343             return unpack_array(s, root, ap);
344
345         case 's':
346             if(!json_is_string(root)) {
347                 set_error(s, "Expected string, got %s", type_name(root));
348                 return -1;
349             }
350
351             if(!(s->flags & JSON_VALIDATE_ONLY)) {
352                 const char **str;
353
354                 str = va_arg(*ap, const char **);
355                 if(!str) {
356                     set_error(s, "NULL string");
357                     return -1;
358                 }
359
360                 *str = json_string_value(root);
361             }
362             return 0;
363
364         case 'i':
365             if(!json_is_integer(root)) {
366                 set_error(s, "Expected integer, got %s", type_name(root));
367                 return -1;
368             }
369
370             if(!(s->flags & JSON_VALIDATE_ONLY))
371                 *va_arg(*ap, int*) = json_integer_value(root);
372
373             return 0;
374
375         case 'I':
376             if(!json_is_integer(root)) {
377                 set_error(s, "Expected integer, got %s", type_name(root));
378                 return -1;
379             }
380
381             if(!(s->flags & JSON_VALIDATE_ONLY))
382                 *va_arg(*ap, json_int_t*) = json_integer_value(root);
383
384             return 0;
385
386         case 'b':
387             if(!json_is_boolean(root)) {
388                 set_error(s, "Expected true or false, got %s", type_name(root));
389                 return -1;
390             }
391
392             if(!(s->flags & JSON_VALIDATE_ONLY))
393                 *va_arg(*ap, int*) = json_is_true(root);
394
395             return 0;
396
397         case 'f':
398             if(!json_is_real(root)) {
399                 set_error(s, "Expected real, got %s", type_name(root));
400                 return -1;
401             }
402
403             if(!(s->flags & JSON_VALIDATE_ONLY))
404                 *va_arg(*ap, double*) = json_real_value(root);
405
406             return 0;
407
408         case 'F':
409             if(!json_is_number(root)) {
410                 set_error(s, "Expected real or integer, got %s",
411                           type_name(root));
412                 return -1;
413             }
414
415             if(!(s->flags & JSON_VALIDATE_ONLY))
416                 *va_arg(*ap, double*) = json_number_value(root);
417
418             return 0;
419
420         case 'O':
421             if(!(s->flags & JSON_VALIDATE_ONLY))
422                 json_incref(root);
423             /* Fall through */
424
425         case 'o':
426             if(!(s->flags & JSON_VALIDATE_ONLY))
427                 *va_arg(*ap, json_t**) = root;
428
429             return 0;
430
431         case 'n':
432             /* Never assign, just validate */
433             if(!json_is_null(root)) {
434                 set_error(s, "Expected null, got %s", type_name(root));
435                 return -1;
436             }
437             return 0;
438
439         default:
440             set_error(s, "Unknown format character '%c'", s->token);
441             return -1;
442     }
443 }
444
445 json_t *json_vpack_ex(json_error_t *error, size_t flags,
446                       const char *fmt, va_list ap)
447 {
448     scanner_t s;
449     va_list ap_copy;
450     json_t *value;
451
452     jsonp_error_init(error, "");
453
454     if(!fmt || !*fmt) {
455         jsonp_error_set(error, -1, -1, 0, "Null or empty format string");
456         return NULL;
457     }
458
459     s.error = error;
460     s.flags = flags;
461     s.fmt = s.start = fmt;
462     s.line = 1;
463     s.column = 0;
464
465     next_token(&s);
466     va_copy(ap_copy, ap);
467     value = pack(&s, &ap_copy);
468     va_end(ap_copy);
469
470     next_token(&s);
471     if(s.token) {
472         json_decref(value);
473         set_error(&s, "Garbage after format string");
474         return NULL;
475     }
476
477     return value;
478 }
479
480 json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...)
481 {
482     json_t *value;
483     va_list ap;
484
485     va_start(ap, fmt);
486     value = json_vpack_ex(error, flags, fmt, ap);
487     va_end(ap);
488
489     return value;
490 }
491
492 json_t *json_pack(const char *fmt, ...)
493 {
494     json_t *value;
495     va_list ap;
496
497     va_start(ap, fmt);
498     value = json_vpack_ex(NULL, 0, fmt, ap);
499     va_end(ap);
500
501     return value;
502 }
503
504 int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
505                     const char *fmt, va_list ap)
506 {
507     scanner_t s;
508     va_list ap_copy;
509
510     jsonp_error_init(error, "");
511
512     if(!fmt || !*fmt) {
513         jsonp_error_set(error, -1, -1, 0, "Null or empty format string");
514         return -1;
515     }
516
517     s.error = error;
518     s.flags = flags;
519     s.fmt = s.start = fmt;
520     s.line = 1;
521     s.column = 0;
522
523     next_token(&s);
524
525     va_copy(ap_copy, ap);
526     if(unpack(&s, root, &ap_copy)) {
527         va_end(ap_copy);
528         return -1;
529     }
530     va_end(ap_copy);
531
532     next_token(&s);
533     if(s.token) {
534         set_error(&s, "Garbage after format string");
535         return -1;
536     }
537
538     return 0;
539 }
540
541 int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...)
542 {
543     int ret;
544     va_list ap;
545
546     va_start(ap, fmt);
547     ret = json_vunpack_ex(root, error, flags, fmt, ap);
548     va_end(ap);
549
550     return ret;
551 }
552
553 int json_unpack(json_t *root, const char *fmt, ...)
554 {
555     int ret;
556     va_list ap;
557
558     va_start(ap, fmt);
559     ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
560     va_end(ap);
561
562     return ret;
563 }