> Subject: [ndctl PATCH 5/7] util/parse-configs: add a key/value search helper
> 
> Add a new config query type called CONFIG_SEARCH_SECTION, which searches
> all loaded config files based on a query criteria of: specified section name,
> specified key/value pair within that section, and can return other key/values 
> from
> the section that matched the search criteria.
> 
> This allows for multiple named subsections, where a subsection name is of the
> type: '[section subsection]'.
> 
> Cc: QI Fuli <[email protected]>
> Cc: Dan Williams <[email protected]>
> Signed-off-by: Vishal Verma <[email protected]>
> ---
>  util/parse-configs.h | 15 +++++++++++++  util/parse-configs.c | 51
> ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 66 insertions(+)
> 
> diff --git a/util/parse-configs.h b/util/parse-configs.h index 
> 491aebb..6dcc01c
> 100644
> --- a/util/parse-configs.h
> +++ b/util/parse-configs.h
> @@ -9,6 +9,7 @@
> 
>  enum parse_conf_type {
>       CONFIG_STRING,
> +     CONFIG_SEARCH_SECTION,
>       CONFIG_END,
>       MONITOR_CALLBACK,
>  };
> @@ -20,6 +21,10 @@ typedef int parse_conf_cb(const struct config *, const char
> *config_file);
> 
>  struct config {
>       enum parse_conf_type type;
> +     const char *section;
> +     const char *search_key;
> +     const char *search_val;
> +     const char *get_key;
>       const char *key;
>       void *value;
>       void *defval;
> @@ -31,6 +36,16 @@ struct config {
>  #define CONF_END() { .type = CONFIG_END }  #define CONF_STR(k,v,d) \
>       { .type = CONFIG_STRING, .key = (k), .value = check_vtype(v, const char
> **), .defval = (d) }
> +#define CONF_SEARCH(s, sk, sv, gk, v, d)     \
> +{                                            \
> +     .type = CONFIG_SEARCH_SECTION,          \
> +     .section = (s),                         \
> +     .search_key = (sk),                     \
> +     .search_val = (sv),                     \
> +     .get_key = (gk),                        \
> +     .value = check_vtype(v, const char **), \
> +     .defval = (d)                           \
> +}
>  #define CONF_MONITOR(k,f) \
>       { .type = MONITOR_CALLBACK, .key = (k), .callback = (f)}
> 
> diff --git a/util/parse-configs.c b/util/parse-configs.c index 
> 72c4913..8eabe3d
> 100644
> --- a/util/parse-configs.c
> +++ b/util/parse-configs.c
> @@ -38,6 +38,54 @@ static void set_str_val(const char **value, const char 
> *val)
>       *value = strbuf_detach(&buf, NULL);
>  }
> 
> +static const char *search_section_kv(dictionary *d, const struct config
> +*c) {
> +     int i;
> +
> +     for (i = 0; i < iniparser_getnsec(d); i++) {
> +             const char *cur_sec_full = iniparser_getsecname(d, i);
> +             char *cur_sec = strdup(cur_sec_full);
> +             const char *search_val, *ret_val;
> +             const char *delim = " \t\n\r";
> +             char *save, *cur, *query;
> +
> +             if (!cur_sec)
> +                     return NULL;
> +             if (!c->section || !c->search_key || !c->search_val
> || !c->get_key) {
> +                     fprintf(stderr, "warning: malformed config query,
> skipping\n");
> +                     return NULL;
> +             }
> +
> +             cur = strtok_r(cur_sec, delim, &save);
> +             if ((cur == NULL) || (strcmp(cur, c->section) != 0))
> +                     goto out_sec;
> +
> +             if (asprintf(&query, "%s:%s", cur_sec_full, c->search_key) < 0)
> +                     goto out_sec;
> +             search_val = iniparser_getstring(d, query, NULL);
> +             if (!search_val)
> +                     goto out_query;
> +             if (strcmp(search_val, c->search_val) != 0)
> +                     goto out_query;
> +
> +             /* we're now in a matching section */
> +             free(query);
> +             if (asprintf(&query, "%s:%s", cur_sec_full, c->get_key) < 0)
> +                     goto out_sec;
> +             ret_val = iniparser_getstring(d, query, NULL);
> +             free(query);
> +             free(cur_sec);
> +             return ret_val;
> +
> +out_query:
> +             free(query);
> +out_sec:
> +             free(cur_sec);
> +     }
> +
> +     return NULL;
> +}
> +
>  static int parse_config_file(const char *config_file,
>                       const struct config *configs)
>  {
> @@ -54,6 +102,9 @@ static int parse_config_file(const char *config_file,
>                                       iniparser_getstring(dic,
>                                       configs->key, configs->defval));
>                       break;
> +             case CONFIG_SEARCH_SECTION:
> +                     set_str_val((const char **)configs->value,
> +                                     search_section_kv(dic, configs));
>               case MONITOR_CALLBACK:
>               case CONFIG_END:
>                       break;
> --
> 2.31.1

Thank you very much.
This looks good to me.

QI


Reply via email to