X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgt-json.c;h=0fda364ab62f6d161dc08abdef60944d64d05137;hb=a123bb31906ef03ff813559aee426282416d729d;hp=cc5ee93311c306261a3551d32cce30cc702d74aa;hpb=1d4de11a907e41c06063a2cd5028dc4101690f50;p=src%2Fapp-framework-main.git diff --git a/src/wgt-json.c b/src/wgt-json.c index cc5ee93..0fda364 100644 --- a/src/wgt-json.c +++ b/src/wgt-json.c @@ -1,5 +1,5 @@ /* - Copyright 2015, 2016, 2017 IoT.bzh + Copyright (C) 2015-2020 IoT.bzh author: José Bollo @@ -36,78 +36,88 @@ #include "verbose.h" /* -{ - permissions: { - dict: { - ID: { name: ID, level: LEVEL, index: INDEX }, - ... - }, - list: [ - { name: ID, level: LEVEL, index: 0 }, - ... - } - }, - targets: [ - { name: ID, level: LEVEL, index: 0 }, - ... - ] - } -} -*/ - + * This describes an action to be performed for a parameter of name. + * The action takes a not null json object, the param matched and a given closure. + */ struct paramaction { - const char *name; - int (*action)(struct json_object *obj, const struct wgt_desc_param *param, void *closure); - void *closure; + const char *name; /* the name of the parameter trigerring the action or null (mark end) */ + int (*action)(struct json_object *obj, const struct wgt_desc_param *param, void *closure); /* the action to perform or null (no action) */ + void *closure; /* the closure to pass to the action */ }; -/* apply params */ -static int apply_params(struct json_object *obj, const struct wgt_desc_param *param, const struct paramaction *actions) +/* + * Apply the first matching 'actions' to each of the given 'params' and for the given json 'obj' (that shouldn't be null) + * Returns 0 in case of success or -1 on error. + */ +static int apply_params(struct json_object *obj, const struct wgt_desc_param *params, const struct paramaction *actions) { int rc; const struct paramaction *a; - if (!obj) + if (!obj) { + /* obj can't be null */ + errno = EINVAL; rc = -1; - else { + } else { + /* iterate over the params */ rc = 0; - while(param) { - for (a = actions ; a->name && strcmp(a->name, param->name) ; a++); - if (a->action && a->action(obj, param, a->closure) < 0) + while(params) { + /* search the first match */ + for (a = actions ; a->name && strcmp(a->name, params->name) ; a++); + /* invoke the action (or not if null) */ + if (a->action && a->action(obj, params, a->closure) < 0) rc = -1; - param = param->next; + /* next */ + params = params->next; } } return rc; } -static int get_array(struct json_object **result, struct json_object *obj, const char *key, int create) +/* + * Get the array at the 'mkey' in 'obj'. 'create' it if needed and requested. + * Returns 0 in case of success or a negative number otherwise. + */ +static int get_array(struct json_object **result, struct json_object *obj, const char *mkey, int create) { - int rc = j_enter_m(&obj, &key, 1); + /* enter the multiple key */ + int rc = j_enter_m(&obj, &mkey, create); if (rc < 0) + /* parent keys doesn't exist */ *result = NULL; - else if (!json_object_object_get_ex(obj, key, result)) { + else if (!json_object_object_get_ex(obj, mkey, result)) { + /* parent keys exist but not the final key */ if (!create) { *result = NULL; rc = -ENOENT; } else { - if (!(*result = j_add_new_array(obj, key))) + /* try to create the array */ + if (!(*result = j_add_new_array(obj, mkey))) rc = -ENOMEM; } } return rc; } -/* get the param of 'name' for the feature 'feat' */ +/* + * Returns the target name (#target) of the feature 'feat'. + * Returns 'defval' if not found or NULL is duplicated + */ static const char *get_target_name(const struct wgt_desc_feature *feat, const char *defval) { const struct wgt_desc_param *param = feat->params; + + /* search the parameter of name '#target' */ while (param && strcmp(param->name, string_sharp_target)) param = param->next; if (param) { + /* found, get itsd value */ defval = param->value; + + /* check it is defined only one time */ + /* TODO: validate it in an other place? */ param = param->next; while (param) { if (!strcmp(param->name, string_sharp_target)) { @@ -120,7 +130,10 @@ static const char *get_target_name(const struct wgt_desc_feature *feat, const ch return defval; } -/* get the target */ +/* + * Search in 'array' the first object having a field of name 'key' and of string value 'val' + * Returns NULL if not found + */ static struct json_object *get_array_item_by_key(struct json_object *array, const char *key, const char *val) { struct json_object *result, *k; @@ -137,13 +150,20 @@ static struct json_object *get_array_item_by_key(struct json_object *array, cons return NULL; } +/* + * Get or create from the array 'targets' the structure for the target of 'name' + * Should create if 'create' is not not otherwise just get. + * Returns zero on success or a errno negative code + */ static int get_target(struct json_object **result, struct json_object *targets, const char *name, int create) { int rc; struct json_object *t; + /* search in targets a structure of target name */ t = get_array_item_by_key(targets, string_sharp_target, name); if (t) { + /* found */ if (!create) rc = 0; else { @@ -152,10 +172,12 @@ static int get_target(struct json_object **result, struct json_object *targets, rc = -EEXIST; } } else { + /* not found */ if (!create) { ERROR("target name not found: %s", name); rc = -ENOENT; } else { + /* create a new value */ t = j_add_new_object(targets, NULL); if (t && j_add_string(t, string_sharp_target, name)) rc = 0; @@ -170,41 +192,50 @@ static int get_target(struct json_object **result, struct json_object *targets, return rc; } -static int make_target(struct json_object *targets, const struct wgt_desc_feature *feat) +/* create the target value for the feature */ +static int create_target(struct json_object *targets, const struct wgt_desc_feature *feat) { const char *id; struct json_object *target; + /* search within the feature the parameter naming the target */ id = get_target_name(feat, NULL); if (id == NULL) { - ERROR("target of feature %s is missing or repeated", feat->name); + ERROR("target of feature %s is %s", feat->name, get_target_name(feat, feat->name) ? "repeated" : "missing"); return -EINVAL; } + /* create the target */ return get_target(&target, targets, id, 1); } -static int add_icon(struct json_object *target, const char *src, int width, int height) +/* + * Adds icon data to the target + */ +static int add_icon(struct json_object *target, const struct wgt_desc_icon *icon) { int rc; - struct json_object *icon, *array; + struct json_object *object, *array; rc = get_array(&array, target, string_icon, 1); if (rc >= 0) { - icon = json_object_new_object(); - if(!icon - || !j_add_string(icon, string_src, src) - || (width > 0 && !j_add_integer(icon, string_width, width)) - || (height > 0 && !j_add_integer(icon, string_height, height)) - || !j_add(array, NULL, icon)) { - json_object_put(icon); + object = json_object_new_object(); + if(!object + || !j_add_string(object, string_src, icon->src) + || (icon->width > 0 && !j_add_integer(object, string_width, icon->width)) + || (icon->height > 0 && !j_add_integer(object, string_height, icon->height)) + || !j_add(array, NULL, object)) { + json_object_put(object); rc = -ENOMEM; } } return rc; } -static int make_main_target(struct json_object *targets, const struct wgt_desc *desc) +/* + * Creates the main target + */ +static int create_main_target(struct json_object *targets, const struct wgt_desc *desc) { int rc; struct wgt_desc_icon *icon; @@ -213,13 +244,14 @@ static int make_main_target(struct json_object *targets, const struct wgt_desc * /* create the target 'main' */ rc = get_target(&target, targets, string_main, 1); - /* adds icons if any */ + /* add icons if any */ icon = desc->icons; while (rc >= 0 && icon) { - rc = add_icon(target, icon->src, icon->width, icon->height); + rc = add_icon(target, icon); icon = icon->next; } + /* add content */ if (rc >= 0) rc = j_add_many_strings_m(target, "content.src", desc->content_src, @@ -227,9 +259,12 @@ static int make_main_target(struct json_object *targets, const struct wgt_desc * "content.encoding", desc->content_encoding, NULL) ? 0 : -errno; + /* add other info */ if (rc >= 0) if((desc->width && !j_add_integer(target, string_width, desc->width)) - || (desc->height && !j_add_integer(target, string_height, desc->height))) + || (desc->height && !j_add_integer(target, string_height, desc->height)) + || (desc->viewmodes && !j_add_string(target, string_viewmodes, desc->viewmodes)) + || (desc->defaultlocale && !j_add_string(target, string_defaultlocale, desc->defaultlocale))) rc = -ENOMEM; return rc; @@ -237,6 +272,9 @@ static int make_main_target(struct json_object *targets, const struct wgt_desc * /***********************************************************************************************************/ +/* + * translate a param to an object { "name": name, "value": value } + */ static struct json_object *object_of_param(const struct wgt_desc_param *param) { struct json_object *value; @@ -251,22 +289,30 @@ static struct json_object *object_of_param(const struct wgt_desc_param *param) return NULL; } +/* + * Add the field of mkey 'param'.name with 'param'.value to the object 'obj' + */ static int add_param_simple(struct json_object *obj, const struct wgt_desc_param *param, void *closure) { return j_add_string_m(obj, param->name, param->value); } +/* add a param object to an array of param objects */ static int add_param_array(struct json_object *obj, const struct wgt_desc_param *param, void *closure) { + const char *array_name = closure; struct json_object *array, *value; - if (!closure) + /* the array is either pointed by 'closure=array_name' or the given 'obj' */ + if (!array_name) array = obj; - else if (!json_object_object_get_ex(obj, closure, &array)) { - array = j_add_new_array(obj, closure); + else if (!json_object_object_get_ex(obj, array_name, &array)) { + array = j_add_new_array(obj, array_name); if (!array) return -ENOMEM; } + + /* append the param object */ value = object_of_param(param); if (value && j_add(array, NULL, value)) return 0; @@ -275,17 +321,22 @@ static int add_param_array(struct json_object *obj, const struct wgt_desc_param return -ENOMEM; } +/* add a param object to an object of param objects, indexed by the param name */ static int add_param_object(struct json_object *obj, const struct wgt_desc_param *param, void *closure) { + const char *object_name = closure; struct json_object *object, *value; - if (!closure) + /* the object is either pointed by 'object_name=closure' or the given 'obj' */ + if (!object_name) object = obj; - else if (!json_object_object_get_ex(obj, closure, &object)) { - object = j_add_new_object(obj, closure); + else if (!json_object_object_get_ex(obj, object_name, &object)) { + object = j_add_new_object(obj, object_name); if (!object) return -ENOMEM; } + + /* append the param object */ value = object_of_param(param); if (value && j_add(object, param->name, value)) return 0; @@ -294,6 +345,7 @@ static int add_param_object(struct json_object *obj, const struct wgt_desc_param return -ENOMEM; } +/* Retrieve within 'targets' the target of the feature 'feat' and applies 'actions' to it */ static int add_targeted_params(struct json_object *targets, const struct wgt_desc_feature *feat, struct paramaction actions[]) { int rc; @@ -305,34 +357,67 @@ static int add_targeted_params(struct json_object *targets, const struct wgt_des return rc < 0 ? rc : apply_params(obj, feat->params, actions); } -static int add_provided(struct json_object *targets, const struct wgt_desc_feature *feat) +/* Treats the feature "provided_unit" */ +static int add_provided_unit(struct json_object *targets, const struct wgt_desc_feature *feat) { static struct paramaction actions[] = { - { .name = string_sharp_target, .action = NULL, .closure = NULL }, + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ { .name = NULL, .action = add_param_simple, .closure = NULL } }; return add_targeted_params(targets, feat, actions); } +/* Treats the feature "provided_api" */ +static int add_provided_api(struct json_object *targets, const struct wgt_desc_feature *feat) +{ + static struct paramaction actions[] = { + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ + { .name = NULL, .action = add_param_array, .closure = (void*)string_provided_api } + }; + return add_targeted_params(targets, feat, actions); +} + +/* Treats the feature "required_api" */ +static int add_required_api(struct json_object *targets, const struct wgt_desc_feature *feat) +{ + static struct paramaction actions[] = { + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ + { .name = NULL, .action = add_param_array, .closure = (void*)string_required_api } + }; + return add_targeted_params(targets, feat, actions); +} + +/* Treats the feature "provided_binding" */ +static int add_provided_binding(struct json_object *targets, const struct wgt_desc_feature *feat) +{ + static struct paramaction actions[] = { + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* TODO: should be an error! */ + { .name = NULL, .action = add_param_array, .closure = (void*)string_provided_binding } + }; + return add_targeted_params(targets, feat, actions); +} + +/* Treats the feature "required_binding" */ static int add_required_binding(struct json_object *targets, const struct wgt_desc_feature *feat) { static struct paramaction actions[] = { - { .name = string_sharp_target, .action = NULL, .closure = NULL }, + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ { .name = NULL, .action = add_param_array, .closure = (void*)string_required_binding } }; return add_targeted_params(targets, feat, actions); } - +/* Treats the feature "required_permission" */ static int add_required_permission(struct json_object *targets, const struct wgt_desc_feature *feat) { static struct paramaction actions[] = { - { .name = string_sharp_target, .action = NULL, .closure = NULL }, + { .name = string_sharp_target, .action = NULL, .closure = NULL }, /* skip #target */ { .name = NULL, .action = add_param_object, .closure = (void*)string_required_permission } }; return add_targeted_params(targets, feat, actions); } +/* Treats the feature "defined_permission" */ static int add_defined_permission(struct json_object *defperm, const struct wgt_desc_feature *feat) { static struct paramaction actions[] = { @@ -343,6 +428,9 @@ static int add_defined_permission(struct json_object *defperm, const struct wgt_ /***********************************************************************************************************/ +/* + * Create the json object from 'desc' + */ static struct json_object *to_json(const struct wgt_desc *desc) { size_t prefixlen; @@ -359,7 +447,7 @@ static struct json_object *to_json(const struct wgt_desc *desc) goto error; /* first pass: declarations */ - rc = make_main_target(targets, desc); + rc = create_main_target(targets, desc); prefixlen = strlen(string_AGL_widget_prefix); for (feat = desc->features ; feat ; feat = feat->next) { featname = feat->name; @@ -370,9 +458,8 @@ static struct json_object *to_json(const struct wgt_desc *desc) rc = -EINVAL; } featname += prefixlen; - if (!strcmp(featname, string_provided_binding) - || !strcmp(featname, string_provided_application)) { - rc2 = make_target(targets, feat); + if (!strcmp(featname, string_provided_unit)) { + rc2 = create_target(targets, feat); if (rc2 < 0 && !rc) rc = rc2; } @@ -386,25 +473,30 @@ static struct json_object *to_json(const struct wgt_desc *desc) featname += prefixlen; if (!strcmp(featname, string_defined_permission)) { rc2 = add_defined_permission(permissions, feat); - if (rc2 < 0 && !rc) - rc = rc2; } - else if (!strcmp(featname, string_provided_application) - || !strcmp(featname, string_provided_binding)) { - rc2 = add_provided(targets, feat); - if (rc2 < 0 && !rc) - rc = rc2; + else if (!strcmp(featname, string_provided_unit)) { + rc2 = add_provided_unit(targets, feat); + } + else if (!strcmp(featname, string_provided_api)) { + rc2 = add_provided_api(targets, feat); + } + else if (!strcmp(featname, string_provided_binding)) { + rc2 = add_provided_binding(targets, feat); + } + else if (!strcmp(featname, string_required_api)) { + rc2 = add_required_api(targets, feat); } else if (!strcmp(featname, string_required_binding)) { rc2 = add_required_binding(targets, feat); - if (rc2 < 0 && !rc) - rc = rc2; } else if (!strcmp(featname, string_required_permission)) { rc2 = add_required_permission(targets, feat); - if (rc2 < 0 && !rc) - rc = rc2; + } else { + /* gently ignore other features */ + rc2 = 0; } + if (rc2 < 0 && !rc) + rc = rc2; } } @@ -427,23 +519,22 @@ static struct json_object *to_json(const struct wgt_desc *desc) if (rc2 < 0 && !rc) rc = rc2; - /* */ - - /* */ - if (!rc) { + /* returns the result if there is no error*/ + if (!rc) return result; - } error: json_object_put(result); return NULL; } +/* get the json_object of the wgt_info 'info' or NULL if error */ struct json_object *wgt_info_to_json(struct wgt_info *info) { return to_json(wgt_info_desc(info)); } +/* get the json_object of the 'wgt' or NULL if error */ struct json_object *wgt_to_json(struct wgt *wgt) { struct json_object *result; @@ -459,6 +550,7 @@ struct json_object *wgt_to_json(struct wgt *wgt) return result; } +/* get the json_object of the widget of 'path' relative to 'dfd' or NULL if error */ struct json_object *wgt_path_at_to_json(int dfd, const char *path) { struct json_object *result; @@ -474,6 +566,7 @@ struct json_object *wgt_path_at_to_json(int dfd, const char *path) return result; } +/* get the json_object of the widget of 'path' or NULL if error */ struct json_object *wgt_path_to_json(const char *path) { return wgt_path_at_to_json(AT_FDCWD, path);