devtools: Refactoring, bug fix, new IDL
[src/app-framework-binder.git] / src / devtools / exprefs.c
index 4459f2c..cfd3941 100644 (file)
 #define _GNU_SOURCE
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 
 #include <json-c/json.h>
 
+#include "getref.h"
+#include "exprefs.h"
+
 /**
  * records path to the expanded node
  */
 struct path
 {
        struct json_object *object;     /**< node being expanded */
-       struct path *upper;             /**< link to upper expanded nodes */
+       const struct path *upper;       /**< link to upper expanded nodes */
 };
 
 /**
- * root of the JSON being parsed
- */
-struct json_object *root;
-
-/**
- * Search for a reference of type "#/a/b/c" int the
- * parsed JSON object
+ * Returns the top object
  */
-struct json_object *search(const char *path)
+static inline struct json_object *top(const struct path *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;
+       while (path->upper)
+               path = path->upper;
+       return path->object;
 }
 
 /**
  * Expands the node designated by path and returns its expanded form
  */
-struct json_object *expand(struct path path)
+static struct json_object *expand(const struct path *upper)
 {
-       struct path *p;
-       struct json_object *o, *x;
+       struct path here;
+       struct json_object *object, *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)) {
+       here.upper = upper;
+       object = upper->object;
+       switch (json_object_get_type(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));
+               if (json_object_object_get_ex(object, "$ref", &here.object)) {
+                       /* check that "$ref" value is a string */
+                       if (!json_object_is_type(here.object, json_type_string)) {
+                               fprintf(stderr, "found a $ref not being string. Is: %s\n", json_object_get_string(here.object));
                                exit(1);
                        }
-                       x = search(json_object_get_string(o));
-                       if (!x) {
-                               fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(o));
+                       /* yes, reference, try to substitute its target */
+                       i = search$ref(top(upper), json_object_get_string(here.object), &x);
+                       if (!i) {
+                               fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(here.object));
                                exit(1);
                        }
-                       p = &path;
-                       while(p) {
-                               if (x == p->object) {
-                                       fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(o));
+                       /* check not recursive */
+                       upper = &here;
+                       while(upper) {
+                               if (x == upper->object) {
+                                       fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(here.object));
                                        exit(1);
                                }
-                               p = p->upper;
+                               upper = upper->upper;
                        }
-                       /* cool found, return a new instance of the target */
-                       return json_object_get(x);
+                       /* found. return a new instance of the target */
+                       return x;
                }
                /* no, expand the values */
-               ji = json_object_iter_begin(path.object);
-               jn = json_object_iter_end(path.object);
+               ji = json_object_iter_begin(object);
+               jn = json_object_iter_end(object);
                while (!json_object_iter_equal(&ji, &jn)) {
-                       o = json_object_iter_peek_value(&ji);
-                       x = expand((struct path){ .object = o, .upper = &path });
-                       if (x != o)
-                               json_object_object_add(path.object, json_object_iter_peek_name(&ji), x);
+                       here.object = json_object_iter_peek_value(&ji);
+                       x = expand(&here);
+                       if (x != here.object)
+                               json_object_object_add(object, json_object_iter_peek_name(&ji), json_object_get(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);
+               n = (int)json_object_array_length(object);
                while (i != n) {
-                       o = json_object_array_get_idx(path.object, i);
-                       x = expand((struct path){ .object = o, .upper = &path });
-                       if (x != o)
-                               json_object_array_put_idx(path.object, i, x);
+                       here.object = json_object_array_get_idx(object, i);
+                       x = expand(&here);
+                       if (x != here.object)
+                               json_object_array_put_idx(object, i, json_object_get(x));
                        i++;
                }
                break;
@@ -150,49 +136,62 @@ struct json_object *expand(struct path path)
                break;
        }
        /* return the given node */
-       return path.object;
+       return object;
 }
 
-/**
- * process a file and prints its expansion on stdout
- */
-void process(char *filename)
+struct json_object *exp$refs(struct json_object *root)
 {
-       /* translate - */
-       if (!strcmp(filename, "-"))
-               filename = "/dev/stdin";
+       struct path top = { .object = root, .upper = NULL };
+       return expand(&top);
+}
 
-       /* check access */
-       if (access(filename, R_OK)) {
-               fprintf(stderr, "can't access file %s\n", filename);
-               exit(1);
-       }
+static int is_tree(struct json_object *object, const struct path *upper)
+{
+       struct path here;
+       int n, i;
+       struct json_object_iterator ji, jn;
 
-       /* read the file */
-       root = json_object_from_file(filename);
-       if (!root) {
-               fprintf(stderr, "reading file %s produced null\n", filename);
-               exit(1);
+       switch (json_object_get_type(object)) {
+       case json_type_object:
+       case json_type_array:
+               /* check recursive */
+               here.upper = upper;
+               while (upper) {
+                       if (upper->object == object)
+                               return 0;
+                       upper = upper->upper;
+               }
+               here.object = object;
+               switch (json_object_get_type(object)) {
+               case json_type_object:
+                       ji = json_object_iter_begin(object);
+                       jn = json_object_iter_end(object);
+                       while (!json_object_iter_equal(&ji, &jn)) {
+                               if (!is_tree(json_object_iter_peek_value(&ji), &here))
+                                       return 0;
+                               json_object_iter_next(&ji);
+                       }
+                       break;
+               case json_type_array:
+                       i = 0;
+                       n = (int)json_object_array_length(object);
+                       while (i != n) {
+                               if (!is_tree(json_object_array_get_idx(object, i), &here))
+                                       return 0;
+                               i++;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
        }
-
-       /* expand */
-       root = expand((struct path){ .object = root, .upper = NULL });
-
-       /* print the result */
-       json_object_to_file_ext ("/dev/stdout", root, JSON_C_TO_STRING_PRETTY);
-
-       /* clean up */
-       json_object_put(root);
+       return 1;
 }
 
-/** process the list of files or stdin if none */
-int main(int ac, char **av)
+int exp$refs_is_tree(struct json_object *root)
 {
-       if (!*++av)
-               process("-");
-       else {
-               do { process(*av); } while(*++av);
-       }
-       return 0;
+       return is_tree(root, NULL);
 }
-