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 = wrap_json_vcheck(object, desc, args);
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 = wrap_json_vmatch(object, desc, args);
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 doesn't clones
996 * the content. Synonym of wrap_json_clone_depth(object, 1).
998 * Be aware that this implementation doesn't clones content that is deeper
999 * than 1 but it does link these contents to the original object and
1000 * increments their use count. So, everything deeper that 1 is still available.
1002 * @param object the object to clone
1004 * @return a copy of the object.
1006 * @see wrap_json_clone_depth
1007 * @see wrap_json_clone_deep
1009 struct json_object *wrap_json_clone(struct json_object *object)
1011 return wrap_json_clone_depth(object, 1);
1015 * Clones the 'object': returns a copy of it. Also clones all
1016 * the content recursively. Synonym of wrap_json_clone_depth(object, INT_MAX).
1018 * @param object the object to clone
1020 * @return a copy of the object.
1022 * @see wrap_json_clone_depth
1023 * @see wrap_json_clone
1025 struct json_object *wrap_json_clone_deep(struct json_object *object)
1027 return wrap_json_clone_depth(object, INT_MAX);
1031 * Adds the items of the object 'added' to the object 'dest'.
1033 * @param dest the object to complete this object is modified
1034 * @added the object containing fields to add
1036 * @return the destination object 'dest'
1038 * @example wrap_json_object_add({"a":"a"},{"X":"X"}) -> {"a":"a","X":"X"}
1040 struct json_object *wrap_json_object_add(struct json_object *dest, struct json_object *added)
1042 struct json_object_iterator it, end;
1043 if (json_object_is_type(dest, json_type_object) && json_object_is_type(added, json_type_object)) {
1044 it = json_object_iter_begin(added);
1045 end = json_object_iter_end(added);
1046 while (!json_object_iter_equal(&it, &end)) {
1047 json_object_object_add(dest,
1048 json_object_iter_peek_name(&it),
1049 json_object_get(json_object_iter_peek_value(&it)));
1050 json_object_iter_next(&it);
1057 * Sort the 'array' and returns it. Sorting is done accordingly to the
1058 * order given by the function 'wrap_json_cmp'. If the paramater isn't
1059 * an array, nothing is done and the parameter is returned unchanged.
1061 * @param array the array to sort
1063 * @returns the array sorted
1065 struct json_object *wrap_json_sort(struct json_object *array)
1067 if (json_object_is_type(array, json_type_array))
1068 json_object_array_sort(array, (int(*)(const void*, const void*))wrap_json_cmp);
1074 * Returns a json array of the sorted keys of 'object' or null if 'object' has no keys.
1076 * @param object the object whose keys are to be returned
1078 * @return either NULL is 'object' isn't an object or a sorted array of the key's strings.
1080 struct json_object *wrap_json_keys(struct json_object *object)
1082 struct json_object *r;
1083 struct json_object_iterator it, end;
1084 if (!json_object_is_type(object, json_type_object))
1087 r = json_object_new_array();
1088 it = json_object_iter_begin(object);
1089 end = json_object_iter_end(object);
1090 while (!json_object_iter_equal(&it, &end)) {
1091 json_object_array_add(r, json_object_new_string(json_object_iter_peek_name(&it)));
1092 json_object_iter_next(&it);
1100 * Internal comparison of 'x' with 'y'
1102 * @param x first object to compare
1103 * @param y second object to compare
1104 * @param inc boolean true if should test for inclusion of y in x
1105 * @param sort boolean true if comparison used for sorting
1107 * @return an integer indicating the computed result. Refer to
1108 * the table below for meaning of the returned value.
1110 * inc | sort | x < y | x == y | x > y | y in x
1111 * ----+------+---------+----------+---------+---------
1112 * 0 | 0 | != 0 | 0 | != 0 | > 0
1113 * 0 | 1 | < 0 | 0 | > 0 | > 0
1114 * 1 | 0 | != 0 | 0 | != 0 | 0
1115 * 1 | 1 | < 0 | 0 | > 0 | 0
1118 * if 'x' is found, respectively, to be less than, to match,
1119 * or be greater than 'y'. This is valid when 'sort'
1121 static int jcmp(struct json_object *x, struct json_object *y, int inc, int sort)
1125 const char *sx, *sy;
1126 enum json_type tx, ty;
1128 struct json_object_iterator it, end;
1129 struct json_object *jx, *jy;
1131 /* check equality of pointers */
1136 tx = json_object_get_type(x);
1137 ty = json_object_get_type(y);
1138 r = (int)tx - (int)ty;
1142 /* compare following the type */
1145 case json_type_null:
1148 case json_type_boolean:
1149 r = (int)json_object_get_boolean(x)
1150 - (int)json_object_get_boolean(y);
1153 case json_type_double:
1154 dx = json_object_get_double(x);
1155 dy = json_object_get_double(y);
1156 r = dx < dy ? -1 : dx > dy;
1160 ix = json_object_get_int64(x);
1161 iy = json_object_get_int64(y);
1162 r = ix < iy ? -1 : ix > iy;
1165 case json_type_object:
1166 it = json_object_iter_begin(y);
1167 end = json_object_iter_end(y);
1168 nx = json_object_object_length(x);
1169 ny = json_object_object_length(y);
1173 while (!r && !json_object_iter_equal(&it, &end)) {
1174 if (json_object_object_get_ex(x, json_object_iter_peek_name(&it), &jx)) {
1175 jy = json_object_iter_peek_value(&it);
1176 json_object_iter_next(&it);
1177 r = jcmp(jx, jy, inc, sort);
1179 jx = wrap_json_keys(x);
1180 jy = wrap_json_keys(y);
1181 r = wrap_json_cmp(jx, jy);
1182 json_object_put(jx);
1183 json_object_put(jy);
1189 case json_type_array:
1190 nx = (int)json_object_array_length(x);
1191 ny = (int)json_object_array_length(y);
1195 for (i = 0 ; !r && i < ny ; i++) {
1196 jx = json_object_array_get_idx(x, i);
1197 jy = json_object_array_get_idx(y, i);
1198 r = jcmp(jx, jy, inc, sort);
1202 case json_type_string:
1203 sx = json_object_get_string(x);
1204 sy = json_object_get_string(y);
1212 * Compares 'x' with 'y'
1214 * @param x first object to compare
1215 * @param y second object to compare
1217 * @return an integer less than, equal to, or greater than zero
1218 * if 'x' is found, respectively, to be less than, to match,
1219 * or be greater than 'y'.
1221 int wrap_json_cmp(struct json_object *x, struct json_object *y)
1223 return jcmp(x, y, 0, 1);
1227 * Searchs wether 'x' equals 'y'
1229 * @param x first object to compare
1230 * @param y second object to compare
1232 * @return an integer equal to zero when 'x' != 'y' or 1 when 'x' == 'y'.
1234 int wrap_json_equal(struct json_object *x, struct json_object *y)
1236 return !jcmp(x, y, 0, 0);
1240 * Searchs wether 'x' contains 'y'
1242 * @param x first object to compare
1243 * @param y second object to compare
1245 * @return an integer equal to 1 when 'y' is a subset of 'x' or zero otherwise
1247 int wrap_json_contains(struct json_object *x, struct json_object *y)
1249 return !jcmp(x, y, 1, 0);
1252 #if defined(WRAP_JSON_TEST)
1254 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
1255 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
1258 void tclone(struct json_object *object)
1260 struct json_object *o;
1262 o = wrap_json_clone(object);
1263 if (!wrap_json_equal(object, o))
1264 printf("ERROR in clone or equal: %s VERSUS %s\n", json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE), json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE));
1267 o = wrap_json_clone_deep(object);
1268 if (!wrap_json_equal(object, o))
1269 printf("ERROR in clone_deep or equal: %s VERSUS %s\n", json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE), json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE));
1273 void p(const char *desc, ...)
1277 struct json_object *result;
1279 va_start(args, desc);
1280 rc = wrap_json_vpack(&result, desc, args);
1283 printf(" SUCCESS %s\n\n", json_object_to_json_string_ext(result, JSON_C_TO_STRING_NOSLASHESCAPE));
1285 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));
1287 json_object_put(result);
1294 struct json_object *xo[10];
1298 void u(const char *value, const char *desc, ...)
1303 struct json_object *object, *o;
1305 memset(xs, 0, sizeof xs);
1306 memset(xi, 0, sizeof xi);
1307 memset(xI, 0, sizeof xI);
1308 memset(xf, 0, sizeof xf);
1309 memset(xo, 0, sizeof xo);
1310 memset(xy, 0, sizeof xy);
1311 memset(xz, 0, sizeof xz);
1312 object = json_tokener_parse(value);
1313 va_start(args, desc);
1314 rc = wrap_json_vunpack(object, desc, args);
1317 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));
1321 va_start(args, desc);
1325 case '{': m = (m << 1) | 1; k = 1; break;
1326 case '}': m = m >> 1; k = m&1; break;
1327 case '[': m = m << 1; k = 0; break;
1328 case ']': m = m >> 1; k = m&1; break;
1329 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
1330 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
1331 case 'n': printf(" n"); k = m&1; break;
1332 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
1333 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
1334 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
1335 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
1336 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
1337 case 'o': printf(" o:%s", json_object_to_json_string_ext(*va_arg(args, struct json_object**), JSON_C_TO_STRING_NOSLASHESCAPE)); k = m&1; break;
1338 case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE)); json_object_put(o); k = m&1; break;
1341 uint8_t *p = *va_arg(args, uint8_t**);
1342 size_t s = *va_arg(args, size_t*);
1343 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
1355 json_object_put(object);
1358 void c(const char *sx, const char *sy, int e, int c)
1361 struct json_object *jx, *jy;
1363 jx = json_tokener_parse(sx);
1364 jy = json_tokener_parse(sy);
1366 re = wrap_json_cmp(jx, jy);
1367 rc = wrap_json_contains(jx, jy);
1369 printf("compare(%s)(%s)\n", sx, sy);
1370 printf(" -> %d / %d\n", re, rc);
1373 printf(" ERROR should be %s\n", e ? "equal" : "different");
1375 printf(" ERROR should %scontain\n", c ? "" : "not ");
1380 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
1381 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
1385 char buffer[4] = {'t', 'e', 's', 't'};
1391 P("I", (uint64_t)0x123456789abcdef);
1396 P("s#", "test asdf", 4);
1397 P("s%", "test asdf", (size_t)4);
1399 P("s%", buffer, (size_t)4);
1400 P("s++", "te", "st", "ing");
1401 P("s#+#+", "test", 1, "test", 2, "test");
1402 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
1405 P("o", json_object_new_int(1));
1406 P("o?", json_object_new_int(1));
1408 P("O", json_object_new_int(1));
1409 P("O?", json_object_new_int(1));
1412 P("{s+#+: []}", "foo", "barbar", 3, "baz");
1413 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
1414 P("{s:**}", "a", NULL);
1415 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
1416 P("[i,i,i]", 0, 1, 2);
1417 P("[s,o,O]", NULL, NULL, NULL);
1419 P("[s*,o*,O*]", NULL, NULL, NULL);
1422 P("[ i , i, i ] ", 1, 2, 3);
1433 P("{s:i}", NULL, 1);
1434 P("{ {}: s }", "foo");
1435 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
1436 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
1437 P("y", "???????hello>>>>>>>", (size_t)19);
1438 P("Y", "???????hello>>>>>>>", (size_t)19);
1439 P("{sy?}", "foo", "hi", (size_t)2);
1440 P("{sy?}", "foo", NULL, 0);
1441 P("{sy*}", "foo", "hi", (size_t)2);
1442 P("{sy*}", "foo", NULL, 0);
1444 U("true", "b", &xi[0]);
1445 U("false", "b", &xi[0]);
1447 U("42", "i", &xi[0]);
1448 U("123456789", "I", &xI[0]);
1449 U("3.14", "f", &xf[0]);
1450 U("12345", "F", &xf[0]);
1451 U("3.14", "F", &xf[0]);
1452 U("\"foo\"", "s", &xs[0]);
1453 U("\"foo\"", "s%", &xs[0], &xz[0]);
1456 U("{}", "o", &xo[0]);
1457 U("{}", "O", &xo[0]);
1458 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
1459 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
1460 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
1467 U("[42]", "[i]a", &xi[0]);
1468 U("42", "ia", &xi[0]);
1470 U("\"foo\"", "s", NULL);
1475 U("42", "[i]", NULL);
1476 U("42", "{si}", "foo", NULL);
1478 U("\"foo\"", "b", NULL);
1479 U("\"foo\"", "i", NULL);
1480 U("\"foo\"", "I", NULL);
1481 U("\"foo\"", "f", NULL);
1482 U("\"foo\"", "F", NULL);
1483 U("true", "s", NULL);
1485 U("true", "i", NULL);
1486 U("true", "I", NULL);
1487 U("true", "f", NULL);
1488 U("true", "F", NULL);
1489 U("[42]", "[ii]", &xi[0], &xi[1]);
1490 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
1491 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
1492 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
1493 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
1494 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
1495 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
1496 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
1497 U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
1498 U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
1499 U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
1500 U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
1501 U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
1502 U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
1503 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
1504 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
1505 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
1506 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
1507 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
1508 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
1509 U("{}", "{s?i}", "foo", &xi[0]);
1510 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
1511 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1512 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1513 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1514 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1515 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1516 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1517 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1518 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1520 U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
1521 U("\"\"", "y", &xy[0], &xz[0]);
1522 U("null", "y", &xy[0], &xz[0]);
1523 U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1524 U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1525 U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
1527 c("null", "null", 1, 1);
1528 c("true", "true", 1, 1);
1529 c("false", "false", 1, 1);
1531 c("1.0", "1.0", 1, 1);
1532 c("\"\"", "\"\"", 1, 1);
1533 c("\"hi\"", "\"hi\"", 1, 1);
1534 c("{}", "{}", 1, 1);
1535 c("{\"a\":true,\"b\":false}", "{\"b\":false,\"a\":true}", 1, 1);
1536 c("[]", "[]", 1, 1);
1537 c("[1,true,null]", "[1,true,null]", 1, 1);
1539 c("null", "true", 0, 0);
1540 c("null", "false", 0, 0);
1543 c("0", "true", 0, 0);
1544 c("0", "false", 0, 0);
1545 c("0", "null", 0, 0);
1547 c("\"hi\"", "\"hello\"", 0, 0);
1548 c("\"hello\"", "\"hi\"", 0, 0);
1550 c("{}", "null", 0, 0);
1551 c("{}", "true", 0, 0);
1553 c("{}", "1.0", 0, 0);
1554 c("{}", "[]", 0, 0);
1555 c("{}", "\"x\"", 0, 0);
1557 c("[1,true,null]", "[1,true]", 0, 1);
1558 c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1);
1559 c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0);
1560 c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0);
1569 /* Unpack the same item twice */
1570 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
1571 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
1572 fail("json_unpack object with strict validation failed");
1574 const char *possible_errors[] = {
1575 "2 object item(s) left unpacked: baz, quux",
1576 "2 object item(s) left unpacked: quux, baz"
1578 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);