Update copyright dates
[src/app-framework-binder.git] / src / wrap-json.c
1 /*
2  Copyright (C) 2015-2020 "IoT.bzh"
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
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
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
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.
17 */
18
19 #include <string.h>
20 #include <limits.h>
21
22 #include "wrap-json.h"
23
24 #define STACKCOUNT  32
25 #define STRCOUNT    8
26
27 enum {
28         wrap_json_error_none,
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_
45 };
46
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])
51
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])
55
56 static const char *pack_errors[_wrap_json_error_count_] =
57 {
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"
74 };
75
76 int wrap_json_get_error_position(int rc)
77 {
78         if (rc < 0)
79                 rc = -rc;
80         return (rc >> 4) + 1;
81 }
82
83 int wrap_json_get_error_code(int rc)
84 {
85         if (rc < 0)
86                 rc = -rc;
87         return rc & 15;
88 }
89
90 const char *wrap_json_get_error_string(int rc)
91 {
92         rc = wrap_json_get_error_code(rc);
93         if (rc >= (int)(sizeof pack_errors / sizeof *pack_errors))
94                 rc = 0;
95         return pack_errors[rc];
96 }
97
98 static int encode_base64(
99                 const uint8_t *data,
100                 size_t datalen,
101                 char **encoded,
102                 size_t *encodedlen,
103                 int width,
104                 int pad,
105                 int url)
106 {
107         uint16_t u16 = 0;
108         uint8_t u8 = 0;
109         size_t in, out, rlen, n3, r3, iout, nout;
110         int iw;
111         char *result, c;
112
113         /* compute unformatted output length */
114         n3 = datalen / 3;
115         r3 = datalen % 3;
116         nout = 4 * n3 + r3 + !!r3;
117
118         /* deduce formatted output length */
119         rlen = nout;
120         if (pad)
121                 rlen += ((~rlen) + 1) & 3;
122         if (width)
123                 rlen += rlen / width;
124
125         /* allocate the output */
126         result = malloc(rlen + 1);
127         if (result == NULL)
128                 return wrap_json_error_out_of_memory;
129
130         /* compute the formatted output */
131         iw = width;
132         for (in = out = iout = 0 ; iout < nout ; iout++) {
133                 /* get in 'u8' the 6 bits value to add */
134                 switch (iout & 3) {
135                 case 0:
136                         u16 = (uint16_t)data[in++];
137                         u8 = (uint8_t)(u16 >> 2);
138                         break;
139                 case 1:
140                         u16 = (uint16_t)(u16 << 8);
141                         if (in < datalen)
142                                 u16 = (uint16_t)(u16 | data[in++]);
143                         u8 = (uint8_t)(u16 >> 4);
144                         break;
145                 case 2:
146                         u16 = (uint16_t)(u16 << 8);
147                         if (in < datalen)
148                                 u16 = (uint16_t)(u16 | data[in++]);
149                         u8 = (uint8_t)(u16 >> 6);
150                         break;
151                 case 3:
152                         u8 = (uint8_t)u16;
153                         break;
154                 }
155                 u8 &= 63;
156
157                 /* encode 'u8' to the char 'c' */
158                 if (u8 < 52) {
159                         if (u8 < 26)
160                                 c = (char)('A' + u8);
161                         else
162                                 c = (char)('a' + u8 - 26);
163                 } else {
164                         if (u8 < 62)
165                                 c = (char)('0' + u8 - 52);
166                         else if (u8 == 62)
167                                 c = url ? '-' : '+';
168                         else
169                                 c = url ? '_' : '/';
170                 }
171
172                 /* put to output with format */
173                 result[out++] = c;
174                 if (iw && !--iw) {
175                         result[out++] = '\n';
176                         iw = width;
177                 }
178         }
179
180         /* pad the output */
181         while (out < rlen) {
182                 result[out++] = '=';
183                 if (iw && !--iw) {
184                         result[out++] = '\n';
185                         iw = width;
186                 }
187         }
188
189         /* terminate */
190         result[out] = 0;
191         *encoded = result;
192         *encodedlen = rlen;
193         return 0;
194 }
195
196 static int decode_base64(
197                 const char *data,
198                 size_t datalen,
199                 uint8_t **decoded,
200                 size_t *decodedlen,
201                 int url)
202 {
203         uint16_t u16;
204         uint8_t u8, *result;
205         size_t in, out, iin;
206         char c;
207
208         /* allocate enougth output */
209         result = malloc(datalen);
210         if (result == NULL)
211                 return wrap_json_error_out_of_memory;
212
213         /* decode the input */
214         for (iin = in = out = 0 ; in < datalen ; in++) {
215                 c = data[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 == '-')
224                                 u8 = (uint8_t)62;
225                         else if (c == '/' || c == '_')
226                                 u8 = (uint8_t)63;
227                         else {
228                                 free(result);
229                                 return wrap_json_error_bad_base64;
230                         }
231                         if (!iin) {
232                                 u16 = (uint16_t)u8;
233                                 iin = 6;
234                         } else {
235                                 u16 = (uint16_t)((u16 << 6) | u8);
236                                 iin -= 2;
237                                 u8 = (uint8_t)(u16 >> iin);
238                                 result[out++] = u8;
239                         }
240                 }
241         }
242
243         /* terminate */
244         *decoded = realloc(result, out);
245         if (out && *decoded == NULL) {
246                 free(result);
247                 return wrap_json_error_out_of_memory;
248         }
249         *decodedlen = out;
250         return 0;
251 }
252
253 static inline const char *skip(const char *d)
254 {
255         while (*d && strchr(ignore_all, *d))
256                 d++;
257         return d;
258 }
259
260 int wrap_json_vpack(struct json_object **result, const char *desc, va_list args)
261 {
262         /* TODO: the case of structs with key being single char should be optimized */
263         int nstr, notnull, nullable, rc;
264         size_t sz, dsz, ssz;
265         char *s;
266         char c;
267         const char *d;
268         char buffer[256];
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;
273
274         ssz = sizeof buffer;
275         s = buffer;
276         top = stack;
277         top->key = NULL;
278         top->cont = NULL;
279         top->acc = pack_accept_any;
280         top->type = 0;
281         d = desc;
282         if (!d)
283                 goto null_spec;
284         d = skip(d);
285         for(;;) {
286                 c = *d;
287                 if (!c)
288                         goto truncated;
289                 if (!strchr(top->acc, c))
290                         goto invalid_character;
291                 d = skip(d + 1);
292                 switch(c) {
293                 case 's':
294                         nullable = 0;
295                         notnull = 0;
296                         nstr = 0;
297                         sz = 0;
298                         for (;;) {
299                                 strs[nstr].str = va_arg(args, const char*);
300                                 if (strs[nstr].str)
301                                         notnull = 1;
302                                 if (*d == '?') {
303                                         d = skip(d + 1);
304                                         nullable = 1;
305                                 }
306                                 switch(*d) {
307                                 case '%': strs[nstr].sz = va_arg(args, size_t); d = skip(d + 1); break;
308                                 case '#': strs[nstr].sz = (size_t)va_arg(args, int); d = skip(d + 1); break;
309                                 default: strs[nstr].sz = strs[nstr].str ? strlen(strs[nstr].str) : 0; break;
310                                 }
311                                 sz += strs[nstr++].sz;
312                                 if (*d == '?') {
313                                         d = skip(d + 1);
314                                         nullable = 1;
315                                 }
316                                 if (*d != '+')
317                                         break;
318                                 if (nstr >= STRCOUNT)
319                                         goto too_long;
320                                 d = skip(d + 1);
321                         }
322                         if (*d == '*')
323                                 nullable = 1;
324                         if (notnull) {
325                                 if (sz > ssz) {
326                                         ssz += ssz;
327                                         if (ssz < sz)
328                                                 ssz = sz;
329                                         s = alloca(sz);
330                                 }
331                                 dsz = sz;
332                                 while (nstr) {
333                                         nstr--;
334                                         dsz -= strs[nstr].sz;
335                                         memcpy(&s[dsz], strs[nstr].str, strs[nstr].sz);
336                                 }
337                                 obj = json_object_new_string_len(s, (int)sz);
338                                 if (!obj)
339                                         goto out_of_memory;
340                         } else if (nullable)
341                                 obj = NULL;
342                         else
343                                 goto null_string;
344                         break;
345                 case 'n':
346                         obj = NULL;
347                         break;
348                 case 'b':
349                         obj = json_object_new_boolean(va_arg(args, int));
350                         if (!obj)
351                                 goto out_of_memory;
352                         break;
353                 case 'i':
354                         obj = json_object_new_int(va_arg(args, int));
355                         if (!obj)
356                                 goto out_of_memory;
357                         break;
358                 case 'I':
359                         obj = json_object_new_int64(va_arg(args, int64_t));
360                         if (!obj)
361                                 goto out_of_memory;
362                         break;
363                 case 'f':
364                         obj = json_object_new_double(va_arg(args, double));
365                         if (!obj)
366                                 goto out_of_memory;
367                         break;
368                 case 'o':
369                 case 'O':
370                         obj = va_arg(args, struct json_object*);
371                         if (*d == '?')
372                                 d = skip(d + 1);
373                         else if (*d != '*' && !obj)
374                                 goto null_object;
375                         if (c == 'O')
376                                 json_object_get(obj);
377                         break;
378                 case 'y':
379                 case 'Y':
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)
383                                 obj = NULL;
384                         else {
385                                 rc = encode_base64(bytes.in, bytes.insz,
386                                         &bytes.out, &bytes.outsz, 0, 0, c == 'y');
387                                 if (rc)
388                                         goto error;
389                                 obj = json_object_new_string_len(bytes.out, (int)bytes.outsz);
390                                 free(bytes.out);
391                                 if (!obj)
392                                         goto out_of_memory;
393                         }
394                         if (*d == '?')
395                                 d = skip(d + 1);
396                         else if (*d != '*' && !obj) {
397                                 obj = json_object_new_string_len(d, 0);
398                                 if (!obj)
399                                         goto out_of_memory;
400                         }
401                         break;
402                 case '[':
403                 case '{':
404                         if (++top >= &stack[STACKCOUNT])
405                                 goto too_deep;
406                         top->key = NULL;
407                         if (c == '[') {
408                                 top->type = ']';
409                                 top->acc = pack_accept_arr;
410                                 top->cont = json_object_new_array();
411                         } else {
412                                 top->type = '}';
413                                 top->acc = pack_accept_key;
414                                 top->cont = json_object_new_object();
415                         }
416                         if (!top->cont)
417                                 goto out_of_memory;
418                         continue;
419                 case '}':
420                 case ']':
421                         if (c != top->type || top <= stack)
422                                 goto internal_error;
423                         obj = (top--)->cont;
424                         if (*d == '*' && !(c == '}' ? json_object_object_length(obj) : json_object_array_length(obj))) {
425                                 json_object_put(obj);
426                                 obj = NULL;
427                         }
428                         break;
429                 default:
430                         goto internal_error;
431                 }
432                 switch (top->type) {
433                 case 0:
434                         if (top != stack)
435                                 goto internal_error;
436                         if (*d)
437                                 goto invalid_character;
438                         *result = obj;
439                         return 0;
440                 case ']':
441                         if (obj || *d != '*')
442                                 json_object_array_add(top->cont, obj);
443                         if (*d == '*')
444                                 d = skip(d + 1);
445                         break;
446                 case '}':
447                         if (!obj)
448                                 goto null_key;
449                         top->key = obj;
450                         top->acc = pack_accept_any;
451                         top->type = ':';
452                         break;
453                 case ':':
454                         if (obj || *d != '*')
455                                 json_object_object_add(top->cont, json_object_get_string(top->key), obj);
456                         if (*d == '*')
457                                 d = skip(d + 1);
458                         json_object_put(top->key);
459                         top->key = NULL;
460                         top->acc = pack_accept_key;
461                         top->type = '}';
462                         break;
463                 default:
464                         goto internal_error;
465                 }
466         }
467
468 null_object:
469         rc = wrap_json_error_null_object;
470         goto error;
471 truncated:
472         rc = wrap_json_error_truncated;
473         goto error;
474 internal_error:
475         rc = wrap_json_error_internal_error;
476         goto error;
477 out_of_memory:
478         rc = wrap_json_error_out_of_memory;
479         goto error;
480 invalid_character:
481         rc = wrap_json_error_invalid_character;
482         goto error;
483 too_long:
484         rc = wrap_json_error_too_long;
485         goto error;
486 too_deep:
487         rc = wrap_json_error_too_deep;
488         goto error;
489 null_spec:
490         rc = wrap_json_error_null_spec;
491         goto error;
492 null_key:
493         rc = wrap_json_error_null_key;
494         goto error;
495 null_string:
496         rc = wrap_json_error_null_string;
497         goto error;
498 error:
499         do {
500                 json_object_put(top->key);
501                 json_object_put(top->cont);
502         } while (--top >= stack);
503         *result = NULL;
504         rc = rc | (int)((d - desc) << 4);
505         return -rc;
506 }
507
508 int wrap_json_pack(struct json_object **result, const char *desc, ...)
509 {
510         int rc;
511         va_list args;
512
513         va_start(args, desc);
514         rc = wrap_json_vpack(result, desc, args);
515         va_end(args);
516         return rc;
517 }
518
519 static int vunpack(struct json_object *object, const char *desc, va_list args, int store)
520 {
521         int rc = 0, optionnal, ignore;
522         char c, xacc[2] = { 0, 0 };
523         const char *acc;
524         const char *d, *fit = NULL;
525         const char *key = NULL;
526         const char **ps = NULL;
527         double *pf = NULL;
528         int *pi = NULL;
529         int64_t *pI = NULL;
530         size_t *pz = NULL;
531         uint8_t **py = 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;
535
536         xacc[0] = 0;
537         ignore = 0;
538         top = NULL;
539         acc = unpack_accept_any;
540         d = desc;
541         if (!d)
542                 goto null_spec;
543         d = skip(d);
544         obj = object;
545         for(;;) {
546                 fit = d;
547                 c = *d;
548                 if (!c)
549                         goto truncated;
550                 if (!strchr(acc, c))
551                         goto invalid_character;
552                 d = skip(d + 1);
553                 switch(c) {
554                 case 's':
555                         if (xacc[0] == '}') {
556                                 /* expects a key */
557                                 key = va_arg(args, const char *);
558                                 if (!key)
559                                         goto null_key;
560                                 if (*d != '?')
561                                         optionnal = 0;
562                                 else {
563                                         optionnal = 1;
564                                         d = skip(d + 1);
565                                 }
566                                 if (ignore)
567                                         ignore++;
568                                 else {
569                                         if (json_object_object_get_ex(top->parent, key, &obj)) {
570                                                 /* found */
571                                                 top->index++;
572                                         } else {
573                                                 /* not found */
574                                                 if (!optionnal)
575                                                         goto key_not_found;
576                                                 ignore = 1;
577                                                 obj = NULL;
578                                         }
579                                 }
580                                 xacc[0] = ':';
581                                 acc = unpack_accept_any;
582                                 continue;
583                         }
584                         /* get a string */
585                         if (store)
586                                 ps = va_arg(args, const char **);
587                         if (!ignore) {
588                                 if (!json_object_is_type(obj, json_type_string))
589                                         goto missfit;
590                                 if (store && ps)
591                                         *ps = json_object_get_string(obj);
592                         }
593                         if (*d == '%') {
594                                 d = skip(d + 1);
595                                 if (store) {
596                                         pz = va_arg(args, size_t *);
597                                         if (!ignore && pz)
598                                                 *pz = (size_t)json_object_get_string_len(obj);
599                                 }
600                         }
601                         break;
602                 case 'n':
603                         if (!ignore && !json_object_is_type(obj, json_type_null))
604                                 goto missfit;
605                         break;
606                 case 'b':
607                         if (store)
608                                 pi = va_arg(args, int *);
609
610                         if (!ignore) {
611                                 if (!json_object_is_type(obj, json_type_boolean))
612                                         goto missfit;
613                                 if (store && pi)
614                                         *pi = json_object_get_boolean(obj);
615                         }
616                         break;
617                 case 'i':
618                         if (store)
619                                 pi = va_arg(args, int *);
620
621                         if (!ignore) {
622                                 if (!json_object_is_type(obj, json_type_int))
623                                         goto missfit;
624                                 if (store && pi)
625                                         *pi = json_object_get_int(obj);
626                         }
627                         break;
628                 case 'I':
629                         if (store)
630                                 pI = va_arg(args, int64_t *);
631
632                         if (!ignore) {
633                                 if (!json_object_is_type(obj, json_type_int))
634                                         goto missfit;
635                                 if (store && pI)
636                                         *pI = json_object_get_int64(obj);
637                         }
638                         break;
639                 case 'f':
640                 case 'F':
641                         if (store)
642                                 pf = va_arg(args, double *);
643
644                         if (!ignore) {
645                                 if (!(json_object_is_type(obj, json_type_double) || (c == 'F' && json_object_is_type(obj, json_type_int))))
646                                         goto missfit;
647                                 if (store && pf)
648                                         *pf = json_object_get_double(obj);
649                         }
650                         break;
651                 case 'o':
652                 case 'O':
653                         if (store) {
654                                 po = va_arg(args, struct json_object **);
655                                 if (!ignore && po) {
656                                         if (c == 'O')
657                                                 obj = json_object_get(obj);
658                                         *po = obj;
659                                 }
660                         }
661                         break;
662                 case 'y':
663                 case 'Y':
664                         if (store) {
665                                 py = va_arg(args, uint8_t **);
666                                 pz = va_arg(args, size_t *);
667                         }
668                         if (!ignore) {
669                                 if (obj == NULL) {
670                                         if (store && py && pz) {
671                                                 *py = NULL;
672                                                 *pz = 0;
673                                         }
674                                 } else {
675                                         if (!json_object_is_type(obj, json_type_string))
676                                                 goto missfit;
677                                         if (store && py && pz) {
678                                                 rc = decode_base64(
679                                                         json_object_get_string(obj),
680                                                         (size_t)json_object_get_string_len(obj),
681                                                         py, pz, c == 'y');
682                                                 if (rc)
683                                                         goto error;
684                                         }
685                                 }
686                         }
687                         break;
688
689                 case '[':
690                 case '{':
691                         if (!top)
692                                 top = stack;
693                         else if (++top  >= &stack[STACKCOUNT])
694                                 goto too_deep;
695
696                         top->acc = acc;
697                         top->type = xacc[0];
698                         top->index = 0;
699                         top->parent = obj;
700                         if (ignore)
701                                 ignore++;
702                         if (c == '[') {
703                                 if (!ignore) {
704                                         if (!json_object_is_type(obj, json_type_array))
705                                                 goto missfit;
706                                         top->count = (int)json_object_array_length(obj);
707                                 }
708                                 xacc[0] = ']';
709                                 acc = unpack_accept_arr;
710                         } else {
711                                 if (!ignore) {
712                                         if (!json_object_is_type(obj, json_type_object))
713                                                 goto missfit;
714                                         top->count = json_object_object_length(obj);
715                                 }
716                                 xacc[0] = '}';
717                                 acc = unpack_accept_key;
718                                 continue;
719                         }
720                         break;
721                 case '}':
722                 case ']':
723                         if (!top || c != xacc[0])
724                                 goto internal_error;
725                         acc = top->acc;
726                         xacc[0] = top->type;
727                         top = top == stack ? NULL : top - 1;
728                         if (ignore)
729                                 ignore--;
730                         break;
731                 case '!':
732                         if (*d != xacc[0])
733                                 goto invalid_character;
734                         if (!ignore && top->index != top->count)
735                                 goto incomplete;
736                         /*@fallthrough@*/
737                 case '*':
738                         acc = xacc;
739                         continue;
740                 default:
741                         goto internal_error;
742                 }
743                 switch (xacc[0]) {
744                 case 0:
745                         if (top)
746                                 goto internal_error;
747                         if (*d)
748                                 goto invalid_character;
749                         return 0;
750                 case ']':
751                         if (!ignore) {
752                                 key = strchr(unpack_accept_arr, *d);
753                                 if (key && key >= unpack_accept_any) {
754                                         if (top->index >= top->count)
755                                                 goto out_of_range;
756                                         obj = json_object_array_get_idx(top->parent, top->index++);
757                                 }
758                         }
759                         break;
760                 case ':':
761                         acc = unpack_accept_key;
762                         xacc[0] = '}';
763                         if (ignore)
764                                 ignore--;
765                         break;
766                 default:
767                         goto internal_error;
768                 }
769         }
770 truncated:
771         rc = wrap_json_error_truncated;
772         goto error;
773 internal_error:
774         rc = wrap_json_error_internal_error;
775         goto error;
776 invalid_character:
777         rc = wrap_json_error_invalid_character;
778         goto error;
779 too_deep:
780         rc = wrap_json_error_too_deep;
781         goto error;
782 null_spec:
783         rc = wrap_json_error_null_spec;
784         goto error;
785 null_key:
786         rc = wrap_json_error_null_key;
787         goto error;
788 out_of_range:
789         rc = wrap_json_error_out_of_range;
790         goto error;
791 incomplete:
792         rc = wrap_json_error_incomplete;
793         goto error;
794 missfit:
795         rc = wrap_json_error_missfit_type;
796         goto errorfit;
797 key_not_found:
798         rc = wrap_json_error_key_not_found;
799         goto error;
800 errorfit:
801         d = fit;
802 error:
803         rc = rc | (int)((d - desc) << 4);
804         return -rc;
805 }
806
807 int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
808 {
809         return vunpack(object, desc, args, 0);
810 }
811
812 int wrap_json_check(struct json_object *object, const char *desc, ...)
813 {
814         int rc;
815         va_list args;
816
817         va_start(args, desc);
818         rc = wrap_json_vcheck(object, desc, args);
819         va_end(args);
820         return rc;
821 }
822
823 int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
824 {
825         return !vunpack(object, desc, args, 0);
826 }
827
828 int wrap_json_match(struct json_object *object, const char *desc, ...)
829 {
830         int rc;
831         va_list args;
832
833         va_start(args, desc);
834         rc = wrap_json_vmatch(object, desc, args);
835         va_end(args);
836         return rc;
837 }
838
839 int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
840 {
841         return vunpack(object, desc, args, 1);
842 }
843
844 int wrap_json_unpack(struct json_object *object, const char *desc, ...)
845 {
846         int rc;
847         va_list args;
848
849         va_start(args, desc);
850         rc = vunpack(object, desc, args, 1);
851         va_end(args);
852         return rc;
853 }
854
855 static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
856 {
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);
862         }
863 }
864
865 static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
866 {
867         int n = (int)json_object_array_length(object);
868         int i = 0;
869         while(i < n)
870                 callback(closure, json_object_array_get_idx(object, i++));
871 }
872
873 void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
874 {
875         if (json_object_is_type(object, json_type_array))
876                 array_for_all(object, callback, closure);
877         else
878                 callback(closure, object);
879 }
880
881 void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
882 {
883         if (json_object_is_type(object, json_type_array))
884                 array_for_all(object, callback, closure);
885 }
886
887 void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
888 {
889         if (json_object_is_type(object, json_type_object))
890                 object_for_all(object, callback, closure);
891 }
892
893 void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
894 {
895         if (json_object_is_type(object, json_type_object))
896                 object_for_all(object, callback, closure);
897         else
898                 callback(closure, object, NULL);
899 }
900
901 void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
902 {
903         if (!object)
904                 /* do nothing */;
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);
909         else {
910                 int n = (int)json_object_array_length(object);
911                 int i = 0;
912                 while(i < n)
913                         callback(closure, json_object_array_get_idx(object, i++), NULL);
914         }
915 }
916
917 /**
918  * Clones the 'object' for the depth 'subdepth'. The object 'object' is
919  * duplicated and all its fields are cloned with the depth 'subdepth'.
920  *
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.
923  *
924  * @return the cloned object.
925  */
926 static struct json_object *clone_object(struct json_object *object, int subdepth)
927 {
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);
936         }
937         return r;
938 }
939
940 /**
941  * Clones the 'array' for the depth 'subdepth'. The array 'array' is
942  * duplicated and all its fields are cloned with the depth 'subdepth'.
943  *
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.
946  *
947  * @return the cloned array.
948  */
949 static struct json_object *clone_array(struct json_object *array, int subdepth)
950 {
951         int n = (int)json_object_array_length(array);
952         struct json_object *r = json_object_new_array();
953         while (n) {
954                 n--;
955                 json_object_array_put_idx(r, n,
956                         wrap_json_clone_depth(json_object_array_get_idx(array, n), subdepth));
957         }
958         return r;
959 }
960
961 /**
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.
965  *
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.
970  *
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.
973  *
974  * @return the cloned array.
975  *
976  * @see wrap_json_clone
977  * @see wrap_json_clone_deep
978  */
979 struct json_object *wrap_json_clone_depth(struct json_object *item, int depth)
980 {
981         if (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);
987                 default:
988                         break;
989                 }
990         }
991         return json_object_get(item);
992 }
993
994 /**
995  * Clones the 'object': returns a copy of it. But doesn't clones
996  * the content. Synonym of wrap_json_clone_depth(object, 1).
997  *
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.
1001  *
1002  * @param object the object to clone
1003  *
1004  * @return a copy of the object.
1005  *
1006  * @see wrap_json_clone_depth
1007  * @see wrap_json_clone_deep
1008  */
1009 struct json_object *wrap_json_clone(struct json_object *object)
1010 {
1011         return wrap_json_clone_depth(object, 1);
1012 }
1013
1014 /**
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).
1017  *
1018  * @param object the object to clone
1019  *
1020  * @return a copy of the object.
1021  *
1022  * @see wrap_json_clone_depth
1023  * @see wrap_json_clone
1024  */
1025 struct json_object *wrap_json_clone_deep(struct json_object *object)
1026 {
1027         return wrap_json_clone_depth(object, INT_MAX);
1028 }
1029
1030 /**
1031  * Adds the items of the object 'added' to the object 'dest'.
1032  *
1033  * @param dest the object to complete this object is modified
1034  * @added the object containing fields to add
1035  *
1036  * @return the destination object 'dest'
1037  *
1038  * @example wrap_json_object_add({"a":"a"},{"X":"X"}) -> {"a":"a","X":"X"}
1039  */
1040 struct json_object *wrap_json_object_add(struct json_object *dest, struct json_object *added)
1041 {
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);
1051                 }
1052         }
1053         return dest;
1054 }
1055
1056 /**
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.
1060  *
1061  * @param array the array to sort
1062  *
1063  * @returns the array sorted
1064  */
1065 struct json_object *wrap_json_sort(struct json_object *array)
1066 {
1067         if (json_object_is_type(array, json_type_array))
1068                 json_object_array_sort(array, (int(*)(const void*, const void*))wrap_json_cmp);
1069
1070         return array;
1071 }
1072
1073 /**
1074  * Returns a json array of the sorted keys of 'object' or null if 'object' has no keys.
1075  *
1076  * @param object the object whose keys are to be returned
1077  *
1078  * @return either NULL is 'object' isn't an object or a sorted array of the key's strings.
1079  */
1080 struct json_object *wrap_json_keys(struct json_object *object)
1081 {
1082         struct json_object *r;
1083         struct json_object_iterator it, end;
1084         if (!json_object_is_type(object, json_type_object))
1085                 r = NULL;
1086         else {
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);
1093                 }
1094                 wrap_json_sort(r);
1095         }
1096         return r;
1097 }
1098
1099 /**
1100  * Internal comparison of 'x' with 'y'
1101  *
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
1106  *
1107  * @return an integer indicating the computed result. Refer to
1108  * the table below for meaning of the returned value.
1109  *
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
1116  *
1117  *
1118  * if 'x' is found, respectively, to be less  than,  to match,
1119  * or be greater than 'y'. This is valid when 'sort'
1120  */
1121 static int jcmp(struct json_object *x, struct json_object *y, int inc, int sort)
1122 {
1123         double dx, dy;
1124         int64_t ix, iy;
1125         const char *sx, *sy;
1126         enum json_type tx, ty;
1127         int r, nx, ny, i;
1128         struct json_object_iterator it, end;
1129         struct json_object *jx, *jy;
1130
1131         /* check equality of pointers */
1132         if (x == y)
1133                 return 0;
1134
1135         /* get the types */
1136         tx = json_object_get_type(x);
1137         ty = json_object_get_type(y);
1138         r = (int)tx - (int)ty;
1139         if (r)
1140                 return r;
1141
1142         /* compare following the type */
1143         switch (tx) {
1144         default:
1145         case json_type_null:
1146                 break;
1147
1148         case json_type_boolean:
1149                 r = (int)json_object_get_boolean(x)
1150                         - (int)json_object_get_boolean(y);
1151                 break;
1152
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;
1157                 break;
1158
1159         case json_type_int:
1160                 ix = json_object_get_int64(x);
1161                 iy = json_object_get_int64(y);
1162                 r = ix < iy ? -1 : ix > iy;
1163                 break;
1164
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);
1170                 r = nx - ny;
1171                 if (r > 0 && inc)
1172                         r = 0;
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);
1178                         } else if (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);
1184                         } else
1185                                 r = 1;
1186                 }
1187                 break;
1188
1189         case json_type_array:
1190                 nx = (int)json_object_array_length(x);
1191                 ny = (int)json_object_array_length(y);
1192                 r = nx - ny;
1193                 if (r > 0 && inc)
1194                         r = 0;
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);
1199                 }
1200                 break;
1201
1202         case json_type_string:
1203                 sx = json_object_get_string(x);
1204                 sy = json_object_get_string(y);
1205                 r = strcmp(sx, sy);
1206                 break;
1207         }
1208         return r;
1209 }
1210
1211 /**
1212  * Compares 'x' with 'y'
1213  *
1214  * @param x first object to compare
1215  * @param y second object to compare
1216  *
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'.
1220  */
1221 int wrap_json_cmp(struct json_object *x, struct json_object *y)
1222 {
1223         return jcmp(x, y, 0, 1);
1224 }
1225
1226 /**
1227  * Searchs wether 'x' equals 'y'
1228  *
1229  * @param x first object to compare
1230  * @param y second object to compare
1231  *
1232  * @return an integer equal to zero when 'x' != 'y' or 1 when 'x' == 'y'.
1233  */
1234 int wrap_json_equal(struct json_object *x, struct json_object *y)
1235 {
1236         return !jcmp(x, y, 0, 0);
1237 }
1238
1239 /**
1240  * Searchs wether 'x' contains 'y'
1241  *
1242  * @param x first object to compare
1243  * @param y second object to compare
1244  *
1245  * @return an integer equal to 1 when 'y' is a subset of 'x' or zero otherwise
1246  */
1247 int wrap_json_contains(struct json_object *x, struct json_object *y)
1248 {
1249         return !jcmp(x, y, 1, 0);
1250 }
1251
1252 #if defined(WRAP_JSON_TEST)
1253 #include <stdio.h>
1254 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
1255 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
1256 #endif
1257 #define j2t(o) json_object_to_json_string_ext((o), JSON_C_TO_STRING_NOSLASHESCAPE)
1258
1259 void tclone(struct json_object *object)
1260 {
1261         struct json_object *o;
1262
1263         o = wrap_json_clone(object);
1264         if (!wrap_json_equal(object, o))
1265                 printf("ERROR in clone or equal: %s VERSUS %s\n", j2t(object), j2t(o));
1266         json_object_put(o);
1267
1268         o = wrap_json_clone_deep(object);
1269         if (!wrap_json_equal(object, o))
1270                 printf("ERROR in clone_deep or equal: %s VERSUS %s\n", j2t(object), j2t(o));
1271         json_object_put(o);
1272 }
1273
1274 void p(const char *desc, ...)
1275 {
1276         int rc;
1277         va_list args;
1278         struct json_object *result;
1279
1280         va_start(args, desc);
1281         rc = wrap_json_vpack(&result, desc, args);
1282         va_end(args);
1283         if (!rc)
1284                 printf("  SUCCESS %s\n\n", j2t(result));
1285         else
1286                 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         tclone(result);
1288         json_object_put(result);
1289 }
1290
1291 const char *xs[10];
1292 int *xi[10];
1293 int64_t *xI[10];
1294 double *xf[10];
1295 struct json_object *xo[10];
1296 size_t xz[10];
1297 uint8_t *xy[10];
1298
1299 void u(const char *value, const char *desc, ...)
1300 {
1301         unsigned m, k;
1302         int rc;
1303         va_list args;
1304         struct json_object *object, *o;
1305
1306         memset(xs, 0, sizeof xs);
1307         memset(xi, 0, sizeof xi);
1308         memset(xI, 0, sizeof xI);
1309         memset(xf, 0, sizeof xf);
1310         memset(xo, 0, sizeof xo);
1311         memset(xy, 0, sizeof xy);
1312         memset(xz, 0, sizeof xz);
1313         object = json_tokener_parse(value);
1314         va_start(args, desc);
1315         rc = wrap_json_vunpack(object, desc, args);
1316         va_end(args);
1317         if (rc)
1318                 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));
1319         else {
1320                 value = NULL;
1321                 printf("  SUCCESS");
1322                 va_start(args, desc);
1323                 k = m = 0;
1324                 while(*desc) {
1325                         switch(*desc) {
1326                         case '{': m = (m << 1) | 1; k = 1; break;
1327                         case '}': m = m >> 1; k = m&1; break;
1328                         case '[': m = m << 1; k = 0; break;
1329                         case ']': m = m >> 1; k = m&1; break;
1330                         case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
1331                         case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
1332                         case 'n': printf(" n"); k = m&1; break;
1333                         case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
1334                         case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
1335                         case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
1336                         case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
1337                         case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
1338                         case 'o': printf(" o:%s", j2t(*va_arg(args, struct json_object**))); k = m&1; break;
1339                         case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", j2t(o)); json_object_put(o); k = m&1; break;
1340                         case 'y':
1341                         case 'Y': {
1342                                 uint8_t *p = *va_arg(args, uint8_t**);
1343                                 size_t s = *va_arg(args, size_t*);
1344                                 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
1345                                 k ^= m&1;
1346                                 break;
1347                                 }
1348                         default: break;
1349                         }
1350                         desc++;
1351                 }
1352                 va_end(args);
1353                 printf("\n\n");
1354         }
1355         tclone(object);
1356         json_object_put(object);
1357 }
1358
1359 void c(const char *sx, const char *sy, int e, int c)
1360 {
1361         int re, rc;
1362         struct json_object *jx, *jy;
1363
1364         jx = json_tokener_parse(sx);
1365         jy = json_tokener_parse(sy);
1366
1367         re = wrap_json_cmp(jx, jy);
1368         rc = wrap_json_contains(jx, jy);
1369
1370         printf("compare(%s)(%s)\n", sx, sy);
1371         printf("   -> %d / %d\n", re, rc);
1372
1373         if (!re != !!e)
1374                 printf("  ERROR should be %s\n", e ? "equal" : "different");
1375         if (!rc != !c)
1376                 printf("  ERROR should %scontain\n", c ? "" : "not ");
1377
1378         printf("\n");
1379 }
1380
1381 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
1382 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
1383
1384 int main()
1385 {
1386         char buffer[4] = {'t', 'e', 's', 't'};
1387
1388         P("n");
1389         P("b", 1);
1390         P("b", 0);
1391         P("i", 1);
1392         P("I", (uint64_t)0x123456789abcdef);
1393         P("f", 3.14);
1394         P("s", "test");
1395         P("s?", "test");
1396         P("s?", NULL);
1397         P("s#", "test asdf", 4);
1398         P("s%", "test asdf", (size_t)4);
1399         P("s#", buffer, 4);
1400         P("s%", buffer, (size_t)4);
1401         P("s++", "te", "st", "ing");
1402         P("s#+#+", "test", 1, "test", 2, "test");
1403         P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
1404         P("{}", 1.0);
1405         P("[]", 1.0);
1406         P("o", json_object_new_int(1));
1407         P("o?", json_object_new_int(1));
1408         P("o?", NULL);
1409         P("O", json_object_new_int(1));
1410         P("O?", json_object_new_int(1));
1411         P("O?", NULL);
1412         P("{s:[]}", "foo");
1413         P("{s+#+: []}", "foo", "barbar", 3, "baz");
1414         P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
1415         P("{s:**}", "a", NULL);
1416         P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
1417         P("[i,i,i]", 0, 1, 2);
1418         P("[s,o,O]", NULL, NULL, NULL);
1419         P("[**]", NULL);
1420         P("[s*,o*,O*]", NULL, NULL, NULL);
1421         P(" s ", "test");
1422         P("[ ]");
1423         P("[ i , i,  i ] ", 1, 2, 3);
1424         P("{\n\n1");
1425         P("[}");
1426         P("{]");
1427         P("[");
1428         P("{");
1429         P("[i]a", 42);
1430         P("ia", 42);
1431         P("s", NULL);
1432         P("+", NULL);
1433         P(NULL);
1434         P("{s:i}", NULL, 1);
1435         P("{ {}: s }", "foo");
1436         P("{ s: {},  s:[ii{} }", "foo", "bar", 12, 13);
1437         P("[[[[[   [[[[[  [[[[ }]]]] ]]]] ]]]]]");
1438         P("y", "???????hello>>>>>>>", (size_t)19);
1439         P("Y", "???????hello>>>>>>>", (size_t)19);
1440         P("{sy?}", "foo", "hi", (size_t)2);
1441         P("{sy?}", "foo", NULL, 0);
1442         P("{sy*}", "foo", "hi", (size_t)2);
1443         P("{sy*}", "foo", NULL, 0);
1444
1445         U("true", "b", &xi[0]);
1446         U("false", "b", &xi[0]);
1447         U("null", "n");
1448         U("42", "i", &xi[0]);
1449         U("123456789", "I", &xI[0]);
1450         U("3.14", "f", &xf[0]);
1451         U("12345", "F", &xf[0]);
1452         U("3.14", "F", &xf[0]);
1453         U("\"foo\"", "s", &xs[0]);
1454         U("\"foo\"", "s%", &xs[0], &xz[0]);
1455         U("{}", "{}");
1456         U("[]", "[]");
1457         U("{}", "o", &xo[0]);
1458         U("{}", "O", &xo[0]);
1459         U("{\"foo\":42}", "{si}", "foo", &xi[0]);
1460         U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
1461         U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
1462         U("42", "z");
1463         U("null", "[i]");
1464         U("[]", "[}");
1465         U("{}", "{]");
1466         U("[]", "[");
1467         U("{}", "{");
1468         U("[42]", "[i]a", &xi[0]);
1469         U("42", "ia", &xi[0]);
1470         U("[]", NULL);
1471         U("\"foo\"", "s", NULL);
1472         U("42", "s", NULL);
1473         U("42", "n");
1474         U("42", "b", NULL);
1475         U("42", "f", NULL);
1476         U("42", "[i]", NULL);
1477         U("42", "{si}", "foo", NULL);
1478         U("\"foo\"", "n");
1479         U("\"foo\"", "b", NULL);
1480         U("\"foo\"", "i", NULL);
1481         U("\"foo\"", "I", NULL);
1482         U("\"foo\"", "f", NULL);
1483         U("\"foo\"", "F", NULL);
1484         U("true", "s", NULL);
1485         U("true", "n");
1486         U("true", "i", NULL);
1487         U("true", "I", NULL);
1488         U("true", "f", NULL);
1489         U("true", "F", NULL);
1490         U("[42]", "[ii]", &xi[0], &xi[1]);
1491         U("{\"foo\":42}", "{si}", NULL, &xi[0]);
1492         U("{\"foo\":42}", "{si}", "baz", &xi[0]);
1493         U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
1494         U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
1495         U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
1496         U("[1,2,3]", "[ii*]", &xi[0], &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}", "{sisi!}", "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("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
1503         U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
1504         U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
1505         U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
1506         U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
1507         U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
1508         U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
1509         U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
1510         U("{}", "{s?i}", "foo", &xi[0]);
1511         U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
1512         U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1513         U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1514         U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
1515         U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1516         U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1517         U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
1518         U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1519         U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
1520
1521         U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
1522         U("\"\"", "y", &xy[0], &xz[0]);
1523         U("null", "y", &xy[0], &xz[0]);
1524         U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1525         U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
1526         U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
1527
1528         c("null", "null", 1, 1);
1529         c("true", "true", 1, 1);
1530         c("false", "false", 1, 1);
1531         c("1", "1", 1, 1);
1532         c("1.0", "1.0", 1, 1);
1533         c("\"\"", "\"\"", 1, 1);
1534         c("\"hi\"", "\"hi\"", 1, 1);
1535         c("{}", "{}", 1, 1);
1536         c("{\"a\":true,\"b\":false}", "{\"b\":false,\"a\":true}", 1, 1);
1537         c("[]", "[]", 1, 1);
1538         c("[1,true,null]", "[1,true,null]", 1, 1);
1539
1540         c("null", "true", 0, 0);
1541         c("null", "false", 0, 0);
1542         c("0", "1", 0, 0);
1543         c("1", "0", 0, 0);
1544         c("0", "true", 0, 0);
1545         c("0", "false", 0, 0);
1546         c("0", "null", 0, 0);
1547
1548         c("\"hi\"", "\"hello\"", 0, 0);
1549         c("\"hello\"", "\"hi\"", 0, 0);
1550
1551         c("{}", "null", 0, 0);
1552         c("{}", "true", 0, 0);
1553         c("{}", "1", 0, 0);
1554         c("{}", "1.0", 0, 0);
1555         c("{}", "[]", 0, 0);
1556         c("{}", "\"x\"", 0, 0);
1557
1558         c("[1,true,null]", "[1,true]", 0, 1);
1559         c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1);
1560         c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0);
1561         c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0);
1562         return 0;
1563 }
1564
1565 #endif
1566
1567 #if 0
1568
1569
1570     /* Unpack the same item twice */
1571     j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
1572     if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
1573         fail("json_unpack object with strict validation failed");
1574     {
1575         const char *possible_errors[] = {
1576             "2 object item(s) left unpacked: baz, quux",
1577             "2 object item(s) left unpacked: quux, baz"
1578         };
1579         check_errors(possible_errors, 2, "<validation>", 1, 10, 10);
1580     }
1581     json_decref(j);
1582
1583 #endif