2 Copyright (C) 2016, 2017, 2018 "IoT.bzh"
4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
22 #include "wrap-json.h"
29 wrap_json_error_null_object,
30 wrap_json_error_truncated,
31 wrap_json_error_internal_error,
32 wrap_json_error_out_of_memory,
33 wrap_json_error_invalid_character,
34 wrap_json_error_too_long,
35 wrap_json_error_too_deep,
36 wrap_json_error_null_spec,
37 wrap_json_error_null_key,
38 wrap_json_error_null_string,
39 wrap_json_error_out_of_range,
40 wrap_json_error_incomplete,
41 wrap_json_error_missfit_type,
42 wrap_json_error_key_not_found,
43 wrap_json_error_bad_base64,
44 _wrap_json_error_count_
47 static const char ignore_all[] = " \t\n\r,:";
48 static const char pack_accept_arr[] = "][{snbiIfoOyY";
49 static const char pack_accept_key[] = "s}";
50 #define pack_accept_any (&pack_accept_arr[1])
52 static const char unpack_accept_arr[] = "*!][{snbiIfFoOyY";
53 static const char unpack_accept_key[] = "*!s}";
54 #define unpack_accept_any (&unpack_accept_arr[3])
56 static const char *pack_errors[_wrap_json_error_count_] =
58 [wrap_json_error_none] = "unknown error",
59 [wrap_json_error_null_object] = "null object",
60 [wrap_json_error_truncated] = "truncated",
61 [wrap_json_error_internal_error] = "internal error",
62 [wrap_json_error_out_of_memory] = "out of memory",
63 [wrap_json_error_invalid_character] = "invalid character",
64 [wrap_json_error_too_long] = "too long",
65 [wrap_json_error_too_deep] = "too deep",
66 [wrap_json_error_null_spec] = "spec is NULL",
67 [wrap_json_error_null_key] = "key is NULL",
68 [wrap_json_error_null_string] = "string is NULL",
69 [wrap_json_error_out_of_range] = "array too small",
70 [wrap_json_error_incomplete] = "incomplete container",
71 [wrap_json_error_missfit_type] = "missfit of type",
72 [wrap_json_error_key_not_found] = "key not found",
73 [wrap_json_error_bad_base64] = "bad base64 encoding"
76 int wrap_json_get_error_position(int rc)
83 int wrap_json_get_error_code(int rc)
90 const char *wrap_json_get_error_string(int rc)
92 rc = wrap_json_get_error_code(rc);
93 if (rc >= (int)(sizeof pack_errors / sizeof *pack_errors))
95 return pack_errors[rc];
98 static int encode_base64(
109 size_t in, out, rlen, n3, r3, iout, nout;
113 /* compute unformatted output length */
116 nout = 4 * n3 + r3 + !!r3;
118 /* deduce formatted output length */
121 rlen += ((~rlen) + 1) & 3;
123 rlen += rlen / width;
125 /* allocate the output */
126 result = malloc(rlen + 1);
128 return wrap_json_error_out_of_memory;
130 /* compute the formatted output */
132 for (in = out = iout = 0 ; iout < nout ; iout++) {
133 /* get in 'u8' the 6 bits value to add */
136 u16 = (uint16_t)data[in++];
137 u8 = (uint8_t)(u16 >> 2);
140 u16 = (uint16_t)(u16 << 8);
142 u16 = (uint16_t)(u16 | data[in++]);
143 u8 = (uint8_t)(u16 >> 4);
146 u16 = (uint16_t)(u16 << 8);
148 u16 = (uint16_t)(u16 | data[in++]);
149 u8 = (uint8_t)(u16 >> 6);
157 /* encode 'u8' to the char 'c' */
160 c = (char)('A' + u8);
162 c = (char)('a' + u8 - 26);
165 c = (char)('0' + u8 - 52);
172 /* put to output with format */
175 result[out++] = '\n';
184 result[out++] = '\n';
196 static int decode_base64(
208 /* allocate enougth output */
209 result = malloc(datalen);
211 return wrap_json_error_out_of_memory;
213 /* decode the input */
214 for (iin = in = out = 0 ; in < datalen ; in++) {
216 if (c != '\n' && c != '\r' && c != '=') {
217 if ('A' <= c && c <= 'Z')
218 u8 = (uint8_t)(c - 'A');
219 else if ('a' <= c && c <= 'z')
220 u8 = (uint8_t)(c - 'a' + 26);
221 else if ('0' <= c && c <= '9')
222 u8 = (uint8_t)(c - '0' + 52);
223 else if (c == '+' || c == '-')
225 else if (c == '/' || c == '_')
229 return wrap_json_error_bad_base64;
235 u16 = (uint16_t)((u16 << 6) | u8);
237 u8 = (uint8_t)(u16 >> iin);
244 *decoded = realloc(result, out);
245 if (out && *decoded == NULL) {
247 return wrap_json_error_out_of_memory;
253 static inline const char *skip(const char *d)
255 while (*d && strchr(ignore_all, *d))
260 int wrap_json_vpack(struct json_object **result, const char *desc, va_list args)
262 /* TODO: the case of structs with key being single char should be optimized */
263 int nstr, notnull, nullable, rc;
269 struct { const uint8_t *in; size_t insz; char *out; size_t outsz; } bytes;
270 struct { const char *str; size_t sz; } strs[STRCOUNT];
271 struct { struct json_object *cont, *key; const char *acc; char type; } stack[STACKCOUNT], *top;
272 struct json_object *obj;
279 top->acc = pack_accept_any;
289 if (!strchr(top->acc, c))
290 goto invalid_character;
299 strs[nstr].str = va_arg(args, const char*);
307 case '%': strs[nstr].sz = va_arg(args, size_t); d = skip(++d); break;
308 case '#': strs[nstr].sz = (size_t)va_arg(args, int); d = skip(++d); break;
309 default: strs[nstr].sz = strs[nstr].str ? strlen(strs[nstr].str) : 0; break;
311 sz += strs[nstr++].sz;
318 if (nstr >= STRCOUNT)
334 dsz -= strs[nstr].sz;
335 memcpy(&s[dsz], strs[nstr].str, strs[nstr].sz);
337 obj = json_object_new_string_len(s, (int)sz);
349 obj = json_object_new_boolean(va_arg(args, int));
354 obj = json_object_new_int(va_arg(args, int));
359 obj = json_object_new_int64(va_arg(args, int64_t));
364 obj = json_object_new_double(va_arg(args, double));
370 obj = va_arg(args, struct json_object*);
373 else if (*d != '*' && !obj)
376 json_object_get(obj);
380 bytes.in = va_arg(args, const uint8_t*);
381 bytes.insz = va_arg(args, size_t);
382 if (bytes.in == NULL || bytes.insz == 0)
385 rc = encode_base64(bytes.in, bytes.insz,
386 &bytes.out, &bytes.outsz, 0, 0, c == 'y');
389 obj = json_object_new_string_len(bytes.out, (int)bytes.outsz);
396 else if (*d != '*' && !obj) {
397 obj = json_object_new_string_len(d, 0);
404 if (++top >= &stack[STACKCOUNT])
409 top->acc = pack_accept_arr;
410 top->cont = json_object_new_array();
413 top->acc = pack_accept_key;
414 top->cont = json_object_new_object();
421 if (c != top->type || top <= stack)
424 if (*d == '*' && !(c == '}' ? json_object_object_length(obj) : json_object_array_length(obj))) {
425 json_object_put(obj);
437 goto invalid_character;
441 if (obj || *d != '*')
442 json_object_array_add(top->cont, obj);
450 top->acc = pack_accept_any;
454 if (obj || *d != '*')
455 json_object_object_add(top->cont, json_object_get_string(top->key), obj);
458 json_object_put(top->key);
460 top->acc = pack_accept_key;
469 rc = wrap_json_error_null_object;
472 rc = wrap_json_error_truncated;
475 rc = wrap_json_error_internal_error;
478 rc = wrap_json_error_out_of_memory;
481 rc = wrap_json_error_invalid_character;
484 rc = wrap_json_error_too_long;
487 rc = wrap_json_error_too_deep;
490 rc = wrap_json_error_null_spec;
493 rc = wrap_json_error_null_key;
496 rc = wrap_json_error_null_string;
500 json_object_put(top->key);
501 json_object_put(top->cont);
502 } while (--top >= stack);
504 rc = rc | (int)((d - desc) << 4);
508 int wrap_json_pack(struct json_object **result, const char *desc, ...)
513 va_start(args, desc);
514 rc = wrap_json_vpack(result, desc, args);
519 static int vunpack(struct json_object *object, const char *desc, va_list args, int store)
521 int rc = 0, optionnal, ignore;
522 char c, xacc[2] = { 0, 0 };
524 const char *d, *fit = NULL;
525 const char *key = NULL;
526 const char **ps = NULL;
532 struct { struct json_object *parent; const char *acc; int index; int count; char type; } stack[STACKCOUNT], *top;
533 struct json_object *obj;
534 struct json_object **po;
539 acc = unpack_accept_any;
551 goto invalid_character;
555 if (xacc[0] == '}') {
557 key = va_arg(args, const char *);
569 if (json_object_object_get_ex(top->parent, key, &obj)) {
581 acc = unpack_accept_any;
586 ps = va_arg(args, const char **);
588 if (!json_object_is_type(obj, json_type_string))
591 *ps = json_object_get_string(obj);
596 pz = va_arg(args, size_t *);
598 *pz = (size_t)json_object_get_string_len(obj);
603 if (!ignore && !json_object_is_type(obj, json_type_null))
608 pi = va_arg(args, int *);
611 if (!json_object_is_type(obj, json_type_boolean))
614 *pi = json_object_get_boolean(obj);
619 pi = va_arg(args, int *);
622 if (!json_object_is_type(obj, json_type_int))
625 *pi = json_object_get_int(obj);
630 pI = va_arg(args, int64_t *);
633 if (!json_object_is_type(obj, json_type_int))
636 *pI = json_object_get_int64(obj);
642 pf = va_arg(args, double *);
645 if (!(json_object_is_type(obj, json_type_double) || (c == 'F' && json_object_is_type(obj, json_type_int))))
648 *pf = json_object_get_double(obj);
654 po = va_arg(args, struct json_object **);
657 obj = json_object_get(obj);
665 py = va_arg(args, uint8_t **);
666 pz = va_arg(args, size_t *);
670 if (store && py && pz) {
675 if (!json_object_is_type(obj, json_type_string))
677 if (store && py && pz) {
679 json_object_get_string(obj),
680 (size_t)json_object_get_string_len(obj),
693 else if (++top >= &stack[STACKCOUNT])
704 if (!json_object_is_type(obj, json_type_array))
706 top->count = (int)json_object_array_length(obj);
709 acc = unpack_accept_arr;
712 if (!json_object_is_type(obj, json_type_object))
714 top->count = json_object_object_length(obj);
717 acc = unpack_accept_key;
723 if (!top || c != xacc[0])
727 top = top == stack ? NULL : top - 1;
733 goto invalid_character;
734 if (!ignore && top->index != top->count)
748 goto invalid_character;
752 key = strchr(unpack_accept_arr, *d);
753 if (key && key >= unpack_accept_any) {
754 if (top->index >= top->count)
756 obj = json_object_array_get_idx(top->parent, top->index++);
761 acc = unpack_accept_key;
771 rc = wrap_json_error_truncated;
774 rc = wrap_json_error_internal_error;
777 rc = wrap_json_error_invalid_character;
780 rc = wrap_json_error_too_deep;
783 rc = wrap_json_error_null_spec;
786 rc = wrap_json_error_null_key;
789 rc = wrap_json_error_out_of_range;
792 rc = wrap_json_error_incomplete;
795 rc = wrap_json_error_missfit_type;
798 rc = wrap_json_error_key_not_found;
803 rc = rc | (int)((d - desc) << 4);
807 int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
809 return vunpack(object, desc, args, 0);
812 int wrap_json_check(struct json_object *object, const char *desc, ...)
817 va_start(args, desc);
818 rc = vunpack(object, desc, args, 0);
823 int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
825 return !vunpack(object, desc, args, 0);
828 int wrap_json_match(struct json_object *object, const char *desc, ...)
833 va_start(args, desc);
834 rc = vunpack(object, desc, args, 0);
839 int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
841 return vunpack(object, desc, args, 1);
844 int wrap_json_unpack(struct json_object *object, const char *desc, ...)
849 va_start(args, desc);
850 rc = vunpack(object, desc, args, 1);
855 static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
857 struct json_object_iterator it = json_object_iter_begin(object);
858 struct json_object_iterator end = json_object_iter_end(object);
859 while (!json_object_iter_equal(&it, &end)) {
860 callback(closure, json_object_iter_peek_value(&it), json_object_iter_peek_name(&it));
861 json_object_iter_next(&it);
865 static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
867 int n = (int)json_object_array_length(object);
870 callback(closure, json_object_array_get_idx(object, i++));
873 void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
875 if (json_object_is_type(object, json_type_array))
876 array_for_all(object, callback, closure);
878 callback(closure, object);
881 void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
883 if (json_object_is_type(object, json_type_array))
884 array_for_all(object, callback, closure);
887 void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
889 if (json_object_is_type(object, json_type_object))
890 object_for_all(object, callback, closure);
893 void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
895 if (json_object_is_type(object, json_type_object))
896 object_for_all(object, callback, closure);
898 callback(closure, object, NULL);
901 void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
905 else if (json_object_is_type(object, json_type_object))
906 object_for_all(object, callback, closure);
907 else if (!json_object_is_type(object, json_type_array))
908 callback(closure, object, NULL);
910 int n = (int)json_object_array_length(object);
913 callback(closure, json_object_array_get_idx(object, i++), NULL);
917 static struct json_object *clone_any(struct json_object *object, int deep);
919 static struct json_object *clone_object(struct json_object *object, int subdeep)
921 struct json_object *r = json_object_new_object();
922 struct json_object_iterator it = json_object_iter_begin(object);
923 struct json_object_iterator end = json_object_iter_end(object);
924 while (!json_object_iter_equal(&it, &end)) {
925 json_object_object_add(r,
926 json_object_iter_peek_name(&it),
927 clone_any(json_object_iter_peek_value(&it), subdeep));
928 json_object_iter_next(&it);
933 static struct json_object *clone_array(struct json_object *object, int subdeep)
935 int n = json_object_array_length(object);
936 struct json_object *r = json_object_new_array();
939 json_object_array_put_idx(r, n,
940 clone_any(json_object_array_get_idx(object, n), subdeep));
945 static struct json_object *clone_any(struct json_object *object, int deep)
948 switch (json_object_get_type(object)) {
949 case json_type_object:
950 return clone_object(object, deep - 1);
951 case json_type_array:
952 return clone_array(object, deep - 1);
957 return json_object_get(object);
960 struct json_object *wrap_json_clone(struct json_object *object)
962 return clone_any(object, 1);
965 struct json_object *wrap_json_clone_deep(struct json_object *object)
967 return clone_any(object, INT_MAX);
970 void wrap_json_object_add(struct json_object *dest, struct json_object *added)
972 struct json_object_iterator it, end;
973 if (json_object_is_type(dest, json_type_object) && json_object_is_type(added, json_type_object)) {
974 it = json_object_iter_begin(added);
975 end = json_object_iter_end(added);
976 while (!json_object_iter_equal(&it, &end)) {
977 json_object_object_add(dest,
978 json_object_iter_peek_name(&it),
979 json_object_get(json_object_iter_peek_value(&it)));
980 json_object_iter_next(&it);
985 #if defined(WRAP_JSON_TEST)
988 void tclone(struct json_object *obj)
990 struct json_object *o;
992 o = wrap_json_clone(obj);
993 if (strcmp(json_object_to_json_string(obj), json_object_to_json_string(o)))
994 printf("ERROR in clone: %s VERSUS %s\n", json_object_to_json_string(obj), json_object_to_json_string(o));
997 o = wrap_json_clone_deep(obj);
998 if (strcmp(json_object_to_json_string(obj), json_object_to_json_string(o)))
999 printf("ERROR in clone_deep: %s VERSUS %s\n", json_object_to_json_string(obj), json_object_to_json_string(o));
1003 void p(const char *desc, ...)
1007 struct json_object *result;
1009 va_start(args, desc);
1010 rc = wrap_json_vpack(&result, desc, args);
1013 printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
1015 printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
1017 json_object_put(result);
1024 struct json_object *xo[10];
1028 void u(const char *value, const char *desc, ...)
1033 struct json_object *obj, *o;
1035 memset(xs, 0, sizeof xs);
1036 memset(xi, 0, sizeof xi);
1037 memset(xI, 0, sizeof xI);
1038 memset(xf, 0, sizeof xf);
1039 memset(xo, 0, sizeof xo);
1040 memset(xy, 0, sizeof xy);
1041 memset(xz, 0, sizeof xz);
1042 obj = json_tokener_parse(value);
1043 va_start(args, desc);
1044 rc = wrap_json_vunpack(obj, desc, args);
1047 printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
1051 va_start(args, desc);
1055 case '{': m = (m << 1) | 1; k = 1; break;
1056 case '}': m = m >> 1; k = m&1; break;
1057 case '[': m = m << 1; k = 0; break;
1058 case ']': m = m >> 1; k = m&1; break;
1059 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
1060 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
1061 case 'n': printf(" n"); k = m&1; break;
1062 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
1063 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
1064 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
1065 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
1066 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
1067 case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
1068 case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", json_object_to_json_string(o)); json_object_put(o); k = m&1; break;
1071 uint8_t *p = *va_arg(args, uint8_t**);
1072 size_t s = *va_arg(args, size_t*);
1073 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
1085 json_object_put(obj);
1088 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
1089 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
1093 char buffer[4] = {'t', 'e', 's', 't'};
1099 P("I", (uint64_t)0x123456789abcdef);
1104 P("s#", "test asdf", 4);
1105 P("s%", "test asdf", (size_t)4);
1107 P("s%", buffer, (size_t)4);
1108 P("s++", "te", "st", "ing");
1109 P("s#+#+", "test", 1, "test", 2, "test");
1110 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
1113 P("o", json_object_new_int(1));
1114 P("o?", json_object_new_int(1));
1116 P("O", json_object_new_int(1));
1117 P("O?", json_object_new_int(1));
1120 P("{s+#+: []}", "foo", "barbar", 3, "baz");
1121 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
1122 P("{s:**}", "a", NULL);
1123 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
1124 P("[i,i,i]", 0, 1, 2);
1125 P("[s,o,O]", NULL, NULL, NULL);
1127 P("[s*,o*,O*]", NULL, NULL, NULL);
1130 P("[ i , i, i ] ", 1, 2, 3);
1141 P("{s:i}", NULL, 1);
1142 P("{ {}: s }", "foo");
1143 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
1144 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
1145 P("y", "???????hello>>>>>>>", (size_t)19);
1146 P("Y", "???????hello>>>>>>>", (size_t)19);
1147 P("{sy?}", "foo", "hi", (size_t)2);
1148 P("{sy?}", "foo", NULL, 0);
1149 P("{sy*}", "foo", "hi", (size_t)2);
1150 P("{sy*}", "foo", NULL, 0);
1152 U("true", "b", &xi[0]);
1153 U("false", "b", &xi[0]);
1155 U("42", "i", &xi[0]);
1156 U("123456789", "I", &xI[0]);
1157 U("3.14", "f", &xf[0]);
1158 U("12345", "F", &xf[0]);
1159 U("3.14", "F", &xf[0]);
1160 U("\"foo\"", "s", &xs[0]);
1161 U("\"foo\"", "s%", &xs[0], &xz[0]);
1164 U("{}", "o", &xo[0]);
1165 U("{}", "O", &xo[0]);
1166 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
1167 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
1168 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
1175 U("[42]", "[i]a", &xi[0]);
1176 U("42", "ia", &xi[0]);
1178 U("\"foo\"", "s", NULL);
1183 U("42", "[i]", NULL);
1184 U("42", "{si}", "foo", NULL);
1186 U("\"foo\"", "b", NULL);
1187 U("\"foo\"", "i", NULL);
1188 U("\"foo\"", "I", NULL);
1189 U("\"foo\"", "f", NULL);
1190 U("\"foo\"", "F", NULL);
1191 U("true", "s", NULL);
1193 U("true", "i", NULL);
1194 U("true", "I", NULL);
1195 U("true", "f", NULL);
1196 U("true", "F", NULL);
1197 U("[42]", "[ii]", &xi[0], &xi[1]);
1198 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
1199 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
1200 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
1201 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
1202 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
1203 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
1204 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
1205 U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
1206 U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
1207 U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
1208 U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
1209 U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
1210 U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
1211 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
1212 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
1213 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
1214 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
1215 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
1216 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
1217 U("{}", "{s?i}", "foo", &xi[0]);
1218 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
1219 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1220 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1221 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1222 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1223 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1224 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1225 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1226 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1228 U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
1229 U("\"\"", "y", &xy[0], &xz[0]);
1230 U("null", "y", &xy[0], &xz[0]);
1231 U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1232 U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1233 U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
1242 /* Unpack the same item twice */
1243 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
1244 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
1245 fail("json_unpack object with strict validation failed");
1247 const char *possible_errors[] = {
1248 "2 object item(s) left unpacked: baz, quux",
1249 "2 object item(s) left unpacked: quux, baz"
1251 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);