-/**
- * Search for a reference of type "#/a/b/c" in the
- * parsed JSON object (root)
- */
-struct json_object *search(const char *path)
-{
- char *d;
- struct json_object *i;
-
- /* does it match #/ at the beginning? */
- if (path[0] != '#' || (path[0] && path[1] != '/'))
- return NULL;
-
- /* search from root to target */
- i = root;
- d = strdupa(path+2);
- d = strtok(d, "/");
- while(i && d) {
- if (!json_object_object_get_ex(i, d, &i))
- return NULL;
- d = strtok(NULL, "/");
- }
- return i;
-}
-
-/**
- * Expands the node designated by path and returns its expanded form
- */
-struct json_object *expand_$ref(struct path path)
-{
- struct path *p;
- struct json_object *o, *x;
- int n, i;
- struct json_object_iterator ji, jn;
-
- /* expansion depends of the type of the node */
- switch (json_object_get_type(path.object)) {
- case json_type_object:
- /* for object, look if it contains a property "$ref" */
- if (json_object_object_get_ex(path.object, "$ref", &o)) {
- /* yes, reference, try to substitute its target */
- if (!json_object_is_type(o, json_type_string)) {
- fprintf(stderr, "found a $ref not being string. Is: %s\n", json_object_get_string(o));
- exit(1);
- }
- x = search(json_object_get_string(o));
- if (!x) {
- fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(o));
- exit(1);
- }
- p = &path;
- while(p) {
- if (x == p->object) {
- fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(o));
- exit(1);
- }
- p = p->upper;
- }
- /* cool found, return a new instance of the target */
- return json_object_get(x);
- }
- /* no, expand the values */
- ji = json_object_iter_begin(path.object);
- jn = json_object_iter_end(path.object);
- while (!json_object_iter_equal(&ji, &jn)) {
- o = json_object_iter_peek_value(&ji);
- x = expand_$ref((struct path){ .object = o, .upper = &path });
- if (x != o)
- json_object_object_add(path.object, json_object_iter_peek_name(&ji), x);
- json_object_iter_next(&ji);
- }
- break;
- case json_type_array:
- /* expand the values of arrays */
- i = 0;
- n = (int)json_object_array_length(path.object);
- while (i != n) {
- o = json_object_array_get_idx(path.object, i);
- x = expand_$ref((struct path){ .object = o, .upper = &path });
- if (x != o)
- json_object_array_put_idx(path.object, i, x);
- i++;
- }
- break;
- default:
- /* otherwise no expansion */
- break;
- }