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)
539 goto invalid_character;
543 key = strchr(unpack_accept_arr, *d);
544 if (key && key >= unpack_accept_any) {
545 if (top->index >= top->count)
547 obj = json_object_array_get_idx(top->parent, top->index++);
552 acc = unpack_accept_key;
562 rc = wrap_json_error_truncated;
565 rc = wrap_json_error_internal_error;
568 rc = wrap_json_error_invalid_character;
571 rc = wrap_json_error_too_deep;
574 rc = wrap_json_error_null_spec;
577 rc = wrap_json_error_null_key;
580 rc = wrap_json_error_out_of_range;
583 rc = wrap_json_error_incomplete;
586 rc = wrap_json_error_missfit_type;
589 rc = wrap_json_error_key_not_found;
594 rc = rc | (int)((d - desc) << 4);
598 int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
600 return vunpack(object, desc, args, 0);
603 int wrap_json_check(struct json_object *object, const char *desc, ...)
608 va_start(args, desc);
609 rc = vunpack(object, desc, args, 0);
614 int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
616 return !vunpack(object, desc, args, 0);
619 int wrap_json_match(struct json_object *object, const char *desc, ...)
624 va_start(args, desc);
625 rc = vunpack(object, desc, args, 0);
630 int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
632 return vunpack(object, desc, args, 1);
635 int wrap_json_unpack(struct json_object *object, const char *desc, ...)
640 va_start(args, desc);
641 rc = vunpack(object, desc, args, 1);
646 static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
648 struct json_object_iterator it = json_object_iter_begin(object);
649 struct json_object_iterator end = json_object_iter_end(object);
650 while (!json_object_iter_equal(&it, &end)) {
651 callback(closure, json_object_iter_peek_value(&it), json_object_iter_peek_name(&it));
652 json_object_iter_next(&it);
656 static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
658 int n = json_object_array_length(object);
661 callback(closure, json_object_array_get_idx(object, i++));
664 void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
666 if (json_object_is_type(object, json_type_array))
667 array_for_all(object, callback, closure);
669 callback(closure, object);
672 void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
674 if (json_object_is_type(object, json_type_array))
675 array_for_all(object, callback, closure);
678 void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
680 if (json_object_is_type(object, json_type_object))
681 object_for_all(object, callback, closure);
684 void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
686 if (json_object_is_type(object, json_type_object))
687 object_for_all(object, callback, closure);
689 callback(closure, object, NULL);
692 void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
696 else if (json_object_is_type(object, json_type_object))
697 object_for_all(object, callback, closure);
698 else if (!json_object_is_type(object, json_type_array))
699 callback(closure, object, NULL);
701 int n = json_object_array_length(object);
704 callback(closure, json_object_array_get_idx(object, i++), NULL);
708 #if defined(WRAP_JSON_TEST)
711 void p(const char *desc, ...)
715 struct json_object *result;
717 va_start(args, desc);
718 rc = wrap_json_vpack(&result, desc, args);
721 printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
723 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));
724 json_object_put(result);
731 struct json_object *xo[10];
734 void u(const char *value, const char *desc, ...)
739 struct json_object *obj, *o;
741 memset(xs, 0, sizeof xs);
742 memset(xi, 0, sizeof xi);
743 memset(xI, 0, sizeof xI);
744 memset(xf, 0, sizeof xf);
745 memset(xo, 0, sizeof xo);
746 memset(xz, 0, sizeof xz);
747 obj = json_tokener_parse(value);
748 va_start(args, desc);
749 rc = wrap_json_vunpack(obj, desc, args);
752 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));
756 va_start(args, desc);
760 case '{': m = (m << 1) | 1; k = 1; break;
761 case '}': m = m >> 1; k = m&1; break;
762 case '[': m = m << 1; k = 0; break;
763 case ']': m = m >> 1; k = m&1; break;
764 case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
765 case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
766 case 'n': printf(" n"); k = m&1; break;
767 case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
768 case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
769 case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
770 case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
771 case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
772 case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
773 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;
781 json_object_put(obj);
784 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
785 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
789 char buffer[4] = {'t', 'e', 's', 't'};
795 P("I", (uint64_t)0x123456789abcdef);
800 P("s#", "test asdf", 4);
801 P("s%", "test asdf", (size_t)4);
803 P("s%", buffer, (size_t)4);
804 P("s++", "te", "st", "ing");
805 P("s#+#+", "test", 1, "test", 2, "test");
806 P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
809 P("o", json_object_new_int(1));
810 P("o?", json_object_new_int(1));
812 P("O", json_object_new_int(1));
813 P("O?", json_object_new_int(1));
816 P("{s+#+: []}", "foo", "barbar", 3, "baz");
817 P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
818 P("{s:**}", "a", NULL);
819 P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
820 P("[i,i,i]", 0, 1, 2);
821 P("[s,o,O]", NULL, NULL, NULL);
823 P("[s*,o*,O*]", NULL, NULL, NULL);
826 P("[ i , i, i ] ", 1, 2, 3);
838 P("{ {}: s }", "foo");
839 P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
840 P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
842 U("true", "b", &xi[0]);
843 U("false", "b", &xi[0]);
845 U("42", "i", &xi[0]);
846 U("123456789", "I", &xI[0]);
847 U("3.14", "f", &xf[0]);
848 U("12345", "F", &xf[0]);
849 U("3.14", "F", &xf[0]);
850 U("\"foo\"", "s", &xs[0]);
851 U("\"foo\"", "s%", &xs[0], &xz[0]);
854 U("{}", "o", &xo[0]);
855 U("{}", "O", &xo[0]);
856 U("{\"foo\":42}", "{si}", "foo", &xi[0]);
857 U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
858 U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
865 U("[42]", "[i]a", &xi[0]);
866 U("42", "ia", &xi[0]);
868 U("\"foo\"", "s", NULL);
873 U("42", "[i]", NULL);
874 U("42", "{si}", "foo", NULL);
876 U("\"foo\"", "b", NULL);
877 U("\"foo\"", "i", NULL);
878 U("\"foo\"", "I", NULL);
879 U("\"foo\"", "f", NULL);
880 U("\"foo\"", "F", NULL);
881 U("true", "s", NULL);
883 U("true", "i", NULL);
884 U("true", "I", NULL);
885 U("true", "f", NULL);
886 U("true", "F", NULL);
887 U("[42]", "[ii]", &xi[0], &xi[1]);
888 U("{\"foo\":42}", "{si}", NULL, &xi[0]);
889 U("{\"foo\":42}", "{si}", "baz", &xi[0]);
890 U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
891 U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
892 U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
893 U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
894 U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &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}", "{si}", "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("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
901 U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
902 U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
903 U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
904 U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
905 U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
906 U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
907 U("{}", "{s?i}", "foo", &xi[0]);
908 U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
909 U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
910 U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
911 U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
912 U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
913 U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
914 U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
915 U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
916 U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
925 /* Unpack the same item twice */
926 j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
927 if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
928 fail("json_unpack object with strict validation failed");
930 const char *possible_errors[] = {
931 "2 object item(s) left unpacked: baz, quux",
932 "2 object item(s) left unpacked: quux, baz"
934 check_errors(possible_errors, 2, "<validation>", 1, 10, 10);