comparison extern/jansson/src/pack_unpack.c @ 0:8991989c4708

Initial import
author David Demelier <markand@malikania.fr>
date Tue, 22 Mar 2016 18:26:05 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8991989c4708
1 /*
2 * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
3 * Copyright (c) 2011-2012 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 <string.h>
10 #include "jansson.h"
11 #include "jansson_private.h"
12 #include "utf.h"
13
14 typedef struct {
15 int line;
16 int column;
17 size_t pos;
18 char token;
19 } token_t;
20
21 typedef struct {
22 const char *start;
23 const char *fmt;
24 token_t prev_token;
25 token_t token;
26 token_t next_token;
27 json_error_t *error;
28 size_t flags;
29 int line;
30 int column;
31 size_t pos;
32 } scanner_t;
33
34 #define token(scanner) ((scanner)->token.token)
35
36 static const char * const type_names[] = {
37 "object",
38 "array",
39 "string",
40 "integer",
41 "real",
42 "true",
43 "false",
44 "null"
45 };
46
47 #define type_name(x) type_names[json_typeof(x)]
48
49 static const char unpack_value_starters[] = "{[siIbfFOon";
50
51
52 static void scanner_init(scanner_t *s, json_error_t *error,
53 size_t flags, const char *fmt)
54 {
55 s->error = error;
56 s->flags = flags;
57 s->fmt = s->start = fmt;
58 memset(&s->prev_token, 0, sizeof(token_t));
59 memset(&s->token, 0, sizeof(token_t));
60 memset(&s->next_token, 0, sizeof(token_t));
61 s->line = 1;
62 s->column = 0;
63 s->pos = 0;
64 }
65
66 static void next_token(scanner_t *s)
67 {
68 const char *t;
69 s->prev_token = s->token;
70
71 if(s->next_token.line) {
72 s->token = s->next_token;
73 s->next_token.line = 0;
74 return;
75 }
76
77 t = s->fmt;
78 s->column++;
79 s->pos++;
80
81 /* skip space and ignored chars */
82 while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
83 if(*t == '\n') {
84 s->line++;
85 s->column = 1;
86 }
87 else
88 s->column++;
89
90 s->pos++;
91 t++;
92 }
93
94 s->token.token = *t;
95 s->token.line = s->line;
96 s->token.column = s->column;
97 s->token.pos = s->pos;
98
99 t++;
100 s->fmt = t;
101 }
102
103 static void prev_token(scanner_t *s)
104 {
105 s->next_token = s->token;
106 s->token = s->prev_token;
107 }
108
109 static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
110 {
111 va_list ap;
112 va_start(ap, fmt);
113
114 jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos,
115 fmt, ap);
116
117 jsonp_error_set_source(s->error, source);
118
119 va_end(ap);
120 }
121
122 static json_t *pack(scanner_t *s, va_list *ap);
123
124
125 /* ours will be set to 1 if jsonp_free() must be called for the result
126 afterwards */
127 static char *read_string(scanner_t *s, va_list *ap,
128 const char *purpose, size_t *out_len, int *ours)
129 {
130 char t;
131 strbuffer_t strbuff;
132 const char *str;
133 size_t length;
134
135 next_token(s);
136 t = token(s);
137 prev_token(s);
138
139 if(t != '#' && t != '%' && t != '+') {
140 /* Optimize the simple case */
141 str = va_arg(*ap, const char *);
142
143 if(!str) {
144 set_error(s, "<args>", "NULL string argument");
145 return NULL;
146 }
147
148 length = strlen(str);
149
150 if(!utf8_check_string(str, length)) {
151 set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
152 return NULL;
153 }
154
155 *out_len = length;
156 *ours = 0;
157 return (char *)str;
158 }
159
160 strbuffer_init(&strbuff);
161
162 while(1) {
163 str = va_arg(*ap, const char *);
164 if(!str) {
165 set_error(s, "<args>", "NULL string argument");
166 strbuffer_close(&strbuff);
167 return NULL;
168 }
169
170 next_token(s);
171
172 if(token(s) == '#') {
173 length = va_arg(*ap, int);
174 }
175 else if(token(s) == '%') {
176 length = va_arg(*ap, size_t);
177 }
178 else {
179 prev_token(s);
180 length = strlen(str);
181 }
182
183 if(strbuffer_append_bytes(&strbuff, str, length) == -1) {
184 set_error(s, "<internal>", "Out of memory");
185 strbuffer_close(&strbuff);
186 return NULL;
187 }
188
189 next_token(s);
190 if(token(s) != '+') {
191 prev_token(s);
192 break;
193 }
194 }
195
196 if(!utf8_check_string(strbuff.value, strbuff.length)) {
197 set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
198 strbuffer_close(&strbuff);
199 return NULL;
200 }
201
202 *out_len = strbuff.length;
203 *ours = 1;
204 return strbuffer_steal_value(&strbuff);
205 }
206
207 static json_t *pack_object(scanner_t *s, va_list *ap)
208 {
209 json_t *object = json_object();
210 next_token(s);
211
212 while(token(s) != '}') {
213 char *key;
214 size_t len;
215 int ours;
216 json_t *value;
217
218 if(!token(s)) {
219 set_error(s, "<format>", "Unexpected end of format string");
220 goto error;
221 }
222
223 if(token(s) != 's') {
224 set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
225 goto error;
226 }
227
228 key = read_string(s, ap, "object key", &len, &ours);
229 if(!key)
230 goto error;
231
232 next_token(s);
233
234 value = pack(s, ap);
235 if(!value) {
236 if(ours)
237 jsonp_free(key);
238
239 goto error;
240 }
241
242 if(json_object_set_new_nocheck(object, key, value)) {
243 if(ours)
244 jsonp_free(key);
245
246 set_error(s, "<internal>", "Unable to add key \"%s\"", key);
247 goto error;
248 }
249
250 if(ours)
251 jsonp_free(key);
252
253 next_token(s);
254 }
255
256 return object;
257
258 error:
259 json_decref(object);
260 return NULL;
261 }
262
263 static json_t *pack_array(scanner_t *s, va_list *ap)
264 {
265 json_t *array = json_array();
266 next_token(s);
267
268 while(token(s) != ']') {
269 json_t *value;
270
271 if(!token(s)) {
272 set_error(s, "<format>", "Unexpected end of format string");
273 goto error;
274 }
275
276 value = pack(s, ap);
277 if(!value)
278 goto error;
279
280 if(json_array_append_new(array, value)) {
281 set_error(s, "<internal>", "Unable to append to array");
282 goto error;
283 }
284
285 next_token(s);
286 }
287 return array;
288
289 error:
290 json_decref(array);
291 return NULL;
292 }
293
294 static json_t *pack(scanner_t *s, va_list *ap)
295 {
296 switch(token(s)) {
297 case '{':
298 return pack_object(s, ap);
299
300 case '[':
301 return pack_array(s, ap);
302
303 case 's': /* string */
304 {
305 char *str;
306 size_t len;
307 int ours;
308
309 str = read_string(s, ap, "string", &len, &ours);
310 if(!str)
311 return NULL;
312
313 if (ours)
314 return jsonp_stringn_nocheck_own(str, len);
315 else
316 return json_stringn_nocheck(str, len);
317 }
318
319 case 'n': /* null */
320 return json_null();
321
322 case 'b': /* boolean */
323 return va_arg(*ap, int) ? json_true() : json_false();
324
325 case 'i': /* integer from int */
326 return json_integer(va_arg(*ap, int));
327
328 case 'I': /* integer from json_int_t */
329 return json_integer(va_arg(*ap, json_int_t));
330
331 case 'f': /* real */
332 return json_real(va_arg(*ap, double));
333
334 case 'O': /* a json_t object; increments refcount */
335 return json_incref(va_arg(*ap, json_t *));
336
337 case 'o': /* a json_t object; doesn't increment refcount */
338 return va_arg(*ap, json_t *);
339
340 default:
341 set_error(s, "<format>", "Unexpected format character '%c'",
342 token(s));
343 return NULL;
344 }
345 }
346
347 static int unpack(scanner_t *s, json_t *root, va_list *ap);
348
349 static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
350 {
351 int ret = -1;
352 int strict = 0;
353 int gotopt = 0;
354
355 /* Use a set (emulated by a hashtable) to check that all object
356 keys are accessed. Checking that the correct number of keys
357 were accessed is not enough, as the same key can be unpacked
358 multiple times.
359 */
360 hashtable_t key_set;
361
362 if(hashtable_init(&key_set)) {
363 set_error(s, "<internal>", "Out of memory");
364 return -1;
365 }
366
367 if(root && !json_is_object(root)) {
368 set_error(s, "<validation>", "Expected object, got %s",
369 type_name(root));
370 goto out;
371 }
372 next_token(s);
373
374 while(token(s) != '}') {
375 const char *key;
376 json_t *value;
377 int opt = 0;
378
379 if(strict != 0) {
380 set_error(s, "<format>", "Expected '}' after '%c', got '%c'",
381 (strict == 1 ? '!' : '*'), token(s));
382 goto out;
383 }
384
385 if(!token(s)) {
386 set_error(s, "<format>", "Unexpected end of format string");
387 goto out;
388 }
389
390 if(token(s) == '!' || token(s) == '*') {
391 strict = (token(s) == '!' ? 1 : -1);
392 next_token(s);
393 continue;
394 }
395
396 if(token(s) != 's') {
397 set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
398 goto out;
399 }
400
401 key = va_arg(*ap, const char *);
402 if(!key) {
403 set_error(s, "<args>", "NULL object key");
404 goto out;
405 }
406
407 next_token(s);
408
409 if(token(s) == '?') {
410 opt = gotopt = 1;
411 next_token(s);
412 }
413
414 if(!root) {
415 /* skipping */
416 value = NULL;
417 }
418 else {
419 value = json_object_get(root, key);
420 if(!value && !opt) {
421 set_error(s, "<validation>", "Object item not found: %s", key);
422 goto out;
423 }
424 }
425
426 if(unpack(s, value, ap))
427 goto out;
428
429 hashtable_set(&key_set, key, 0, json_null());
430 next_token(s);
431 }
432
433 if(strict == 0 && (s->flags & JSON_STRICT))
434 strict = 1;
435
436 if(root && strict == 1) {
437 /* We need to check that all non optional items have been parsed */
438 const char *key;
439 json_t *value;
440 long unpacked = 0;
441 if (gotopt) {
442 /* We have optional keys, we need to iter on each key */
443 json_object_foreach(root, key, value) {
444 if(!hashtable_get(&key_set, key)) {
445 unpacked++;
446 }
447 }
448 } else {
449 /* No optional keys, we can just compare the number of items */
450 unpacked = (long)json_object_size(root) - (long)key_set.size;
451 }
452 if (unpacked) {
453 set_error(s, "<validation>", "%li object item(s) left unpacked", unpacked);
454 goto out;
455 }
456 }
457
458 ret = 0;
459
460 out:
461 hashtable_close(&key_set);
462 return ret;
463 }
464
465 static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
466 {
467 size_t i = 0;
468 int strict = 0;
469
470 if(root && !json_is_array(root)) {
471 set_error(s, "<validation>", "Expected array, got %s", type_name(root));
472 return -1;
473 }
474 next_token(s);
475
476 while(token(s) != ']') {
477 json_t *value;
478
479 if(strict != 0) {
480 set_error(s, "<format>", "Expected ']' after '%c', got '%c'",
481 (strict == 1 ? '!' : '*'),
482 token(s));
483 return -1;
484 }
485
486 if(!token(s)) {
487 set_error(s, "<format>", "Unexpected end of format string");
488 return -1;
489 }
490
491 if(token(s) == '!' || token(s) == '*') {
492 strict = (token(s) == '!' ? 1 : -1);
493 next_token(s);
494 continue;
495 }
496
497 if(!strchr(unpack_value_starters, token(s))) {
498 set_error(s, "<format>", "Unexpected format character '%c'",
499 token(s));
500 return -1;
501 }
502
503 if(!root) {
504 /* skipping */
505 value = NULL;
506 }
507 else {
508 value = json_array_get(root, i);
509 if(!value) {
510 set_error(s, "<validation>", "Array index %lu out of range",
511 (unsigned long)i);
512 return -1;
513 }
514 }
515
516 if(unpack(s, value, ap))
517 return -1;
518
519 next_token(s);
520 i++;
521 }
522
523 if(strict == 0 && (s->flags & JSON_STRICT))
524 strict = 1;
525
526 if(root && strict == 1 && i != json_array_size(root)) {
527 long diff = (long)json_array_size(root) - (long)i;
528 set_error(s, "<validation>", "%li array item(s) left unpacked", diff);
529 return -1;
530 }
531
532 return 0;
533 }
534
535 static int unpack(scanner_t *s, json_t *root, va_list *ap)
536 {
537 switch(token(s))
538 {
539 case '{':
540 return unpack_object(s, root, ap);
541
542 case '[':
543 return unpack_array(s, root, ap);
544
545 case 's':
546 if(root && !json_is_string(root)) {
547 set_error(s, "<validation>", "Expected string, got %s",
548 type_name(root));
549 return -1;
550 }
551
552 if(!(s->flags & JSON_VALIDATE_ONLY)) {
553 const char **str_target;
554 size_t *len_target = NULL;
555
556 str_target = va_arg(*ap, const char **);
557 if(!str_target) {
558 set_error(s, "<args>", "NULL string argument");
559 return -1;
560 }
561
562 next_token(s);
563
564 if(token(s) == '%') {
565 len_target = va_arg(*ap, size_t *);
566 if(!len_target) {
567 set_error(s, "<args>", "NULL string length argument");
568 return -1;
569 }
570 }
571 else
572 prev_token(s);
573
574 if(root) {
575 *str_target = json_string_value(root);
576 if(len_target)
577 *len_target = json_string_length(root);
578 }
579 }
580 return 0;
581
582 case 'i':
583 if(root && !json_is_integer(root)) {
584 set_error(s, "<validation>", "Expected integer, got %s",
585 type_name(root));
586 return -1;
587 }
588
589 if(!(s->flags & JSON_VALIDATE_ONLY)) {
590 int *target = va_arg(*ap, int*);
591 if(root)
592 *target = (int)json_integer_value(root);
593 }
594
595 return 0;
596
597 case 'I':
598 if(root && !json_is_integer(root)) {
599 set_error(s, "<validation>", "Expected integer, got %s",
600 type_name(root));
601 return -1;
602 }
603
604 if(!(s->flags & JSON_VALIDATE_ONLY)) {
605 json_int_t *target = va_arg(*ap, json_int_t*);
606 if(root)
607 *target = json_integer_value(root);
608 }
609
610 return 0;
611
612 case 'b':
613 if(root && !json_is_boolean(root)) {
614 set_error(s, "<validation>", "Expected true or false, got %s",
615 type_name(root));
616 return -1;
617 }
618
619 if(!(s->flags & JSON_VALIDATE_ONLY)) {
620 int *target = va_arg(*ap, int*);
621 if(root)
622 *target = json_is_true(root);
623 }
624
625 return 0;
626
627 case 'f':
628 if(root && !json_is_real(root)) {
629 set_error(s, "<validation>", "Expected real, got %s",
630 type_name(root));
631 return -1;
632 }
633
634 if(!(s->flags & JSON_VALIDATE_ONLY)) {
635 double *target = va_arg(*ap, double*);
636 if(root)
637 *target = json_real_value(root);
638 }
639
640 return 0;
641
642 case 'F':
643 if(root && !json_is_number(root)) {
644 set_error(s, "<validation>", "Expected real or integer, got %s",
645 type_name(root));
646 return -1;
647 }
648
649 if(!(s->flags & JSON_VALIDATE_ONLY)) {
650 double *target = va_arg(*ap, double*);
651 if(root)
652 *target = json_number_value(root);
653 }
654
655 return 0;
656
657 case 'O':
658 if(root && !(s->flags & JSON_VALIDATE_ONLY))
659 json_incref(root);
660 /* Fall through */
661
662 case 'o':
663 if(!(s->flags & JSON_VALIDATE_ONLY)) {
664 json_t **target = va_arg(*ap, json_t**);
665 if(root)
666 *target = root;
667 }
668
669 return 0;
670
671 case 'n':
672 /* Never assign, just validate */
673 if(root && !json_is_null(root)) {
674 set_error(s, "<validation>", "Expected null, got %s",
675 type_name(root));
676 return -1;
677 }
678 return 0;
679
680 default:
681 set_error(s, "<format>", "Unexpected format character '%c'",
682 token(s));
683 return -1;
684 }
685 }
686
687 json_t *json_vpack_ex(json_error_t *error, size_t flags,
688 const char *fmt, va_list ap)
689 {
690 scanner_t s;
691 va_list ap_copy;
692 json_t *value;
693
694 if(!fmt || !*fmt) {
695 jsonp_error_init(error, "<format>");
696 jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
697 return NULL;
698 }
699 jsonp_error_init(error, NULL);
700
701 scanner_init(&s, error, flags, fmt);
702 next_token(&s);
703
704 va_copy(ap_copy, ap);
705 value = pack(&s, &ap_copy);
706 va_end(ap_copy);
707
708 if(!value)
709 return NULL;
710
711 next_token(&s);
712 if(token(&s)) {
713 json_decref(value);
714 set_error(&s, "<format>", "Garbage after format string");
715 return NULL;
716 }
717
718 return value;
719 }
720
721 json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...)
722 {
723 json_t *value;
724 va_list ap;
725
726 va_start(ap, fmt);
727 value = json_vpack_ex(error, flags, fmt, ap);
728 va_end(ap);
729
730 return value;
731 }
732
733 json_t *json_pack(const char *fmt, ...)
734 {
735 json_t *value;
736 va_list ap;
737
738 va_start(ap, fmt);
739 value = json_vpack_ex(NULL, 0, fmt, ap);
740 va_end(ap);
741
742 return value;
743 }
744
745 int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
746 const char *fmt, va_list ap)
747 {
748 scanner_t s;
749 va_list ap_copy;
750
751 if(!root) {
752 jsonp_error_init(error, "<root>");
753 jsonp_error_set(error, -1, -1, 0, "NULL root value");
754 return -1;
755 }
756
757 if(!fmt || !*fmt) {
758 jsonp_error_init(error, "<format>");
759 jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
760 return -1;
761 }
762 jsonp_error_init(error, NULL);
763
764 scanner_init(&s, error, flags, fmt);
765 next_token(&s);
766
767 va_copy(ap_copy, ap);
768 if(unpack(&s, root, &ap_copy)) {
769 va_end(ap_copy);
770 return -1;
771 }
772 va_end(ap_copy);
773
774 next_token(&s);
775 if(token(&s)) {
776 set_error(&s, "<format>", "Garbage after format string");
777 return -1;
778 }
779
780 return 0;
781 }
782
783 int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...)
784 {
785 int ret;
786 va_list ap;
787
788 va_start(ap, fmt);
789 ret = json_vunpack_ex(root, error, flags, fmt, ap);
790 va_end(ap);
791
792 return ret;
793 }
794
795 int json_unpack(json_t *root, const char *fmt, ...)
796 {
797 int ret;
798 va_list ap;
799
800 va_start(ap, fmt);
801 ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
802 va_end(ap);
803
804 return ret;
805 }