2 Copyright (C) 2016, 2017 "IoT.bzh"
4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
21 #include "wrap-json.h"
28 wrap_json_error_null_object,
29 wrap_json_error_truncated,
30 wrap_json_error_internal_error,
31 wrap_json_error_out_of_memory,
32 wrap_json_error_invalid_character,
33 wrap_json_error_too_long,
34 wrap_json_error_too_deep,
35 wrap_json_error_null_spec,
36 wrap_json_error_null_key,
37 wrap_json_error_null_string,
38 wrap_json_error_out_of_range,
39 wrap_json_error_incomplete,
40 wrap_json_error_missfit_type,
41 wrap_json_error_key_not_found,
42 _wrap_json_error_count_
45 static const char ignore_all[] = " \t\n\r,:";
46 static const char pack_accept_arr[] = "][{snbiIfoO";
47 static const char pack_accept_key[] = "s}";
48 #define pack_accept_any (&pack_accept_arr[1])
50 static const char unpack_accept_arr[] = "*!][{snbiIfFoO";
51 static const char unpack_accept_key[] = "*!s}";
52 #define unpack_accept_any (&unpack_accept_arr[3])
54 static const char *pack_errors[_wrap_json_error_count_] =
56 [wrap_json_error_none] = "unknown error",
57 [wrap_json_error_null_object] = "null object",
58 [wrap_json_error_truncated] = "truncated",
59 [wrap_json_error_internal_error] = "internal error",
60 [wrap_json_error_out_of_memory] = "out of memory",
61 [wrap_json_error_invalid_character] = "invalid character",
62 [wrap_json_error_too_long] = "too long",
63 [wrap_json_error_too_deep] = "too deep",
64 [wrap_json_error_null_spec] = "spec is NULL",
65 [wrap_json_error_null_key] = "key is NULL",
66 [wrap_json_error_null_string] = "string is NULL",
67 [wrap_json_error_out_of_range] = "array too small",
68 [wrap_json_error_incomplete] = "incomplete container",
69 [wrap_json_error_missfit_type] = "missfit of type",
70 [wrap_json_error_key_not_found] = "key not found"
73 int wrap_json_get_error_position(int rc)
80 int wrap_json_get_error_code(int rc)
87 const char *wrap_json_get_error_string(int rc)
89 rc = wrap_json_get_error_code(rc);
90 if (rc >= sizeof pack_errors / sizeof *pack_errors)
92 return pack_errors[rc];
97 static inline const char *skip(const char *d)
99 while (*d && strchr(ignore_all, *d))
104 int wrap_json_vpack(struct json_object **result, const char *desc, va_list args)
106 /* TODO: the case of structs with key being single char should be optimized */
107 int nstr, notnull, nullable, rc;
113 struct { const char *str; size_t sz; } strs[STRCOUNT];
114 struct { struct json_object *cont, *key; const char *acc; char type; } stack[STACKCOUNT], *top;
115 struct json_object *obj;
122 top->acc = pack_accept_any;
132 if (!strchr(top->acc, c))
133 goto invalid_character;
142 strs[nstr].str = va_arg(args, const char*);
150 case '%': strs[nstr].sz = va_arg(args, size_t); d = skip(++d); break;
151 case '#': strs[nstr].sz = (size_t)va_arg(args, int); d = skip(++d); break;
152 default: strs[nstr].sz = strs[nstr].str ? strlen(strs[nstr].str) : 0; break;
154 sz += strs[nstr++].sz;
161 if (nstr >= STRCOUNT)
177 dsz -= strs[nstr].sz;
178 memcpy(&s[dsz], strs[nstr].str, strs[nstr].sz);
180 obj = json_object_new_string_len(s, (int)sz);
192 obj = json_object_new_boolean(va_arg(args, int));
197 obj = json_object_new_int(va_arg(args, int));
202 obj = json_object_new_int64(va_arg(args, int64_t));
207 obj = json_object_new_double(va_arg(args, double));
213 obj = va_arg(args, struct json_object*);
216 else if (*d != '*' && !obj)
219 json_object_get(obj);
223 if (++top >= &stack[STACKCOUNT])
228 top->acc = pack_accept_arr;
229 top->cont = json_object_new_array();
232 top->acc = pack_accept_key;
233 top->cont = json_object_new_object();
240 if (c != top->type || top <= stack)
243 if (*d == '*' && !(c == '}' ? json_object_object_length(obj) : json_object_array_length(obj))) {
244 json_object_put(obj);
256 goto invalid_character;
260 if (obj || *d != '*')
261 json_object_array_add(top->cont, obj);
269 top->acc = pack_accept_any;
273 if (obj || *d != '*')
274 json_object_object_add(top->cont, json_object_get_string(top->key), obj);
277 json_object_put(top->key);
279 top->acc = pack_accept_key;
288 rc = wrap_json_error_null_object;
291 rc = wrap_json_error_truncated;
294 rc = wrap_json_error_internal_error;
297 rc = wrap_json_error_out_of_memory;
300 rc = wrap_json_error_invalid_character;
303 rc = wrap_json_error_too_long;
306 rc = wrap_json_error_too_deep;
309 rc = wrap_json_error_null_spec;
312 rc = wrap_json_error_null_key;
315 rc = wrap_json_error_null_string;
319 json_object_put(top->key);
320 json_object_put(top->cont);
321 } while (--top >= stack);
323 rc = rc | (int)((d - desc) << 4);
327 int wrap_json_pack(struct json_object **result, const char *desc, ...)
332 va_start(args, desc);
333 rc = wrap_json_vpack(result, desc, args);
338 static int vunpack(struct json_object *object, const char *desc, va_list args, int store)
340 int rc = 0, optionnal, ignore;
341 char c, xacc[2] = { 0, 0 };
343 const char *d, *fit = NULL;
344 const char *key = NULL;
345 const char **ps = NULL;
350 struct { struct json_object *parent; const char *acc; int index, count; char type; } stack[STACKCOUNT], *top;
351 struct json_object *obj;
352 struct json_object **po;
357 acc = unpack_accept_any;
369 goto invalid_character;
373 if (xacc[0] == '}') {
375 key = va_arg(args, const char *);
387 if (json_object_object_get_ex(top->parent, key, &obj)) {
399 acc = unpack_accept_any;
404 ps = va_arg(args, const char **);
406 if (!json_object_is_type(obj, json_type_string))
409 *ps = json_object_get_string(obj);
414 pz = va_arg(args, size_t *);
416 *pz = (size_t)json_object_get_string_len(obj);
421 if (!ignore && !json_object_is_type(obj, json_type_null))
426 pi = va_arg(args, int *);
429 if (!json_object_is_type(obj, json_type_boolean))
432 *pi = json_object_get_boolean(obj);
437 pi = va_arg(args, int *);
440 if (!json_object_is_type(obj, json_type_int))
443 *pi = json_object_get_int(obj);
448 pI = va_arg(args, int64_t *);
451 if (!json_object_is_type(obj, json_type_int))
454 *pI = json_object_get_int64(obj);
460 pf = va_arg(args, double *);
463 if (!(json_object_is_type(obj, json_type_double) || (c == 'F' && json_object_is_type(obj, json_type_int))))
466 *pf = json_object_get_double(obj);
472 po = va_arg(args, struct json_object **);
475 obj = json_object_get(obj);
485 else if (++top >= &stack[STACKCOUNT])
496 if (!json_object_is_type(obj, json_type_array))
498 top->count = json_object_array_length(obj);
501 acc = unpack_accept_arr;
504 if (!json_object_is_type(obj, json_type_object))
506 top->count = json_object_object_length(obj);
509 acc = unpack_accept_key;
515 if (!top || c != xacc[0])
519 top = top == stack ? NULL : top - 1;
525 goto invalid_character;
526 if (!ignore && top->index != top->count)
540 goto invalid_character;
544 key = strchr(unpack_accept_arr, *d);
545 if (key && key >= unpack_accept_any) {
546 if (top->index >= top->count)
548 obj = json_object_array_get_idx(top->parent, top->index++);
553 acc = unpack_accept_key;
563 rc = wrap_json_error_truncated;
566 rc = wrap_json_error_internal_error;
569 rc = wrap_json_error_invalid_character;
572 rc = wrap_json_error_too_deep;
575 rc = wrap_json_error_null_spec;
578 rc = wrap_json_error_null_key;
581 rc = wrap_json_error_out_of_range;
584 rc = wrap_json_error_incomplete;
587 rc = wrap_json_error_missfit_type;
590 rc = wrap_json_error_key_not_found;
595 rc = rc | (int)((d - desc) << 4);
599 int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
601 return vunpack(object, desc, args, 0);
604 int wrap_json_check(struct json_object *object, const char *desc, ...)
609 va_start(args, desc);
610 rc = vunpack(object, desc, args, 0);
615 int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
617 return !vunpack(object, desc, args, 0);
620 int wrap_json_match(struct json_object *object, const char *desc, ...)
625 va_start(args, desc);
626 rc = vunpack(object, desc, args, 0);
631 int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
633 return vunpack(object, desc, args, 1);
636 int wrap_json_unpack(struct json_object *object, const char *desc, ...)
641 va_start(args, desc);
642 rc = vunpack(object, desc, args, 1);
647 static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
649 struct json_object_iterator it = json_object_iter_begin(object);
650 struct json_object_iterator end = json_object_iter_end(object);
651 while (!json_object_iter_equal(&it, &end)) {
652 callback(closure, json_object_iter_peek_value(&it), json_object_iter_peek_name(&it));
653 json_object_iter_next(&it);
657 static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
659 int n = json_object_array_length(object);
662 callback(closure, json_object_array_get_idx(object, i++));
665 void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
667 if (json_object_is_type(object, json_type_array))
668 array_for_all(object, callback, closure);
670 callback(closure, object);
673 void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
675 if (json_object_is_type(object, json_type_array))
676 array_for_all(object, callback, closure);
679 void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
681 if (json_object_is_type(object, json_type_object))
682 object_for_all(object, callback, closure);
685 void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
687 if (json_object_is_type(object, json_type_object))
688 object_for_all(object, callback, closure);
690 callback(closure, object, NULL);
693 void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
697 else if (json_object_is_type(object, json_type_object))
698 object_for_all(object, callback, closure);
699 else if (!json_object_is_type(object, json_type_array))
700 callback(closure, object, NULL);
702 int n = json_object_array_length(object);
705 callback(closure, json_object_array_get_idx(object, i++), NULL);
709 #if defined(WRAP_JSON_TEST)
712 void p(const char *desc, ...)
716 struct json_object *result;
718 va_start(args, desc);
719 rc = wrap_json_vpack(&result, desc, args);
722 printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
724 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));
725 json_object_put(result);
732 struct json_object *xo[10];
735 void u(const char *value, const char *desc, ...)
740 struct json_object *obj, *o;
742 memset(xs, 0, sizeof xs);
743 memset(xi, 0, sizeof xi);
744 memset(xI, 0, sizeof xI);
745 memset(xf, 0, sizeof xf);
746 memset(xo, 0, sizeof xo);
747 memset(xz, 0, sizeof xz);
748 obj = json_tokener_parse(value);
749 va_start(args, desc);
750 rc = wrap_json_vunpack(obj, desc, args);
753 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));
757 va_start(args, desc);
761 case '{': m = (m << 1) | 1; k = 1; break;
762 case '}': m = m >> 1; k = m&1; break;
763 case '[': m = m << 1; k = 0; break;
764 case ']': m = m >> 1; k = m&1; break;
765 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
766 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
767 case 'n': printf(" n"); k = m&1; break;
768 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
769 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
770 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
771 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
772 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
773 case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
774 case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", json_object_to_json_string(o)); json_object_put(o); k = m&1; break;
782 json_object_put(obj);
785 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
786 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
790 char buffer[4] = {'t', 'e', 's', 't'};
796 P("I", (uint64_t)0x123456789abcdef);
801 P("s#", "test asdf", 4);
802 P("s%", "test asdf", (size_t)4);
804 P("s%", buffer, (size_t)4);
805 P("s++", "te", "st", "ing");
806 P("s#+#+", "test", 1, "test", 2, "test");
807 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
810 P("o", json_object_new_int(1));
811 P("o?", json_object_new_int(1));
813 P("O", json_object_new_int(1));
814 P("O?", json_object_new_int(1));
817 P("{s+#+: []}", "foo", "barbar", 3, "baz");
818 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
819 P("{s:**}", "a", NULL);
820 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
821 P("[i,i,i]", 0, 1, 2);
822 P("[s,o,O]", NULL, NULL, NULL);
824 P("[s*,o*,O*]", NULL, NULL, NULL);
827 P("[ i , i, i ] ", 1, 2, 3);
839 P("{ {}: s }", "foo");
840 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
841 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
843 U("true", "b", &xi[0]);
844 U("false", "b", &xi[0]);
846 U("42", "i", &xi[0]);
847 U("123456789", "I", &xI[0]);
848 U("3.14", "f", &xf[0]);
849 U("12345", "F", &xf[0]);
850 U("3.14", "F", &xf[0]);
851 U("\"foo\"", "s", &xs[0]);
852 U("\"foo\"", "s%", &xs[0], &xz[0]);
855 U("{}", "o", &xo[0]);
856 U("{}", "O", &xo[0]);
857 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
858 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
859 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
866 U("[42]", "[i]a", &xi[0]);
867 U("42", "ia", &xi[0]);
869 U("\"foo\"", "s", NULL);
874 U("42", "[i]", NULL);
875 U("42", "{si}", "foo", NULL);
877 U("\"foo\"", "b", NULL);
878 U("\"foo\"", "i", NULL);
879 U("\"foo\"", "I", NULL);
880 U("\"foo\"", "f", NULL);
881 U("\"foo\"", "F", NULL);
882 U("true", "s", NULL);
884 U("true", "i", NULL);
885 U("true", "I", NULL);
886 U("true", "f", NULL);
887 U("true", "F", NULL);
888 U("[42]", "[ii]", &xi[0], &xi[1]);
889 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
890 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
891 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
892 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
893 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
894 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
895 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
896 U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
897 U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
898 U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
899 U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
900 U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
901 U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
902 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
903 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
904 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
905 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
906 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
907 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
908 U("{}", "{s?i}", "foo", &xi[0]);
909 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
910 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
911 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
912 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
913 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
914 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
915 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
916 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
917 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
926 /* Unpack the same item twice */
927 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
928 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
929 fail("json_unpack object with strict validation failed");
931 const char *possible_errors[] = {
932 "2 object item(s) left unpacked: baz, quux",
933 "2 object item(s) left unpacked: quux, baz"
935 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);