in progress
[src/app-framework-main.git] / src / appfwk.c
index 6dc7182..0ede96a 100644 (file)
 #include <unistd.h>
 #include <sys/types.h>
 
-#include <wgt.h>
+#include <json.h>
 
-struct stringset {
-       int count;
-       char **strings;
+#include <wgt-info.h>
+
+struct afapps {
+       struct json_object *pubarr;
+       struct json_object *direct;
+       struct json_object *byapp;
 };
 
 struct appfwk {
        int refcount;
-       struct stringset paths;
+       int nrroots;
+       char **roots;
+       struct afapps applications;
 };
 
 struct appfwk *appfwk_create()
@@ -43,8 +47,11 @@ struct appfwk *appfwk_create()
                errno = ENOMEM;
        else {
                appfwk->refcount = 1;
-               appfwk->paths.count = 0;
-               appfwk->paths.strings = NULL;
+               appfwk->nrroots = 0;
+               appfwk->roots = NULL;
+               appfwk->applications.pubarr = NULL;
+               appfwk->applications.direct = NULL;
+               appfwk->applications.byapp = NULL;
        }
        return appfwk;
 }
@@ -59,8 +66,9 @@ void appfwk_unref(struct appfwk *appfwk)
 {
        assert(appfwk);
        if (!--appfwk->refcount) {
-               while (appfwk->paths.count)
-                       free(appfwk->paths.strings[--appfwk->paths.count]);
+               while (appfwk->nrroots)
+                       free(appfwk->roots[--appfwk->nrroots]);
+               free(appfwk->roots);
                free(appfwk);
        }
 }
@@ -69,19 +77,23 @@ int appfwk_add_root(struct appfwk *appfwk, const char *path)
 {
        int i, n;
        char *r, **roots;
+
        assert(appfwk);
+
+       /* don't depend on the cwd and unique name */
        r = realpath(path, NULL);
        if (!r)
                return -1;
 
        /* avoiding duplications */
-       n = appfwk->paths.count;
-       roots = appfwk->paths.strings;
-       for (i = 0 ; i < n ; i++)
+       n = appfwk->nrroots;
+       roots = appfwk->roots;
+       for (i = 0 ; i < n ; i++) {
                if (!strcmp(r, roots[i])) {
                        free(r);
                        return 0;
                }
+       }
 
        /* add */
        roots = realloc(roots, (n + 1) * sizeof(roots[0]));
@@ -91,92 +103,165 @@ int appfwk_add_root(struct appfwk *appfwk, const char *path)
                return -1;
        }
        roots[n++] = r;
-       appfwk->paths.strings = roots;
-       appfwk->paths.count = n;
+       appfwk->roots = roots;
+       appfwk->nrroots = n;
        return 0;
 }
 
-struct aea {
-       char *path;
-       char *appver;
-       char *ver;
-       const char *root;
-       const char *appid;
-       const char *version;
-       int (*callback)(struct wgt *wgt, void *data);
-       void *data;
-};
-
-struct appfwk_enumerate_applications_context {
-       const char *dirpath;
-       const char *appid;
-       const char *version;
-       
-       void *data;
-};
+static int json_add(struct json_object *obj, const char *key, struct json_object *val)
+{
+       json_object_object_add(obj, key, val);
+       return 0;
+}
 
-inline int testd(int dirfd, struct dirent *e)
+static int json_add_str(struct json_object *obj, const char *key, const char *val)
 {
-       return e->d_name[0] != '.' || (e->d_name[1] && (e->d_name[1] != '.' || e->d_name[2]));
+       struct json_object *str = json_object_new_string (val ? val : "");
+       return str ? json_add(obj, key, str) : -1;
 }
 
-#include <stdio.h>
-static int aea3(int dirfd, struct aea *aea)
+static int json_add_int(struct json_object *obj, const char *key, int val)
 {
-       printf("aea3 %s *** %s *** %s\n", aea->path, aea->appver, aea->ver);
-       return 0;
+       struct json_object *v = json_object_new_int (val);
+       return v ? json_add(obj, key, v) : -1;
 }
 
-static int aea2(int dirfd, struct aea *aea)
+static int addapp(struct afapps *apps, const char *path)
 {
-       DIR *dir;
-       int rc, fd;
-       struct dirent entry, *e;
+       struct wgt_info *info;
+       const struct wgt_desc *desc;
+       const struct wgt_desc_feature *feat;
+       struct json_object *priv = NULL, *pub, *bya, *plugs, *str;
+       char *appid, *end;
 
-       dir = fdopendir(dirfd);
-       if (!dir)
-               return -1;
+       /* connect to the widget */
+       info = wgt_info_createat(AT_FDCWD, path, 0, 1, 0);
+       if (info == NULL)
+               goto error;
+       desc = wgt_info_desc(info);
 
-       aea->version = entry.d_name;
+       /* create the application id */
+       appid = alloca(2 + strlen(desc->id) + strlen(desc->version));
+       end = stpcpy(appid, desc->id);
+       *end++ = '@';
+       strcpy(end, desc->version);
 
-       rc = readdir_r(dir, &entry, &e);
-       while (!rc && e) {
-               if (testd(dirfd, &entry)) {
-                       fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
-                       if (fd >= 0) {
-                               strcpy(aea->ver, entry.d_name);
-                               rc = aea3(fd, aea);                     
-                               close(fd);
+       /* create the application structure */
+       priv = json_object_new_object();
+       if (!priv)
+               goto error2;
+
+       pub = json_object_new_object();
+       if (!priv)
+               goto error2;
+
+       if (json_add(priv, "public", pub)) {
+               json_object_put(pub);
+               goto error2;
+       }
+
+       plugs = json_object_new_array();
+       if (!priv)
+               goto error2;
+
+       if (json_add(priv, "plugins", plugs)) {
+               json_object_put(plugs);
+               goto error2;
+       }
+
+       if(json_add_str(pub, "id", appid)
+       || json_add_str(priv, "id", desc->id)
+       || json_add_str(pub, "version", desc->version)
+       || json_add_str(priv, "path", path)
+       || json_add_int(pub, "width", desc->width)
+       || json_add_int(pub, "height", desc->height)
+       || json_add_str(pub, "name", desc->name)
+       || json_add_str(pub, "description", desc->description)
+       || json_add_str(pub, "shortname", desc->name_short)
+       || json_add_str(pub, "author", desc->author))
+               goto error2;
+
+       feat = desc->features;
+       while (feat) {
+               static const char prefix[] = FWK_PREFIX_PLUGIN;
+               if (!memcmp(feat->name, prefix, sizeof prefix - 1)) {
+                       str = json_object_new_string (feat->name + sizeof prefix - 1);
+                       if (str == NULL)
+                               goto error2;
+                       if (json_object_array_add(plugs, str)) {
+                               json_object_put(str);
+                               goto error2;
                        }
-               }       
-               rc = readdir_r(dir, &entry, &e);
+               }
+               feat = feat->next;
        }
-       closedir(dir);
-       return rc;
+
+       /* record the application structure */
+       if (!json_object_object_get_ex(apps->byapp, desc->id, &bya)) {
+               bya = json_object_new_object();
+               if (!bya)
+                       goto error2;
+               if (json_add(apps->byapp, desc->id, bya)) {
+                       json_object_put(bya);
+                       goto error2;
+               }
+       }
+
+       if (json_add(apps->direct, appid, priv))
+               goto error2;
+       json_object_get(priv);
+
+       if (json_add(bya, desc->version, priv)) {
+               json_object_put(priv);
+               goto error2;
+       }
+
+       if (json_object_array_add(apps->pubarr, pub))
+               goto error2;
+
+       wgt_info_unref(info);
+       return 0;
+
+error2:
+       json_object_put(priv);
+       wgt_info_unref(info);
+error:
+       return -1;
 }
 
-static int aea1(int dirfd, struct aea *aea)
+struct enumdata {
+       char path[PATH_MAX];
+       int length;
+       struct afapps apps;
+};
+
+static int enumentries(struct enumdata *data, int (*callto)(struct enumdata *))
 {
        DIR *dir;
-       int rc, fd;
+       int rc;
+       char *beg, *end;
        struct dirent entry, *e;
 
-       dir = fdopendir(dirfd);
+       /* opens the directory */
+       dir = opendir(data->path);
        if (!dir)
                return -1;
 
-       aea->appid = entry.d_name;
+       /* prepare appending entry names */
+       beg = data->path + data->length;
+       *beg++ = '/';
 
+       /* enumerate entries */
        rc = readdir_r(dir, &entry, &e);
        while (!rc && e) {
-               if (testd(dirfd, &entry)) {
-                       fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
-                       if (fd >= 0) {
-                               aea->ver = stpcpy(aea->appver, entry.d_name);
-                               *aea->ver++ = '/';
-                               rc = aea2(fd, aea);                     
-                               close(fd);
-                       }
+               if (entry.d_name[0] != '.' || (entry.d_name[1] && (entry.d_name[1] != '.' || entry.d_name[2]))) {
+                       /* prepare callto */
+                       end = stpcpy(beg, entry.d_name);
+                       data->length = end - data->path;
+                       /* call the function */
+                       rc = callto(data);
+                       if (rc)
+                               break;
                }       
                rc = readdir_r(dir, &entry, &e);
        }
@@ -184,41 +269,77 @@ static int aea1(int dirfd, struct aea *aea)
        return rc;
 }
 
-int appfwk_enumerate_applications(struct appfwk *appfwk, int (*callback)(struct wgt *wgt, void *data), void *data)
+static int recordapp(struct enumdata *data)
 {
-       int rc, iroot, nroots;
-       char **roots;
-       int fd;
-       char buffer[PATH_MAX];
-       struct aea aea;
-
-       aea.callback = callback;
-       aea.data = data;
-       aea.path = buffer;
-
-       nroots = appfwk->paths.count;
-       roots = appfwk->paths.strings;
-       for (iroot = 0 ; iroot < nroots ; iroot++) {
-               aea.root = roots[iroot];
-               fd = openat(AT_FDCWD, aea.root, O_DIRECTORY|O_RDONLY);
-               if (fd >= 0) {
-                       aea.appver = stpcpy(buffer, aea.root);
-                       *aea.appver++ = '/';
-                       rc = aea1(fd, &aea);
-                       close(fd);
-               }
+       return addapp(&data->apps, data->path);
+}
+
+/* enumerate the versions */
+static int enumvers(struct enumdata *data)
+{
+       int rc = enumentries(data, recordapp);
+       return !rc || errno != ENOTDIR ? 0 : rc;
+}
+
+/* regenerate the list of applications */
+int appfwk_update_applications(struct appfwk *af)
+{
+       int rc, iroot;
+       struct enumdata edata;
+       struct afapps oldapps;
+
+       /* create the result */
+       edata.apps.pubarr = json_object_new_array();
+       edata.apps.direct = json_object_new_object();
+       edata.apps.byapp = json_object_new_object();
+       if (edata.apps.pubarr == NULL || edata.apps.direct == NULL || edata.apps.byapp == NULL) {
+               errno = ENOMEM;
+               goto error;
        }
+       /* for each root */
+       for (iroot = 0 ; iroot < af->nrroots ; iroot++) {
+               edata.length = stpcpy(edata.path, af->roots[iroot]) - edata.path;
+               assert(edata.length < sizeof edata.path);
+               /* enumerate the applications */
+               rc = enumentries(&edata, enumvers);
+               if (rc)
+                       goto error;
+       }
+       /* commit the result */
+       oldapps = af->applications;
+       af->applications = edata.apps;
+       json_object_put(oldapps.pubarr);
+       json_object_put(oldapps.direct);
+       json_object_put(oldapps.byapp);
        return 0;
+
+error:
+       json_object_put(edata.apps.pubarr);
+       json_object_put(edata.apps.direct);
+       json_object_put(edata.apps.byapp);
+       return -1;
+}
+
+int appfwk_ensure_applications(struct appfwk *af)
+{
+       return af->applications.pubarr ? 0 : appfwk_update_applications(af);
+}
+
+/* regenerate the list of applications */
+struct json_object *appfwk_application_list(struct appfwk *af)
+{
+       return appfwk_ensure_applications(af) ? NULL : af->applications.pubarr;
+}
+
+#include <stdio.h>
+int main()
+{
+struct appfwk *af = appfwk_create();
+appfwk_add_root(af,FWK_APP_DIR);
+appfwk_update_applications(af);
+printf("array = %s\n", json_object_to_json_string_ext(af->applications.pubarr, 3));
+printf("direct = %s\n", json_object_to_json_string_ext(af->applications.direct, 3));
+printf("byapp = %s\n", json_object_to_json_string_ext(af->applications.byapp, 3));
+return 0;
 }
-/*
-       struct wgt *wgt;
-               wgt = wgt_create();
-               if (!wgt)
-                       return -1;
-               wgt_unref(wgt);
-
-       rfd = AT_FDCWD;
-       if (pathname) {
-               rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
-*/