2 * Copyright (C) 2016-2019 "IoT.bzh"
3 * Author José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 * This simple program expands the object { "$ref": "#/path/to/a/target" }
25 * "b": { "$ref": "#/type/a" }
29 * will be exapanded to
38 * Invocation: program [file|-]...
40 * without arguments, it reads the input.
47 #include <json-c/json.h>
53 * records path to the expanded node
57 struct json_object *object; /**< node being expanded */
58 const struct path *upper; /**< link to upper expanded nodes */
62 * Returns the top object
64 static inline struct json_object *top(const struct path *path)
72 * Expands the node designated by path and returns its expanded form
74 static struct json_object *expand(const struct path *upper)
77 struct json_object *object, *x;
79 struct json_object_iterator ji, jn;
81 /* expansion depends of the type of the node */
83 object = upper->object;
84 switch (json_object_get_type(object)) {
85 case json_type_object:
86 /* for object, look if it contains a property "$ref" */
87 if (json_object_object_get_ex(object, "$ref", &here.object)) {
88 /* check that "$ref" value is a string */
89 if (!json_object_is_type(here.object, json_type_string)) {
90 fprintf(stderr, "found a $ref not being string. Is: %s\n", json_object_get_string(here.object));
93 /* yes, reference, try to substitute its target */
94 i = search$ref(top(upper), json_object_get_string(here.object), &x);
96 fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(here.object));
99 /* check not recursive */
102 if (x == upper->object) {
103 fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(here.object));
106 upper = upper->upper;
108 /* found. return a new instance of the target */
111 /* no, expand the values */
112 ji = json_object_iter_begin(object);
113 jn = json_object_iter_end(object);
114 while (!json_object_iter_equal(&ji, &jn)) {
115 here.object = json_object_iter_peek_value(&ji);
117 if (x != here.object)
118 json_object_object_add(object, json_object_iter_peek_name(&ji), json_object_get(x));
119 json_object_iter_next(&ji);
122 case json_type_array:
123 /* expand the values of arrays */
125 n = (int)json_object_array_length(object);
127 here.object = json_object_array_get_idx(object, i);
129 if (x != here.object)
130 json_object_array_put_idx(object, i, json_object_get(x));
135 /* otherwise no expansion */
138 /* return the given node */
142 struct json_object *exp$refs(struct json_object *root)
144 struct path top = { .object = root, .upper = NULL };
148 static int is_tree(struct json_object *object, const struct path *upper)
152 struct json_object_iterator ji, jn;
154 switch (json_object_get_type(object)) {
155 case json_type_object:
156 case json_type_array:
157 /* check recursive */
160 if (upper->object == object)
162 upper = upper->upper;
164 here.object = object;
165 switch (json_object_get_type(object)) {
166 case json_type_object:
167 ji = json_object_iter_begin(object);
168 jn = json_object_iter_end(object);
169 while (!json_object_iter_equal(&ji, &jn)) {
170 if (!is_tree(json_object_iter_peek_value(&ji), &here))
172 json_object_iter_next(&ji);
175 case json_type_array:
177 n = (int)json_object_array_length(object);
179 if (!is_tree(json_object_array_get_idx(object, i), &here))
194 int exp$refs_is_tree(struct json_object *root)
196 return is_tree(root, NULL);