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);
918 * Clones the 'object' for the depth 'subdepth'. The object 'object' is
919 * duplicated and all its fields are cloned with the depth 'subdepth'.
921 * @param object the object to clone. MUST be an **object**.
922 * @param subdepth the depth to use when cloning the fields of the object.
924 * @return the cloned object.
926 static struct json_object *clone_object(struct json_object *object, int subdepth)
928 struct json_object *r = json_object_new_object();
929 struct json_object_iterator it = json_object_iter_begin(object);
930 struct json_object_iterator end = json_object_iter_end(object);
931 while (!json_object_iter_equal(&it, &end)) {
932 json_object_object_add(r,
933 json_object_iter_peek_name(&it),
934 wrap_json_clone_depth(json_object_iter_peek_value(&it), subdepth));
935 json_object_iter_next(&it);
941 * Clones the 'array' for the depth 'subdepth'. The array 'array' is
942 * duplicated and all its fields are cloned with the depth 'subdepth'.
944 * @param array the array to clone. MUST be an **array**.
945 * @param subdepth the depth to use when cloning the items of the array.
947 * @return the cloned array.
949 static struct json_object *clone_array(struct json_object *array, int subdepth)
951 int n = (int)json_object_array_length(array);
952 struct json_object *r = json_object_new_array();
955 json_object_array_put_idx(r, n,
956 wrap_json_clone_depth(json_object_array_get_idx(array, n), subdepth));
962 * Clones any json 'item' for the depth 'depth'. The item is duplicated
963 * and if 'depth' is not zero, its contents is recursively cloned with
964 * the depth 'depth' - 1.
966 * Be aware that this implementation doesn't copies the primitive json
967 * items (numbers, nulls, booleans, strings) but instead increments their
968 * use count. This can cause issues with newer versions of libjson-c that
969 * now unfortunately allows to change their values.
971 * @param item the item to clone. Can be of any kind.
972 * @param depth the depth to use when cloning composites: object or arrays.
974 * @return the cloned array.
976 * @see wrap_json_clone
977 * @see wrap_json_clone_deep
979 struct json_object *wrap_json_clone_depth(struct json_object *item, int depth)
982 switch (json_object_get_type(item)) {
983 case json_type_object:
984 return clone_object(item, depth - 1);
985 case json_type_array:
986 return clone_array(item, depth - 1);
991 return json_object_get(item);
995 * Clones the 'object': returns a copy of it. But doen't clones
996 * the content. Synonym of wrap_json_clone_depth(object, 1).
998 * @param object the object to clone
1000 * @return a copy of the object.
1002 * @see wrap_json_clone_depth
1003 * @see wrap_json_clone_deep
1005 struct json_object *wrap_json_clone(struct json_object *object)
1007 return wrap_json_clone_depth(object, 1);
1011 * Clones the 'object': returns a copy of it. Also clones all
1012 * the content recursively. Synonym of wrap_json_clone_depth(object, INT_MAX).
1014 * @param object the object to clone
1016 * @return a copy of the object.
1018 * @see wrap_json_clone_depth
1019 * @see wrap_json_clone
1021 struct json_object *wrap_json_clone_deep(struct json_object *object)
1023 return wrap_json_clone_depth(object, INT_MAX);
1027 * Adds the items of the object 'added' to the object 'dest'.
1029 * @param dest the object to complete this object is modified
1030 * @added the object containing fields to add
1032 * @return the destination object 'dest'
1034 * @example wrap_json_object_add({"a":"a"},{"X":"X"}) -> {"a":"a","X":"X"}
1036 struct json_object *wrap_json_object_add(struct json_object *dest, struct json_object *added)
1038 struct json_object_iterator it, end;
1039 if (json_object_is_type(dest, json_type_object) && json_object_is_type(added, json_type_object)) {
1040 it = json_object_iter_begin(added);
1041 end = json_object_iter_end(added);
1042 while (!json_object_iter_equal(&it, &end)) {
1043 json_object_object_add(dest,
1044 json_object_iter_peek_name(&it),
1045 json_object_get(json_object_iter_peek_value(&it)));
1046 json_object_iter_next(&it);
1053 * Sort the 'array' and returns it. Sorting is done accordingly to the
1054 * order given by the function 'wrap_json_cmp'. If the paramater isn't
1055 * an array, nothing is done and the parameter is returned unchanged.
1057 * @param array the array to sort
1059 * @returns the array sorted
1061 struct json_object *wrap_json_sort(struct json_object *array)
1063 if (json_object_is_type(array, json_type_array))
1064 json_object_array_sort(array, (int(*)(const void*, const void*))wrap_json_cmp);
1070 * Returns a json array of the sorted keys of 'object' or null if 'object' has no keys.
1072 * @param object the object whose keys are to be returned
1074 * @return either NULL is 'object' isn't an object or a sorted array of the key's strings.
1076 struct json_object *wrap_json_keys(struct json_object *object)
1078 struct json_object *r;
1079 struct json_object_iterator it, end;
1080 if (!json_object_is_type(object, json_type_object))
1083 r = json_object_new_array();
1084 it = json_object_iter_begin(object);
1085 end = json_object_iter_end(object);
1086 while (!json_object_iter_equal(&it, &end)) {
1087 json_object_array_add(r, json_object_new_string(json_object_iter_peek_name(&it)));
1088 json_object_iter_next(&it);
1096 * Internal comparison of 'x' with 'y'
1098 * @param x first object to compare
1099 * @param y second object to compare
1100 * @param inc boolean true if should test for inclusion of y in x
1101 * @param sort boolean true if comparison used for sorting
1103 * @return an integer indicating the computed result. Refer to
1104 * the table below for meaning of the returned value.
1106 * inc | sort | x < y | x == y | x > y | y in x
1107 * ----+------+---------+----------+---------+---------
1108 * 0 | 0 | != 0 | 0 | != 0 | > 0
1109 * 0 | 1 | < 0 | 0 | > 0 | > 0
1110 * 1 | 0 | != 0 | 0 | != 0 | 0
1111 * 1 | 1 | < 0 | 0 | > 0 | 0
1114 * if 'x' is found, respectively, to be less than, to match,
1115 * or be greater than 'y'. This is valid when 'sort'
1117 static int jcmp(struct json_object *x, struct json_object *y, int inc, int sort)
1121 const char *sx, *sy;
1122 enum json_type tx, ty;
1124 struct json_object_iterator it, end;
1125 struct json_object *jx, *jy;
1127 /* check equality of pointers */
1132 tx = json_object_get_type(x);
1133 ty = json_object_get_type(y);
1134 r = (int)tx - (int)ty;
1138 /* compare following the type */
1141 case json_type_null:
1144 case json_type_boolean:
1145 r = (int)json_object_get_boolean(x)
1146 - (int)json_object_get_boolean(y);
1149 case json_type_double:
1150 dx = json_object_get_double(x);
1151 dy = json_object_get_double(y);
1152 r = dx < dy ? -1 : dx > dy;
1156 ix = json_object_get_int64(x);
1157 iy = json_object_get_int64(y);
1158 r = ix < iy ? -1 : ix > iy;
1161 case json_type_object:
1162 it = json_object_iter_begin(y);
1163 end = json_object_iter_end(y);
1164 nx = json_object_object_length(x);
1165 ny = json_object_object_length(y);
1169 while (!r && !json_object_iter_equal(&it, &end)) {
1170 if (json_object_object_get_ex(x, json_object_iter_peek_name(&it), &jx)) {
1171 jy = json_object_iter_peek_value(&it);
1172 json_object_iter_next(&it);
1173 r = jcmp(jx, jy, inc, sort);
1175 jx = wrap_json_keys(x);
1176 jy = wrap_json_keys(y);
1177 r = wrap_json_cmp(jx, jy);
1178 json_object_put(jx);
1179 json_object_put(jy);
1185 case json_type_array:
1186 nx = (int)json_object_array_length(x);
1187 ny = (int)json_object_array_length(y);
1191 for (i = 0 ; !r && i < ny ; i++) {
1192 jx = json_object_array_get_idx(x, i);
1193 jy = json_object_array_get_idx(y, i);
1194 r = jcmp(jx, jy, inc, sort);
1198 case json_type_string:
1199 sx = json_object_get_string(x);
1200 sy = json_object_get_string(y);
1208 * Compares 'x' with 'y'
1210 * @param x first object to compare
1211 * @param y second object to compare
1213 * @return an integer less than, equal to, or greater than zero
1214 * if 'x' is found, respectively, to be less than, to match,
1215 * or be greater than 'y'.
1217 int wrap_json_cmp(struct json_object *x, struct json_object *y)
1219 return jcmp(x, y, 0, 1);
1223 * Searchs wether 'x' equals 'y'
1225 * @param x first object to compare
1226 * @param y second object to compare
1228 * @return an integer equal to zero when 'x' != 'y' or 1 when 'x' == 'y'.
1230 int wrap_json_equal(struct json_object *x, struct json_object *y)
1232 return !jcmp(x, y, 0, 0);
1236 * Searchs wether 'x' contains 'y'
1238 * @param x first object to compare
1239 * @param y second object to compare
1241 * @return an integer equal to 1 when 'y' is a subset of 'x' or zero otherwise
1243 int wrap_json_contains(struct json_object *x, struct json_object *y)
1245 return !jcmp(x, y, 1, 0);
1248 #if defined(WRAP_JSON_TEST)
1251 void tclone(struct json_object *object)
1253 struct json_object *o;
1255 o = wrap_json_clone(object);
1256 if (!wrap_json_equal(object, o))
1257 printf("ERROR in clone or equal: %s VERSUS %s\n", json_object_to_json_string(object), json_object_to_json_string(o));
1260 o = wrap_json_clone_deep(object);
1261 if (!wrap_json_equal(object, o))
1262 printf("ERROR in clone_deep or equal: %s VERSUS %s\n", json_object_to_json_string(object), json_object_to_json_string(o));
1266 void p(const char *desc, ...)
1270 struct json_object *result;
1272 va_start(args, desc);
1273 rc = wrap_json_vpack(&result, desc, args);
1276 printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
1278 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));
1280 json_object_put(result);
1287 struct json_object *xo[10];
1291 void u(const char *value, const char *desc, ...)
1296 struct json_object *object, *o;
1298 memset(xs, 0, sizeof xs);
1299 memset(xi, 0, sizeof xi);
1300 memset(xI, 0, sizeof xI);
1301 memset(xf, 0, sizeof xf);
1302 memset(xo, 0, sizeof xo);
1303 memset(xy, 0, sizeof xy);
1304 memset(xz, 0, sizeof xz);
1305 object = json_tokener_parse(value);
1306 va_start(args, desc);
1307 rc = wrap_json_vunpack(object, desc, args);
1310 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));
1314 va_start(args, desc);
1318 case '{': m = (m << 1) | 1; k = 1; break;
1319 case '}': m = m >> 1; k = m&1; break;
1320 case '[': m = m << 1; k = 0; break;
1321 case ']': m = m >> 1; k = m&1; break;
1322 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
1323 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
1324 case 'n': printf(" n"); k = m&1; break;
1325 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
1326 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
1327 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
1328 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
1329 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
1330 case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
1331 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;
1334 uint8_t *p = *va_arg(args, uint8_t**);
1335 size_t s = *va_arg(args, size_t*);
1336 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
1348 json_object_put(object);
1351 void c(const char *sx, const char *sy, int e, int c)
1354 struct json_object *jx, *jy;
1356 jx = json_tokener_parse(sx);
1357 jy = json_tokener_parse(sy);
1359 re = wrap_json_cmp(jx, jy);
1360 rc = wrap_json_contains(jx, jy);
1362 printf("compare(%s)(%s)\n", sx, sy);
1363 printf(" -> %d / %d\n", re, rc);
1366 printf(" ERROR should be %s\n", e ? "equal" : "different");
1368 printf(" ERROR should %scontain\n", c ? "" : "not ");
1373 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
1374 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
1378 char buffer[4] = {'t', 'e', 's', 't'};
1384 P("I", (uint64_t)0x123456789abcdef);
1389 P("s#", "test asdf", 4);
1390 P("s%", "test asdf", (size_t)4);
1392 P("s%", buffer, (size_t)4);
1393 P("s++", "te", "st", "ing");
1394 P("s#+#+", "test", 1, "test", 2, "test");
1395 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
1398 P("o", json_object_new_int(1));
1399 P("o?", json_object_new_int(1));
1401 P("O", json_object_new_int(1));
1402 P("O?", json_object_new_int(1));
1405 P("{s+#+: []}", "foo", "barbar", 3, "baz");
1406 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
1407 P("{s:**}", "a", NULL);
1408 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
1409 P("[i,i,i]", 0, 1, 2);
1410 P("[s,o,O]", NULL, NULL, NULL);
1412 P("[s*,o*,O*]", NULL, NULL, NULL);
1415 P("[ i , i, i ] ", 1, 2, 3);
1426 P("{s:i}", NULL, 1);
1427 P("{ {}: s }", "foo");
1428 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
1429 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
1430 P("y", "???????hello>>>>>>>", (size_t)19);
1431 P("Y", "???????hello>>>>>>>", (size_t)19);
1432 P("{sy?}", "foo", "hi", (size_t)2);
1433 P("{sy?}", "foo", NULL, 0);
1434 P("{sy*}", "foo", "hi", (size_t)2);
1435 P("{sy*}", "foo", NULL, 0);
1437 U("true", "b", &xi[0]);
1438 U("false", "b", &xi[0]);
1440 U("42", "i", &xi[0]);
1441 U("123456789", "I", &xI[0]);
1442 U("3.14", "f", &xf[0]);
1443 U("12345", "F", &xf[0]);
1444 U("3.14", "F", &xf[0]);
1445 U("\"foo\"", "s", &xs[0]);
1446 U("\"foo\"", "s%", &xs[0], &xz[0]);
1449 U("{}", "o", &xo[0]);
1450 U("{}", "O", &xo[0]);
1451 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
1452 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
1453 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
1460 U("[42]", "[i]a", &xi[0]);
1461 U("42", "ia", &xi[0]);
1463 U("\"foo\"", "s", NULL);
1468 U("42", "[i]", NULL);
1469 U("42", "{si}", "foo", NULL);
1471 U("\"foo\"", "b", NULL);
1472 U("\"foo\"", "i", NULL);
1473 U("\"foo\"", "I", NULL);
1474 U("\"foo\"", "f", NULL);
1475 U("\"foo\"", "F", NULL);
1476 U("true", "s", NULL);
1478 U("true", "i", NULL);
1479 U("true", "I", NULL);
1480 U("true", "f", NULL);
1481 U("true", "F", NULL);
1482 U("[42]", "[ii]", &xi[0], &xi[1]);
1483 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
1484 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
1485 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
1486 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
1487 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
1488 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
1489 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
1490 U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
1491 U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
1492 U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
1493 U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
1494 U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
1495 U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
1496 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
1497 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
1498 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
1499 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
1500 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
1501 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
1502 U("{}", "{s?i}", "foo", &xi[0]);
1503 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
1504 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1505 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1506 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1507 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1508 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1509 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1510 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1511 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1513 U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
1514 U("\"\"", "y", &xy[0], &xz[0]);
1515 U("null", "y", &xy[0], &xz[0]);
1516 U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1517 U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1518 U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
1520 c("null", "null", 1, 1);
1521 c("true", "true", 1, 1);
1522 c("false", "false", 1, 1);
1524 c("1.0", "1.0", 1, 1);
1525 c("\"\"", "\"\"", 1, 1);
1526 c("\"hi\"", "\"hi\"", 1, 1);
1527 c("{}", "{}", 1, 1);
1528 c("{\"a\":true,\"b\":false}", "{\"b\":false,\"a\":true}", 1, 1);
1529 c("[]", "[]", 1, 1);
1530 c("[1,true,null]", "[1,true,null]", 1, 1);
1532 c("null", "true", 0, 0);
1533 c("null", "false", 0, 0);
1536 c("0", "true", 0, 0);
1537 c("0", "false", 0, 0);
1538 c("0", "null", 0, 0);
1540 c("\"hi\"", "\"hello\"", 0, 0);
1541 c("\"hello\"", "\"hi\"", 0, 0);
1543 c("{}", "null", 0, 0);
1544 c("{}", "true", 0, 0);
1546 c("{}", "1.0", 0, 0);
1547 c("{}", "[]", 0, 0);
1548 c("{}", "\"x\"", 0, 0);
1550 c("[1,true,null]", "[1,true]", 0, 1);
1551 c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1);
1552 c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0);
1553 c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0);
1562 /* Unpack the same item twice */
1563 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
1564 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
1565 fail("json_unpack object with strict validation failed");
1567 const char *possible_errors[] = {
1568 "2 object item(s) left unpacked: baz, quux",
1569 "2 object item(s) left unpacked: quux, baz"
1571 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);