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.
21 #include "wrap-json.h"
28 wrap_json_error_null_object,
29 wrap_json_error_truncated,
30 wrap_json_error_internal_error,
31 wrap_json_error_out_of_memory,
32 wrap_json_error_invalid_character,
33 wrap_json_error_too_long,
34 wrap_json_error_too_deep,
35 wrap_json_error_null_spec,
36 wrap_json_error_null_key,
37 wrap_json_error_null_string,
38 wrap_json_error_out_of_range,
39 wrap_json_error_incomplete,
40 wrap_json_error_missfit_type,
41 wrap_json_error_key_not_found,
42 wrap_json_error_bad_base64,
43 _wrap_json_error_count_
46 static const char ignore_all[] = " \t\n\r,:";
47 static const char pack_accept_arr[] = "][{snbiIfoOyY";
48 static const char pack_accept_key[] = "s}";
49 #define pack_accept_any (&pack_accept_arr[1])
51 static const char unpack_accept_arr[] = "*!][{snbiIfFoOyY";
52 static const char unpack_accept_key[] = "*!s}";
53 #define unpack_accept_any (&unpack_accept_arr[3])
55 static const char *pack_errors[_wrap_json_error_count_] =
57 [wrap_json_error_none] = "unknown error",
58 [wrap_json_error_null_object] = "null object",
59 [wrap_json_error_truncated] = "truncated",
60 [wrap_json_error_internal_error] = "internal error",
61 [wrap_json_error_out_of_memory] = "out of memory",
62 [wrap_json_error_invalid_character] = "invalid character",
63 [wrap_json_error_too_long] = "too long",
64 [wrap_json_error_too_deep] = "too deep",
65 [wrap_json_error_null_spec] = "spec is NULL",
66 [wrap_json_error_null_key] = "key is NULL",
67 [wrap_json_error_null_string] = "string is NULL",
68 [wrap_json_error_out_of_range] = "array too small",
69 [wrap_json_error_incomplete] = "incomplete container",
70 [wrap_json_error_missfit_type] = "missfit of type",
71 [wrap_json_error_key_not_found] = "key not found",
72 [wrap_json_error_bad_base64] = "bad base64 encoding"
75 int wrap_json_get_error_position(int rc)
82 int wrap_json_get_error_code(int rc)
89 const char *wrap_json_get_error_string(int rc)
91 rc = wrap_json_get_error_code(rc);
92 if (rc >= (int)(sizeof pack_errors / sizeof *pack_errors))
94 return pack_errors[rc];
97 static int encode_base64(
108 size_t in, out, rlen, n3, r3, iout, nout;
112 /* compute unformatted output length */
115 nout = 4 * n3 + r3 + !!r3;
117 /* deduce formatted output length */
120 rlen += ((~rlen) + 1) & 3;
122 rlen += rlen / width;
124 /* allocate the output */
125 result = malloc(rlen + 1);
127 return wrap_json_error_out_of_memory;
129 /* compute the formatted output */
131 for (in = out = iout = 0 ; iout < nout ; iout++) {
132 /* get in 'u8' the 6 bits value to add */
135 u16 = (uint16_t)data[in++];
136 u8 = (uint8_t)(u16 >> 2);
139 u16 = (uint16_t)(u16 << 8);
141 u16 = (uint16_t)(u16 | data[in++]);
142 u8 = (uint8_t)(u16 >> 4);
145 u16 = (uint16_t)(u16 << 8);
147 u16 = (uint16_t)(u16 | data[in++]);
148 u8 = (uint8_t)(u16 >> 6);
156 /* encode 'u8' to the char 'c' */
159 c = (char)('A' + u8);
161 c = (char)('a' + u8 - 26);
164 c = (char)('0' + u8 - 52);
171 /* put to output with format */
174 result[out++] = '\n';
183 result[out++] = '\n';
195 static int decode_base64(
207 /* allocate enougth output */
208 result = malloc(datalen);
210 return wrap_json_error_out_of_memory;
212 /* decode the input */
213 for (iin = in = out = 0 ; in < datalen ; in++) {
215 if (c != '\n' && c != '\r' && c != '=') {
216 if ('A' <= c && c <= 'Z')
217 u8 = (uint8_t)(c - 'A');
218 else if ('a' <= c && c <= 'z')
219 u8 = (uint8_t)(c - 'a' + 26);
220 else if ('0' <= c && c <= '9')
221 u8 = (uint8_t)(c - '0' + 52);
222 else if (c == '+' || c == '-')
224 else if (c == '/' || c == '_')
228 return wrap_json_error_bad_base64;
234 u16 = (uint16_t)((u16 << 6) | u8);
236 u8 = (uint8_t)(u16 >> iin);
243 *decoded = realloc(result, out);
244 if (out && *decoded == NULL) {
246 return wrap_json_error_out_of_memory;
252 static inline const char *skip(const char *d)
254 while (*d && strchr(ignore_all, *d))
259 int wrap_json_vpack(struct json_object **result, const char *desc, va_list args)
261 /* TODO: the case of structs with key being single char should be optimized */
262 int nstr, notnull, nullable, rc;
268 struct { const uint8_t *in; size_t insz; char *out; size_t outsz; } bytes;
269 struct { const char *str; size_t sz; } strs[STRCOUNT];
270 struct { struct json_object *cont, *key; const char *acc; char type; } stack[STACKCOUNT], *top;
271 struct json_object *obj;
278 top->acc = pack_accept_any;
288 if (!strchr(top->acc, c))
289 goto invalid_character;
298 strs[nstr].str = va_arg(args, const char*);
306 case '%': strs[nstr].sz = va_arg(args, size_t); d = skip(++d); break;
307 case '#': strs[nstr].sz = (size_t)va_arg(args, int); d = skip(++d); break;
308 default: strs[nstr].sz = strs[nstr].str ? strlen(strs[nstr].str) : 0; break;
310 sz += strs[nstr++].sz;
317 if (nstr >= STRCOUNT)
333 dsz -= strs[nstr].sz;
334 memcpy(&s[dsz], strs[nstr].str, strs[nstr].sz);
336 obj = json_object_new_string_len(s, (int)sz);
348 obj = json_object_new_boolean(va_arg(args, int));
353 obj = json_object_new_int(va_arg(args, int));
358 obj = json_object_new_int64(va_arg(args, int64_t));
363 obj = json_object_new_double(va_arg(args, double));
369 obj = va_arg(args, struct json_object*);
372 else if (*d != '*' && !obj)
375 json_object_get(obj);
379 bytes.in = va_arg(args, const uint8_t*);
380 bytes.insz = va_arg(args, size_t);
381 if (bytes.in == NULL || bytes.insz == 0)
384 rc = encode_base64(bytes.in, bytes.insz,
385 &bytes.out, &bytes.outsz, 0, 0, c == 'y');
388 obj = json_object_new_string_len(bytes.out, (int)bytes.outsz);
395 else if (*d != '*' && !obj) {
396 obj = json_object_new_string_len(d, 0);
403 if (++top >= &stack[STACKCOUNT])
408 top->acc = pack_accept_arr;
409 top->cont = json_object_new_array();
412 top->acc = pack_accept_key;
413 top->cont = json_object_new_object();
420 if (c != top->type || top <= stack)
423 if (*d == '*' && !(c == '}' ? json_object_object_length(obj) : json_object_array_length(obj))) {
424 json_object_put(obj);
436 goto invalid_character;
440 if (obj || *d != '*')
441 json_object_array_add(top->cont, obj);
449 top->acc = pack_accept_any;
453 if (obj || *d != '*')
454 json_object_object_add(top->cont, json_object_get_string(top->key), obj);
457 json_object_put(top->key);
459 top->acc = pack_accept_key;
468 rc = wrap_json_error_null_object;
471 rc = wrap_json_error_truncated;
474 rc = wrap_json_error_internal_error;
477 rc = wrap_json_error_out_of_memory;
480 rc = wrap_json_error_invalid_character;
483 rc = wrap_json_error_too_long;
486 rc = wrap_json_error_too_deep;
489 rc = wrap_json_error_null_spec;
492 rc = wrap_json_error_null_key;
495 rc = wrap_json_error_null_string;
499 json_object_put(top->key);
500 json_object_put(top->cont);
501 } while (--top >= stack);
503 rc = rc | (int)((d - desc) << 4);
507 int wrap_json_pack(struct json_object **result, const char *desc, ...)
512 va_start(args, desc);
513 rc = wrap_json_vpack(result, desc, args);
518 static int vunpack(struct json_object *object, const char *desc, va_list args, int store)
520 int rc = 0, optionnal, ignore;
521 char c, xacc[2] = { 0, 0 };
523 const char *d, *fit = NULL;
524 const char *key = NULL;
525 const char **ps = NULL;
531 struct { struct json_object *parent; const char *acc; size_t index; size_t count; char type; } stack[STACKCOUNT], *top;
532 struct json_object *obj;
533 struct json_object **po;
538 acc = unpack_accept_any;
550 goto invalid_character;
554 if (xacc[0] == '}') {
556 key = va_arg(args, const char *);
568 if (json_object_object_get_ex(top->parent, key, &obj)) {
580 acc = unpack_accept_any;
585 ps = va_arg(args, const char **);
587 if (!json_object_is_type(obj, json_type_string))
590 *ps = json_object_get_string(obj);
595 pz = va_arg(args, size_t *);
597 *pz = (size_t)json_object_get_string_len(obj);
602 if (!ignore && !json_object_is_type(obj, json_type_null))
607 pi = va_arg(args, int *);
610 if (!json_object_is_type(obj, json_type_boolean))
613 *pi = json_object_get_boolean(obj);
618 pi = va_arg(args, int *);
621 if (!json_object_is_type(obj, json_type_int))
624 *pi = json_object_get_int(obj);
629 pI = va_arg(args, int64_t *);
632 if (!json_object_is_type(obj, json_type_int))
635 *pI = json_object_get_int64(obj);
641 pf = va_arg(args, double *);
644 if (!(json_object_is_type(obj, json_type_double) || (c == 'F' && json_object_is_type(obj, json_type_int))))
647 *pf = json_object_get_double(obj);
653 po = va_arg(args, struct json_object **);
656 obj = json_object_get(obj);
664 py = va_arg(args, uint8_t **);
665 pz = va_arg(args, size_t *);
669 if (store && py && pz) {
674 if (!json_object_is_type(obj, json_type_string))
676 if (store && py && pz) {
678 json_object_get_string(obj),
679 (size_t)json_object_get_string_len(obj),
692 else if (++top >= &stack[STACKCOUNT])
703 if (!json_object_is_type(obj, json_type_array))
705 top->count = json_object_array_length(obj);
708 acc = unpack_accept_arr;
711 if (!json_object_is_type(obj, json_type_object))
713 top->count = json_object_object_length(obj);
716 acc = unpack_accept_key;
722 if (!top || c != xacc[0])
726 top = top == stack ? NULL : top - 1;
732 goto invalid_character;
733 if (!ignore && top->index != top->count)
747 goto invalid_character;
751 key = strchr(unpack_accept_arr, *d);
752 if (key && key >= unpack_accept_any) {
753 if (top->index >= top->count)
755 obj = json_object_array_get_idx(top->parent, (int)top->index++);
760 acc = unpack_accept_key;
770 rc = wrap_json_error_truncated;
773 rc = wrap_json_error_internal_error;
776 rc = wrap_json_error_invalid_character;
779 rc = wrap_json_error_too_deep;
782 rc = wrap_json_error_null_spec;
785 rc = wrap_json_error_null_key;
788 rc = wrap_json_error_out_of_range;
791 rc = wrap_json_error_incomplete;
794 rc = wrap_json_error_missfit_type;
797 rc = wrap_json_error_key_not_found;
802 rc = rc | (int)((d - desc) << 4);
806 int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
808 return vunpack(object, desc, args, 0);
811 int wrap_json_check(struct json_object *object, const char *desc, ...)
816 va_start(args, desc);
817 rc = vunpack(object, desc, args, 0);
822 int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
824 return !vunpack(object, desc, args, 0);
827 int wrap_json_match(struct json_object *object, const char *desc, ...)
832 va_start(args, desc);
833 rc = vunpack(object, desc, args, 0);
838 int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
840 return vunpack(object, desc, args, 1);
843 int wrap_json_unpack(struct json_object *object, const char *desc, ...)
848 va_start(args, desc);
849 rc = vunpack(object, desc, args, 1);
854 static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
856 struct json_object_iterator it = json_object_iter_begin(object);
857 struct json_object_iterator end = json_object_iter_end(object);
858 while (!json_object_iter_equal(&it, &end)) {
859 callback(closure, json_object_iter_peek_value(&it), json_object_iter_peek_name(&it));
860 json_object_iter_next(&it);
864 static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
866 size_t n = json_object_array_length(object);
869 callback(closure, json_object_array_get_idx(object, (int)i++));
872 void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
874 if (json_object_is_type(object, json_type_array))
875 array_for_all(object, callback, closure);
877 callback(closure, object);
880 void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
882 if (json_object_is_type(object, json_type_array))
883 array_for_all(object, callback, closure);
886 void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
888 if (json_object_is_type(object, json_type_object))
889 object_for_all(object, callback, closure);
892 void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
894 if (json_object_is_type(object, json_type_object))
895 object_for_all(object, callback, closure);
897 callback(closure, object, NULL);
900 void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
904 else if (json_object_is_type(object, json_type_object))
905 object_for_all(object, callback, closure);
906 else if (!json_object_is_type(object, json_type_array))
907 callback(closure, object, NULL);
909 size_t n = json_object_array_length(object);
912 callback(closure, json_object_array_get_idx(object, (int)i++), NULL);
916 #if defined(WRAP_JSON_TEST)
919 void p(const char *desc, ...)
923 struct json_object *result;
925 va_start(args, desc);
926 rc = wrap_json_vpack(&result, desc, args);
929 printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
931 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));
932 json_object_put(result);
939 struct json_object *xo[10];
943 void u(const char *value, const char *desc, ...)
948 struct json_object *obj, *o;
950 memset(xs, 0, sizeof xs);
951 memset(xi, 0, sizeof xi);
952 memset(xI, 0, sizeof xI);
953 memset(xf, 0, sizeof xf);
954 memset(xo, 0, sizeof xo);
955 memset(xy, 0, sizeof xy);
956 memset(xz, 0, sizeof xz);
957 obj = json_tokener_parse(value);
958 va_start(args, desc);
959 rc = wrap_json_vunpack(obj, desc, args);
962 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));
966 va_start(args, desc);
970 case '{': m = (m << 1) | 1; k = 1; break;
971 case '}': m = m >> 1; k = m&1; break;
972 case '[': m = m << 1; k = 0; break;
973 case ']': m = m >> 1; k = m&1; break;
974 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
975 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
976 case 'n': printf(" n"); k = m&1; break;
977 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
978 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
979 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
980 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
981 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
982 case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
983 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;
986 uint8_t *p = *va_arg(args, uint8_t**);
987 size_t s = *va_arg(args, size_t*);
988 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
999 json_object_put(obj);
1002 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
1003 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
1007 char buffer[4] = {'t', 'e', 's', 't'};
1013 P("I", (uint64_t)0x123456789abcdef);
1018 P("s#", "test asdf", 4);
1019 P("s%", "test asdf", (size_t)4);
1021 P("s%", buffer, (size_t)4);
1022 P("s++", "te", "st", "ing");
1023 P("s#+#+", "test", 1, "test", 2, "test");
1024 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
1027 P("o", json_object_new_int(1));
1028 P("o?", json_object_new_int(1));
1030 P("O", json_object_new_int(1));
1031 P("O?", json_object_new_int(1));
1034 P("{s+#+: []}", "foo", "barbar", 3, "baz");
1035 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
1036 P("{s:**}", "a", NULL);
1037 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
1038 P("[i,i,i]", 0, 1, 2);
1039 P("[s,o,O]", NULL, NULL, NULL);
1041 P("[s*,o*,O*]", NULL, NULL, NULL);
1044 P("[ i , i, i ] ", 1, 2, 3);
1055 P("{s:i}", NULL, 1);
1056 P("{ {}: s }", "foo");
1057 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
1058 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
1059 P("y", "???????hello>>>>>>>", (size_t)19);
1060 P("Y", "???????hello>>>>>>>", (size_t)19);
1061 P("{sy?}", "foo", "hi", (size_t)2);
1062 P("{sy?}", "foo", NULL, 0);
1063 P("{sy*}", "foo", "hi", (size_t)2);
1064 P("{sy*}", "foo", NULL, 0);
1066 U("true", "b", &xi[0]);
1067 U("false", "b", &xi[0]);
1069 U("42", "i", &xi[0]);
1070 U("123456789", "I", &xI[0]);
1071 U("3.14", "f", &xf[0]);
1072 U("12345", "F", &xf[0]);
1073 U("3.14", "F", &xf[0]);
1074 U("\"foo\"", "s", &xs[0]);
1075 U("\"foo\"", "s%", &xs[0], &xz[0]);
1078 U("{}", "o", &xo[0]);
1079 U("{}", "O", &xo[0]);
1080 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
1081 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
1082 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
1089 U("[42]", "[i]a", &xi[0]);
1090 U("42", "ia", &xi[0]);
1092 U("\"foo\"", "s", NULL);
1097 U("42", "[i]", NULL);
1098 U("42", "{si}", "foo", NULL);
1100 U("\"foo\"", "b", NULL);
1101 U("\"foo\"", "i", NULL);
1102 U("\"foo\"", "I", NULL);
1103 U("\"foo\"", "f", NULL);
1104 U("\"foo\"", "F", NULL);
1105 U("true", "s", NULL);
1107 U("true", "i", NULL);
1108 U("true", "I", NULL);
1109 U("true", "f", NULL);
1110 U("true", "F", NULL);
1111 U("[42]", "[ii]", &xi[0], &xi[1]);
1112 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
1113 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
1114 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
1115 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
1116 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
1117 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
1118 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
1119 U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
1120 U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
1121 U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
1122 U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
1123 U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
1124 U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
1125 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
1126 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
1127 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
1128 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
1129 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
1130 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
1131 U("{}", "{s?i}", "foo", &xi[0]);
1132 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
1133 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1134 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1135 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1136 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1137 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1138 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1139 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1140 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1142 U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
1143 U("\"\"", "y", &xy[0], &xz[0]);
1144 U("null", "y", &xy[0], &xz[0]);
1145 U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1146 U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1147 U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
1156 /* Unpack the same item twice */
1157 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
1158 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
1159 fail("json_unpack object with strict validation failed");
1161 const char *possible_errors[] = {
1162 "2 object item(s) left unpacked: baz, quux",
1163 "2 object item(s) left unpacked: quux, baz"
1165 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);