diff --git a/librz/config/config.c b/librz/config/config.c index 06dc6ec71d..b4823b72f4 100644 --- a/librz/config/config.c +++ b/librz/config/config.c @@ -18,7 +18,7 @@ static void config_var_fini(RzConfigVar *var) { free(var->name); free(var->desc); - rz_list_free(var->options); + rz_set_s_free(var->options); if (RZ_CONFIG_VAR_HAS_FLAG(var->flags, RZ_CONFIG_VAR_FLAG_BIND)) { // if is bind, we do not own the value. return; @@ -26,8 +26,8 @@ static void config_var_fini(RzConfigVar *var) { if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_STR)) { free(var->value.string); - } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST)) { - rz_list_free(var->value.list); + } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET)) { + rz_set_s_free(var->value.set); } } @@ -61,30 +61,31 @@ static inline bool config_var_set_readonly(RzConfigVar *var, bool read_only) { return true; } -static bool config_var_args_to_list(va_list argp, RzList /**/ *list) { +static bool config_var_args_to_set(va_list argp, RzSetS *set) { const char *value = va_arg(argp, const char *); while (value) { - char *copy = rz_str_dup(value); - if (!copy || !rz_list_append(list, copy)) { - free(copy); - return false; - } + rz_set_s_add(set, value); value = va_arg(argp, const char *); } return true; } -RZ_IPI RZ_OWN RzList /**/ *rz_config_dup_list(RZ_NULLABLE const RzList /**/ *list) { - RzListIter *it; - const char *elem; - RzList *safe_list = rz_list_newf(free); - if (!safe_list) { +RZ_IPI RZ_OWN RzSetS *rz_config_dup_set(RZ_NULLABLE const RzSetS *set) { + RzSetS *safe_set = rz_set_s_new(HT_STR_DUP); + if (!safe_set) { return NULL; } - rz_list_foreach (list, it, elem) { - rz_list_append(safe_list, rz_str_dup(elem)); + if (!set) { + return safe_set; } - return safe_list; + + RzIterator *it = rz_set_s_as_iter(set); + const char **elem; + rz_iterator_foreach(it, elem) { + rz_set_s_add(safe_set, *elem); + } + rz_iterator_free(it); + return safe_set; } /** @@ -221,14 +222,14 @@ static inline bool config_init_var_string(RzConfigVar *var, const char *name, co return true; } -static inline bool config_init_var_list(RzConfigVar *var, const char *name, const char *desc, RZ_OWN RzList /**/ *value) { +static inline bool config_init_var_set(RzConfigVar *var, const char *name, const char *desc, RZ_OWN RzSetS *value) { var->name = rz_str_dup(name); - var->value.list = value; - if (!var->name || !var->value.list) { + var->value.set = value; + if (!var->name || !var->value.set) { return false; } var->desc = rz_str_dup(desc); - var->flags = RZ_CONFIG_VAR_FLAG_WRITABLE | RZ_CONFIG_VAR_TYPE_LIST; + var->flags = RZ_CONFIG_VAR_FLAG_WRITABLE | RZ_CONFIG_VAR_TYPE_SET; return true; } @@ -253,11 +254,11 @@ static inline bool config_var_bind_set_options(RzConfigVar *var) { return true; } - RzList *options = NULL; + RzSetS *options = NULL; if (!var->bind.get_options(var->bind.user, &options)) { return false; } - rz_list_free(var->options); + rz_set_s_free(var->options); var->options = options; return true; } @@ -373,37 +374,39 @@ RZ_API bool rz_config_add_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const cha } va_list argp; - RzList *list = rz_list_newf(free); - if (!list) { - RZ_LOG_ERROR("config: failed to initialize options list for '%s'.\n", name); + RzSetS *set = rz_set_s_new(HT_STR_DUP); + if (!set) { + RZ_LOG_ERROR("config: failed to initialize options set for '%s'.\n", name); config_var_fini(&new_entry.var); return false; } va_start(argp, desc); - bool ok = config_var_args_to_list(argp, list); + const char *first = va_arg(argp, const char *); + if (first) { + rz_set_s_add(set, first); + } + bool ok = config_var_args_to_set(argp, set); va_end(argp); if (!ok) { - RZ_LOG_ERROR("config: failed to initialize options list for '%s'.\n", name); - rz_list_free(list); + RZ_LOG_ERROR("config: failed to initialize options set for '%s'.\n", name); + rz_set_s_free(set); config_var_fini(&new_entry.var); return false; } - - const char *first = rz_list_first_val(list); if (!config_init_var_string(&new_entry.var, name, desc, first)) { RZ_LOG_ERROR("config: failed to initialize '%s'.\n", name); config_var_fini(&new_entry.var); return false; } - new_entry.var.options = list; + new_entry.var.options = set; config_add_entry(cfg, name, &new_entry, true); return true; } /** - * \brief Adds a list variable if doesn't exists. + * \brief Adds a set variable if doesn't exists. * * \param cfg The configuration where to add the variable * \param[in] name The name of the variable to add @@ -412,7 +415,7 @@ RZ_API bool rz_config_add_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const cha * * \return On success returns true, otherwise false */ -RZ_API bool rz_config_add_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...) { +RZ_API bool rz_config_add_set(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), false); RzConfigEntry new_entry = { 0 }; if (config_find_entry(cfg, name)) { @@ -421,18 +424,18 @@ RZ_API bool rz_config_add_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * } va_list argp; - RzList *list = rz_list_newf(free); - if (!list) { + RzSetS *set = rz_set_s_new(HT_STR_DUP); + if (!set) { return false; } va_start(argp, desc); - bool ok = config_var_args_to_list(argp, list); + bool ok = config_var_args_to_set(argp, set); va_end(argp); if (!ok) { - rz_list_free(list); + rz_set_s_free(set); return false; - } else if (!config_init_var_list(&new_entry.var, name, desc, list)) { + } else if (!config_init_var_set(&new_entry.var, name, desc, set)) { RZ_LOG_ERROR("config: failed to initialize '%s'.\n", name); config_var_fini(&new_entry.var); return false; @@ -519,16 +522,17 @@ RZ_API bool rz_config_var_as_json(RZ_NONNULL const RzConfigVar *var, RZ_NONNULL pj_kn(pj, key, rz_config_var_get_integer(var)); } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_STR)) { pj_ks(pj, key, rz_config_var_get_string(var)); - } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_LIST)) { - const char *value; - RzListIter *it; - RzList *list = rz_config_var_get_list(var); + } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_SET)) { + const char **value; + RzSetS *set = rz_config_var_get_set(var); + RzIterator *it = rz_set_s_as_iter(set); pj_ka(pj, key); - rz_list_foreach (list, it, value) { - pj_s(pj, value); + rz_iterator_foreach(it, value) { + pj_s(pj, *value); } + rz_iterator_free(it); pj_end(pj); - rz_list_free(list); + rz_set_s_free(set); } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_ITV)) { RzInterval itv = rz_config_var_get_interval(var); pj_ko(pj, key); @@ -558,10 +562,20 @@ RZ_API RZ_OWN char *rz_config_var_as_string(RZ_NONNULL const RzConfigVar *var) { } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_STR)) { const char *str = rz_config_var_get_string(var); return rz_str_dup(str); - } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_LIST)) { - RzList *list = rz_config_var_get_list(var); - char *value = rz_list_to_str(list, ',', false); - rz_list_free(list); + } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_SET)) { + RzSetS *set = rz_config_var_get_set(var); + RzStrBuf *sb = rz_strbuf_new(""); + RzIterator *it = rz_set_s_as_iter(set); + const char **val; + rz_iterator_foreach(it, val) { + if (rz_strbuf_length(sb) > 0) { + rz_strbuf_append(sb, ","); + } + rz_strbuf_append(sb, *val); + } + rz_iterator_free(it); + char *value = rz_strbuf_drain(sb); + rz_set_s_free(set); return value; } else if (rz_config_var_has_type(var, RZ_CONFIG_VAR_TYPE_ITV)) { RzInterval itv = rz_config_var_get_interval(var); @@ -658,22 +672,22 @@ RZ_API const char *rz_config_var_get_string(RZ_NONNULL const RzConfigVar *var) { } /** - * \brief Returns the list held by the RzConfigVar (must be a list type) + * \brief Returns the set held by the RzConfigVar (must be a set type) * * \param[in] var The RzConfigVar to use * * \return Returns the value held by the RzConfigVar */ -RZ_API RZ_OWN RzList /**/ *rz_config_var_get_list(RZ_NONNULL const RzConfigVar *var) { - config_var_assert_return(var && RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST), var ? var->name : "(null)", false); +RZ_API RZ_OWN RzSetS *rz_config_var_get_set(RZ_NONNULL const RzConfigVar *var) { + config_var_assert_return(var && RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET), var ? var->name : "(null)", false); if (!(RZ_CONFIG_VAR_HAS_FLAG(var->flags, RZ_CONFIG_VAR_FLAG_BIND))) { - return rz_list_clone(var->value.list); + return rz_config_dup_set(var->value.set); } - RzList /**/ *value = NULL; + RzSetS *value = NULL; if (!config_var_bind_get_value(var, &value) || !value) { - return rz_list_new(); + return rz_set_s_new(HT_STR_DUP); } return value; } @@ -769,7 +783,7 @@ RZ_API const char *rz_config_var_get_desc(RZ_NONNULL const RzConfigVar *var) { * * \return The options (can be NULL) */ -RZ_API const RzList /**/ *rz_config_var_get_options(RZ_NONNULL const RzConfigVar *var) { +RZ_API const RzSetS *rz_config_var_get_options(RZ_NONNULL const RzConfigVar *var) { rz_return_val_if_fail(var, NULL); return var->options; } @@ -798,8 +812,8 @@ RZ_API RZ_OWN char *rz_config_var_flags_as_string(ut32 flags) { case RZ_CONFIG_VAR_TYPE_STR: rz_strbuf_append(&sb, "string"); break; - case RZ_CONFIG_VAR_TYPE_LIST: - rz_strbuf_append(&sb, "list"); + case RZ_CONFIG_VAR_TYPE_SET: + rz_strbuf_append(&sb, "set"); break; case RZ_CONFIG_VAR_TYPE_ITV: rz_strbuf_append(&sb, "interval"); @@ -865,20 +879,22 @@ RZ_IPI bool rz_config_var_set_integer(RzConfigVar *var, ut64 value) { } static bool config_var_has_option(RzConfigVar *var, const char *value) { - if (rz_list_length(var->options) < 1) { + if (!var->options || rz_set_s_size(var->options) < 1) { // there are no options so the value is always valid. return true; } // we consider NULL as "" (empty string) value = rz_str_get(value); - const char *opt; - RzListIter *it; - rz_list_foreach (var->options, it, opt) { - if (RZ_STR_EQ(opt, value)) { + const char **opt; + RzIterator *it = rz_set_s_as_iter(var->options); + rz_iterator_foreach(it, opt) { + if (RZ_STR_EQ(*opt, value)) { + rz_iterator_free(it); return true; } } + rz_iterator_free(it); return false; } @@ -903,8 +919,8 @@ RZ_IPI bool rz_config_var_set_string(RzConfigVar *var, const char *value) { return true; } -RZ_IPI bool rz_config_var_set_list(RzConfigVar *var, const RzList /**/ *value) { - config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST), var->name, false); +RZ_IPI bool rz_config_var_set_set(RzConfigVar *var, const RzSetS *value) { + config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET), var->name, false); if (rz_config_var_is_readonly(var)) { RZ_LOG_ERROR("config: '%s' is a read only variable\n", var->name); return false; @@ -916,13 +932,13 @@ RZ_IPI bool rz_config_var_set_list(RzConfigVar *var, const RzList /*value.list); - var->value.list = rz_config_dup_list(value); + rz_set_s_free(var->value.set); + var->value.set = rz_config_dup_set(value); return true; } -RZ_IPI bool rz_config_var_set_list2(RzConfigVar *var, RZ_OWN RzList /**/ *value) { - config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST), var->name, false); +RZ_IPI bool rz_config_var_set_set2(RzConfigVar *var, RZ_OWN RzSetS *value) { + config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET), var->name, false); if (rz_config_var_is_readonly(var)) { RZ_LOG_ERROR("config: '%s' is a read only variable\n", var->name); return false; @@ -930,15 +946,15 @@ RZ_IPI bool rz_config_var_set_list2(RzConfigVar *var, RZ_OWN RzList /**/ if (RZ_CONFIG_VAR_HAS_FLAG(var->flags, RZ_CONFIG_VAR_FLAG_BIND)) { bool ret = config_var_bind_set_value(var, value); - rz_list_free(value); + rz_set_s_free(value); return ret; } else if (!config_var_is_valid_value(var, value)) { - rz_list_free(value); + rz_set_s_free(value); return false; } - rz_list_free(var->value.list); - var->value.list = value; + rz_set_s_free(var->value.set); + var->value.set = value; return true; } @@ -959,16 +975,16 @@ RZ_IPI bool rz_config_var_set_interval(RzConfigVar *var, RzInterval value) { return true; } -static bool config_set_var_list_from_string(RzConfigVar *var, const char *value) { - config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST), var->name, false); - RzList *list = NULL; +static bool config_set_var_set_from_string(RzConfigVar *var, const char *value) { + config_var_assert_return(RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET), var->name, false); + RzSetS *set = NULL; if (value) { - list = rz_str_split_duplist(value, ",", true); + set = rz_str_split_dupset(value, ",", true); } else { - list = rz_list_new(); + set = rz_set_s_new(HT_STR_DUP); } - return rz_config_var_set_list2(var, list); + return rz_config_var_set_set2(var, set); } static bool config_set_var_interval_from_string(RzConfigVar *var, const char *value) { @@ -1000,8 +1016,8 @@ RZ_IPI bool rz_config_var_set_any(RzConfigVar *var, const char *value) { return rz_config_var_set_integer(var, ivalue); } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_STR)) { return rz_config_var_set_string(var, value); - } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST)) { - return config_set_var_list_from_string(var, value); + } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET)) { + return config_set_var_set_from_string(var, value); } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_ITV)) { return config_set_var_interval_from_string(var, value); } @@ -1112,7 +1128,7 @@ RZ_API bool rz_config_set_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * } /** - * \brief Sets the value of a given list variable (must be list type) + * \brief Sets the value of a given set variable (must be set type) * * \param cfg The configuration to use * \param[in] name The name of the variable to change @@ -1120,7 +1136,7 @@ RZ_API bool rz_config_set_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * * * \return On success return true, otherwise false */ -RZ_API bool rz_config_set_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const RzList /**/ *value) { +RZ_API bool rz_config_set_set(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const RzSetS *value) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL); RzConfigEntry *entry = config_find_entry(cfg, name); @@ -1132,19 +1148,19 @@ RZ_API bool rz_config_set_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * return false; } - return rz_config_var_set_list(&entry->var, value); + return rz_config_var_set_set(&entry->var, value); } /** - * \brief Sets the value of a given list variable (must be list type) + * \brief Sets the value of a given set variable (must be set type) * * \param cfg The configuration to use * \param[in] name The name of the variable to change - * \param[in] ... The list of values to set (terminated by a NULL) + * \param[in] ... The set of values to set (terminated by a NULL) * * \return On success return true, otherwise false */ -RZ_API bool rz_config_set_list2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...) { +RZ_API bool rz_config_set_set2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL); RzConfigEntry *entry = config_find_entry(cfg, name); @@ -1157,25 +1173,25 @@ RZ_API bool rz_config_set_list2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char } va_list argp; - RzList *list = rz_list_newf(free); - if (!list) { + RzSetS *set = rz_set_s_new(HT_STR_DUP); + if (!set) { return false; } va_start(argp, name); - bool ok = config_var_args_to_list(argp, list); + bool ok = config_var_args_to_set(argp, set); va_end(argp); if (!ok) { - RZ_LOG_ERROR("config: failed to initialize list for '%s'.\n", name); - rz_list_free(list); + RZ_LOG_ERROR("config: failed to initialize set for '%s'.\n", name); + rz_set_s_free(set); return false; } - return rz_config_var_set_list2(&entry->var, list); + return rz_config_var_set_set2(&entry->var, set); } /** - * \brief Sets the value of a given list variable (must be list type) + * \brief Sets the value of a given set variable (must be set type) * * \param cfg The configuration to use * \param[in] name The name of the variable to change @@ -1183,7 +1199,7 @@ RZ_API bool rz_config_set_list2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * * \return On success return true, otherwise false */ -RZ_API bool rz_config_set_list3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_list) { +RZ_API bool rz_config_set_set3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_list) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL); RzConfigEntry *entry = config_find_entry(cfg, name); @@ -1195,7 +1211,7 @@ RZ_API bool rz_config_set_list3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char return false; } - return config_set_var_list_from_string(&entry->var, comma_list); + return config_set_var_set_from_string(&entry->var, comma_list); } /** @@ -1283,7 +1299,7 @@ RZ_API bool rz_config_set_interval3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const c * - bool, the value `true` is set if `rz_str_is_true` returns true, otherwise is false (on NULL is set to false). * - integer, the value is parsed via RzNum (on NULL is set to 0) * - string, the value is kept as is (on NULL is set to "") - * - list, the expected value is a comma separated list like `a,b,c` (on NULL is set to empty list) + * - set, the expected value is a comma separated set like `a,b,c` (on NULL is set to empty set) * - interval, the expected value is a comma separated range (inclusive) like `from,to` where from <= to (on NULL is set to [0,0]) * * \param cfg The configuration to use @@ -1381,14 +1397,14 @@ RZ_API const char *rz_config_get_string(RZ_NONNULL const RzConfig *cfg, RZ_NONNU } /** - * \brief Returns the list held by the RzConfig (must be a list type) + * \brief Returns the set held by the RzConfig (must be a set type) * * \param[in] cfg The RzConfig to use - * \param[in] name The name of the list variable + * \param[in] name The name of the set variable * * \return Returns the value held by the RzConfig */ -RZ_API RZ_OWN RzList /**/ *rz_config_get_list(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name) { +RZ_API RZ_OWN RzSetS *rz_config_get_set(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL); const RzConfigEntry *entry = config_find_entry_ro(cfg, name); @@ -1402,7 +1418,7 @@ RZ_API RZ_OWN RzList /**/ *rz_config_get_list(RZ_NONNULL const RzC return NULL; } - return rz_config_var_get_list(&entry->var); + return rz_config_var_get_set(&entry->var); } /** @@ -1467,7 +1483,7 @@ RZ_API RZ_OWN char *rz_config_get_as_string(RZ_NONNULL const RzConfig *cfg, RZ_N * * \return On success returns a pointer, can be NULL. */ -RZ_API const RzList /**/ *rz_config_get_options(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name) { +RZ_API const RzSetS *rz_config_get_options(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL); const RzConfigEntry *entry = config_find_entry_ro(cfg, name); if (!entry) { @@ -1510,20 +1526,20 @@ RZ_API ut32 rz_config_get_flags(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const return rz_config_node_get_var_flags(&entry->node); } -static bool config_entry_set_options(RzConfigEntry *entry, RZ_NULLABLE RZ_OWN RzList /**/ *options) { +static bool config_entry_set_options(RzConfigEntry *entry, RZ_NULLABLE RZ_OWN RzSetS *options) { ut32 flags = config_entry_get_flags(entry); if (!(RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_STR))) { const char *name = rz_config_entry_get_name(entry); RZ_LOG_ERROR("config: variable '%s' is not a string.\n", name); - rz_list_free(options); + rz_set_s_free(options); return false; } if (entry->is_variable) { - rz_list_free(entry->var.options); + rz_set_s_free(entry->var.options); entry->var.options = options; } else { - rz_list_free(entry->node.options); + rz_set_s_free(entry->node.options); entry->node.options = options; } @@ -1539,12 +1555,12 @@ static bool config_entry_set_options(RzConfigEntry *entry, RZ_NULLABLE RZ_OWN Rz * * \return On success returns a true, otherwise false. */ -RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RZ_OWN RzList /**/ *options) { +RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RZ_OWN RzSetS *options) { rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), false); RzConfigEntry *entry = config_find_entry(cfg, name); if (!entry) { RZ_LOG_ERROR("config: variable '%s' does not exists.\n", name); - rz_list_free(options); + rz_set_s_free(options); return false; } @@ -1556,7 +1572,7 @@ RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const cha * * \param[in] cfg The RzConfig to use * \param[in] name The name of the string type variable to update - * \param[in] ... The list of options to set (NULL terminated) + * \param[in] ... The set of options to set (NULL terminated) * * \return On success returns a true, otherwise false. */ @@ -1569,16 +1585,16 @@ RZ_API bool rz_config_set_options2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const ch } va_list argp; - RzList *options = rz_list_newf(free); + RzSetS *options = rz_set_s_new(HT_STR_DUP); if (!options) { return false; } va_start(argp, name); - bool ok = config_var_args_to_list(argp, options); + bool ok = config_var_args_to_set(argp, options); va_end(argp); if (!ok) { - rz_list_free(options); + rz_set_s_free(options); return false; } diff --git a/librz/config/config_internal.h b/librz/config/config_internal.h index 526b4b1de8..e641665a1b 100644 --- a/librz/config/config_internal.h +++ b/librz/config/config_internal.h @@ -15,7 +15,7 @@ typedef struct config_value_t { char *string; ut64 integer; bool boolean; - RzList /**/ *list; + RzSetS *set; RzInterval interval; } value; ///< Copy of the variable value } ConfigValue; @@ -54,13 +54,13 @@ static inline void config_add_entry(RzConfig *cfg, const char *name, RzConfigEnt rz_vector_insert_sorted(&cfg->sorted_vars, entry, (RzVectorComparator)sort_variables, NULL); } -RZ_IPI RZ_OWN RzList /**/ *rz_config_dup_list(RZ_NULLABLE const RzList /**/ *list); +RZ_IPI RZ_OWN RzSetS *rz_config_dup_set(RZ_NULLABLE const RzSetS *set); RZ_IPI bool rz_config_var_set_bool(RzConfigVar *var, bool value); RZ_IPI bool rz_config_var_set_integer(RzConfigVar *var, ut64 value); RZ_IPI bool rz_config_var_set_string(RzConfigVar *var, const char *value); -RZ_IPI bool rz_config_var_set_list(RzConfigVar *var, const RzList /**/ *value); -RZ_IPI bool rz_config_var_set_list2(RzConfigVar *var, RZ_OWN RzList /**/ *value); +RZ_IPI bool rz_config_var_set_set(RzConfigVar *var, const RzSetS *set); +RZ_IPI bool rz_config_var_set_set2(RzConfigVar *var, RZ_OWN RzSetS *value); RZ_IPI bool rz_config_var_set_interval(RzConfigVar *var, RzInterval value); RZ_IPI bool rz_config_var_set_any(RzConfigVar *var, const char *value); RZ_IPI bool rz_config_toggle_var_bool(RzConfigVar *var); diff --git a/librz/config/hold.c b/librz/config/hold.c index 49e8726f72..90ff464197 100644 --- a/librz/config/hold.c +++ b/librz/config/hold.c @@ -3,15 +3,6 @@ #include "config_internal.h" -static RzList /**/ *config_hold_dup_safe_list(RzConfigVar *var) { - // we do not know if the strings returned are - // safe or not to be owned, so we just dup them - RzList /**/ *list = rz_config_var_get_list(var); - RzList *safe_list = rz_config_dup_list(list); - rz_list_free(list); - return safe_list; -} - static void config_hold_value_init_from_node(ConfigValue *cv, RzConfigNode *node) { cv->name = node->name; if (rz_config_node_is_bool(node)) { @@ -35,8 +26,8 @@ static void config_hold_value_init_from_var(ConfigValue *cv, RzConfigVar *var) { } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_STR)) { const char *str = rz_config_var_get_string(var); cv->value.string = rz_str_dup(str); - } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST)) { - cv->value.list = config_hold_dup_safe_list(var); + } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_SET)) { + cv->value.set = rz_config_var_get_set(var); } else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_INT)) { cv->value.integer = rz_config_var_get_integer(var); } else { @@ -104,8 +95,8 @@ static void config_hold_value_fini(void *e, void *user) { ConfigValue *cv = (ConfigValue *)e; if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_STR)) { free(cv->value.string); - } else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_LIST)) { - rz_list_free(cv->value.list); + } else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_SET)) { + rz_set_s_free(cv->value.set); } } @@ -211,10 +202,10 @@ RZ_API void rz_config_hold_restore(RZ_NULLABLE RzConfigHold *hold) { config_hold_set_integer(entry, cv->value.integer, cfg_user); } else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_STR)) { config_hold_set_string(entry, cv->value.string, cfg_user); - } else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_LIST)) { - // ownership of list moved to var. - rz_config_var_set_list(&entry->var, cv->value.list); - cv->value.list = NULL; + } else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_SET)) { + // ownership of set moved to var. + rz_config_var_set_set2(&entry->var, cv->value.set); + cv->value.set = NULL; } else { /// RZ_CONFIG_VAR_TYPE_ITV rz_config_var_set_interval(&entry->var, cv->value.interval); } diff --git a/librz/config/old_config.c b/librz/config/old_config.c index 01b986e685..ad9a86dbc7 100644 --- a/librz/config/old_config.c +++ b/librz/config/old_config.c @@ -12,7 +12,7 @@ static bool config_node_init(RzConfigNode *node, RZ_NONNULL const char *name, RZ node->value = rz_str_dup(value); node->flags = CN_STR; node->i_value = rz_num_get(NULL, value); - node->options = rz_list_new(); + node->options = rz_set_s_new(HT_STR_DUP); return node->name && node->value && node->options; } @@ -24,7 +24,7 @@ RZ_IPI void rz_config_node_fini(RZ_NULLABLE RzConfigNode *node) { free(node->name); free(node->desc); free(node->value); - rz_list_free(node->options); + rz_set_s_free(node->options); } RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name) { diff --git a/librz/core/carch.c b/librz/core/carch.c index 1c9811db16..25f710871b 100644 --- a/librz/core/carch.c +++ b/librz/core/carch.c @@ -89,8 +89,7 @@ RZ_DEPRECATE static void core_update_config_bits_options(RzCore *core, const cha return; } - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); if (!core->rasm) { return; } @@ -98,20 +97,21 @@ RZ_DEPRECATE static void core_update_config_bits_options(RzCore *core, const cha ut32 bits = rz_asm_get_plugin_bits(core->rasm); for (ut32 i = 1; i <= bits; i <<= 1) { if (i & bits) { - rz_list_append(node->options, rz_str_newf("%u", i)); + char *s = rz_str_newf("%u", i); + rz_set_s_add(node->options, s); + free(s); } } } RZ_DEPRECATE static void core_update_config_options(RzConfigNode *node, const char *list_comma_sep) { if (RZ_STR_ISEMPTY(list_comma_sep)) { - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } - rz_list_free(node->options); - node->options = rz_str_split_duplist(list_comma_sep, ",", true); + rz_set_s_free(node->options); + node->options = rz_str_split_dupset(list_comma_sep, ",", true); } // copied from cconfig.c & cleaned @@ -120,8 +120,7 @@ RZ_DEPRECATE static void core_update_config_cpu_options(RzCore *core, const char if (!node) { return; } else if (!core->rasm) { - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } @@ -135,8 +134,7 @@ static void core_update_config_platform_options(RzCore *core, const char *name) if (!node) { return; } else if (!core->rasm) { - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } @@ -150,8 +148,7 @@ static void core_update_config_features_options(RzCore *core, const char *name) if (!node) { return; } else if (!core->rasm) { - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } diff --git a/librz/core/cautocmpl.c b/librz/core/cautocmpl.c index f21e524a5a..62cfd49d2f 100644 --- a/librz/core/cautocmpl.c +++ b/librz/core/cautocmpl.c @@ -878,7 +878,7 @@ static void autocmplt_cmd_arg_eval_full(RzCore *core, RzLineNSCompletionResult * char *k = rz_str_ndup(s, eq - s); char *v = NULL; - const RzList *options = rz_config_get_options(core->config, k); + const RzSetS *options = rz_config_get_options(core->config, k); if (!options) { goto err; } @@ -889,14 +889,15 @@ static void autocmplt_cmd_arg_eval_full(RzCore *core, RzLineNSCompletionResult * res->start += strlen(k) + 1; - if (rz_list_length(options) > 0) { - const RzListIter *iter; - const char *opt; - rz_list_foreach (options, iter, opt) { - if (!strncmp(opt, v, len)) { - rz_line_ns_completion_result_add(res, opt); + if (rz_set_s_size(options) > 0) { + RzIterator *iter = rz_set_s_as_iter(options); + const char **opt; + rz_iterator_foreach(iter, opt) { + if (!strncmp(*opt, v, len)) { + rz_line_ns_completion_result_add(res, *opt); } } + rz_iterator_free(iter); } else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_BOOL)) { if (!strncmp("true", v, len)) { rz_line_ns_completion_result_add(res, "true"); diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index 881203f122..73f23c0716 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -39,7 +39,7 @@ static void set_options(RzConfigNode *node, ...) { va_start(argp, node); option = va_arg(argp, char *); while (option) { - rz_list_append(node->options, option); + rz_set_s_add(node->options, option); option = va_arg(argp, char *); } va_end(argp); @@ -55,11 +55,12 @@ static bool isGdbPlugin(RzCore *core) { } static void print_node_options(RzConfigNode *node) { - RzListIter *iter; - char *option; - rz_list_foreach (node->options, iter, option) { - rz_cons_printf("%s\n", option); + RzIterator *iter = rz_set_s_as_iter(node->options); + const char **option; + rz_iterator_foreach(iter, option) { + rz_cons_printf("%s\n", *option); } + rz_iterator_free(iter); } static int compareName(const RzAnalysisFunction *a, const RzAnalysisFunction *b, void *user) { @@ -98,7 +99,7 @@ static void update_asmarch_options(RzCore *core, RzConfigNode *node) { RzAsmPlugin **val; RzIterator *it = rz_asm_plugin_iterator(core->rasm); - rz_list_purge(node->options); + rz_set_s_clear(node->options); rz_iterator_foreach(it, val) { RzAsmPlugin *h = *val; SETOPTIONS(node, h->name, NULL); @@ -112,8 +113,7 @@ static void update_asmbits_options(RzCore *core, RzConfigNode *node) { } int bits = rz_asm_get_plugin_bits(core->rasm); - node->options->free = free; - rz_list_purge(node->options); + rz_set_s_clear(node->options); for (int i = 1; i <= bits; i <<= 1) { if (i & bits) { SETOPTIONS(node, rz_str_newf("%d", i), NULL); @@ -128,12 +128,12 @@ static void update_asmfeatures_options(RzCore *core, RzConfigNode *node) { const char *features = rz_asm_get_plugin_features(core->rasm); if (RZ_STR_ISEMPTY(features)) { - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } - rz_list_free(node->options); - node->options = rz_str_split_duplist(features, ",", true); + rz_set_s_free(node->options); + node->options = rz_str_split_dupset(features, ",", true); } static void update_asmplatforms_options(RzCore *core, RzConfigNode *node) { @@ -143,19 +143,19 @@ static void update_asmplatforms_options(RzCore *core, RzConfigNode *node) { const char *platforms = rz_asm_get_plugin_platforms(core->rasm); if (RZ_STR_ISEMPTY(platforms)) { - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } - rz_list_free(node->options); - node->options = rz_str_split_duplist(platforms, ",", true); + rz_set_s_free(node->options); + node->options = rz_str_split_dupset(platforms, ",", true); } static void update_asmparser_options(RzCore *core, RzConfigNode *node) { RzListIter *iter; RzParsePlugin *parser; if (core && node && core->parser && core->parser->parsers) { - rz_list_purge(node->options); + rz_set_s_clear(node->options); rz_list_foreach (core->parser->parsers, iter, parser) { SETOPTIONS(node, parser->name, NULL); } @@ -167,12 +167,12 @@ static void update_asmcpu_options(RzCore *core, RzConfigNode *node) { const char *cpus = rz_asm_get_plugin_cpus(core->rasm); if (RZ_STR_ISEMPTY(cpus)) { - rz_list_purge(node->options); + rz_set_s_clear(node->options); return; } - rz_list_free(node->options); - node->options = rz_str_split_duplist(cpus, ",", true); + rz_set_s_free(node->options); + node->options = rz_str_split_dupset(cpus, ",", true); } static bool cb_search_case_sensitive(void *_core, void *_node) { @@ -459,7 +459,7 @@ static void update_analysis_arch_options(RzCore *core, RzConfigNode *node) { RzIterator *it = rz_analysis_plugin_iterator(core->analysis); RzAnalysisPlugin **val; if (core && core->analysis && node) { - rz_list_purge(node->options); + rz_set_s_clear(node->options); rz_iterator_foreach(it, val) { RzAnalysisPlugin *h = *val; SETOPTIONS(node, h->name, NULL); @@ -946,18 +946,20 @@ static bool cb_search_str_check_ascii_freq(void *user, void *data) { } static bool find_encoding(RzConfigNode *node, RzStrEnc *encoding) { - RzListIter *iter; - const char *option; - rz_list_foreach (node->options, iter, option) { - if (rz_str_casecmp(option, node->value)) { + RzIterator *iter = rz_set_s_as_iter(node->options); + const char **option; + rz_iterator_foreach(iter, option) { + if (rz_str_casecmp(*option, node->value)) { continue; } free(node->value); - node->value = rz_str_dup(option); - *encoding = rz_str_enc_string_as_type(option); + node->value = rz_str_dup(*option); + *encoding = rz_str_enc_string_as_type(*option); + rz_iterator_free(iter); return true; } - if (rz_list_empty(node->options)) { + rz_iterator_free(iter); + if (rz_set_s_size(node->options) == 0) { // Edge case when the node was just initialized but the options // were not added yet. *encoding = rz_str_enc_string_as_type(node->value); @@ -1594,12 +1596,15 @@ static bool cb_iopcachewrite(void *user, void *data) { return true; } -static void config_print_options_as_json(PJ *pj, const RzList /**/ *options) { - RzListIter *iter; - const char *option; +static void config_print_options_as_json(PJ *pj, const RzSetS *options) { pj_ka(pj, "options"); - rz_list_foreach (options, iter, option) { - pj_s(pj, option); + if (options) { + RzIterator *iter = rz_set_s_as_iter(options); + const char **option; + rz_iterator_foreach(iter, option) { + pj_s(pj, *option); + } + rz_iterator_free(iter); } pj_end(pj); } @@ -1636,7 +1641,7 @@ static void config_print_node_as_long_json(const RzConfigNode *node, PJ *pj) { static void config_print_var_as_long_json(const RzConfigVar *var, PJ *pj) { const char *name = rz_config_var_get_name(var); const char *desc = rz_config_var_get_desc(var); - const RzList *options = rz_config_var_get_options(var); + const RzSetS *options = rz_config_var_get_options(var); ut32 flags = rz_config_var_get_flags(var); pj_o(pj); config_print_long_json(pj, name, desc, flags); @@ -1654,20 +1659,23 @@ typedef struct core_config_print_s { char reset_str[32]; } CoreConfigPrint; -static void core_config_print_array_as_string(const RzList /**/ *list, bool allow_empty) { - const char *entry; - const RzListIter *it; - if (rz_list_empty(list) && !allow_empty) { +static void core_config_print_set_as_string(const RzSetS *set, bool allow_empty) { + if (rz_set_s_size(set) < 1 && !allow_empty) { return; } rz_cons_print("["); - rz_list_foreach (list, it, entry) { - if (rz_list_head(list) != it) { - rz_cons_printf(", %s", entry); + RzIterator *iter = rz_set_s_as_iter(set); + const char **entry; + bool first = true; + rz_iterator_foreach(iter, entry) { + if (!first) { + rz_cons_printf(", %s", *entry); } else { - rz_cons_print(entry); + rz_cons_print(*entry); + first = false; } } + rz_iterator_free(iter); rz_cons_print("]"); } @@ -1685,10 +1693,10 @@ static void core_config_print_var_as_string(const RzConfigEntry *entry, ut32 fla } else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_STR)) { const char *value = rz_config_entry_get_string(entry); rz_cons_print(value); - } else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_LIST)) { - RzList *list = rz_config_var_get_list(&entry->var); - core_config_print_array_as_string(list, true); - rz_list_free(list); + } else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_SET)) { + RzSetS *set = rz_config_var_get_set(&entry->var); + core_config_print_set_as_string(set, true); + rz_set_s_free(set); } else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_ITV)) { RzInterval itv = rz_config_var_get_interval(&entry->var); rz_cons_printf("[0x%08" PFMT64x ",0x%08" PFMT64x "]", rz_itv_begin(itv), rz_itv_end(itv)); @@ -1704,7 +1712,7 @@ static bool core_config_print_iterator(const RzConfigEntry *entry, void *user) { const char *name = NULL; const char *desc = ""; - const RzList *options = NULL; + const RzSetS *options = NULL; ut32 e_flags = 0; RzOutputMode mode = ccp->state->mode; PJ *pj = ccp->state->d.pj; @@ -1742,7 +1750,7 @@ static bool core_config_print_iterator(const RzConfigEntry *entry, void *user) { rz_cons_printf("%s%20s = %s", ccp->color_name, name, ccp->color_value); core_config_print_var_as_string(entry, e_flags); rz_cons_printf(" %s(%s); %s%s ", ccp->color_meta, s_flags, ccp->reset_str, desc); - core_config_print_array_as_string(options, false); + core_config_print_set_as_string(options, false); rz_cons_println(""); break; } diff --git a/librz/core/tui/config.c b/librz/core/tui/config.c index 8811df2ccb..0a283b0f99 100644 --- a/librz/core/tui/config.c +++ b/librz/core/tui/config.c @@ -75,17 +75,17 @@ static void config_visual_hit(RzCore *core, const char *name, int editor) { } static void show_config_options(RzCore *core, const char *name) { - const RzList *options = rz_config_get_options(core->config, name); - if (rz_list_empty(options)) { + const RzSetS *options = rz_config_get_options(core->config, name); + if (rz_set_s_size(options) == 0) { return; } int w = rz_cons_get_size(NULL); - const char *item; - const RzListIter *iter; + const char **item; + RzIterator *iter = rz_set_s_as_iter(options); RzStrBuf *sb = rz_strbuf_new(" Options: "); - rz_list_foreach (options, iter, item) { - rz_strbuf_appendf(sb, "%s%s", rz_list_val(iter) ? ", " : "", item); + rz_iterator_foreach(iter, item) { + rz_strbuf_appendf(sb, "%s%s", *item ? ", " : "", *item); if (rz_strbuf_length(sb) + 5 >= w) { char *s = rz_strbuf_drain(sb); rz_cons_println(s); @@ -93,6 +93,7 @@ static void show_config_options(RzCore *core, const char *name) { sb = rz_strbuf_new(""); } } + rz_iterator_free(iter); char *s = rz_strbuf_drain(sb); rz_cons_println(s); free(s); diff --git a/librz/include/rz_config.h b/librz/include/rz_config.h index 7b3fa437f6..5e77f7e747 100644 --- a/librz/include/rz_config.h +++ b/librz/include/rz_config.h @@ -43,7 +43,7 @@ typedef struct rz_config_node_t { char **cb_ptr_s; RzConfigCallback setter; char *desc; - RzList /**/ *options; + RzSetS *options; } RzConfigNode; typedef enum { @@ -52,7 +52,7 @@ typedef enum { RZ_CONFIG_VAR_TYPE_BOOL = 1, RZ_CONFIG_VAR_TYPE_INT = 2, RZ_CONFIG_VAR_TYPE_STR = 3, - RZ_CONFIG_VAR_TYPE_LIST = 4, + RZ_CONFIG_VAR_TYPE_SET = 4, RZ_CONFIG_VAR_TYPE_ITV = 5, // these are flags RZ_CONFIG_VAR_FLAG_BIND = 0x40000000, @@ -67,14 +67,14 @@ typedef enum { typedef bool (*RzConfigBindGet)(void *user, void *value); typedef bool (*RzConfigBindSet)(void *user, const void *value); -typedef bool (*RzConfigBindOpts)(void *user, RzList /**/ **options); +typedef bool (*RzConfigBindOpts)(void *user, RzSetS **options); typedef struct rz_config_owned_t { union { bool boolean; ///< Owned boolean ut64 integer; ///< Owned unsigned integer char *string; ///< Owned zero-terminated string (can be NULL) - RzList /**/ *list; ///< Owned list of zero-terminated string (can be NULL) + RzSetS *set; ///< Owned set of zero-terminated string (can be NULL) RzInterval interval; ///< Owned interval }; RzConfigBindSet validator; ///< Validator callback @@ -91,7 +91,7 @@ typedef struct rz_config_bind_t { typedef struct rz_config_var_t { char *name; ///< Variable name char *desc; ///< Description of the variable - RzList /**/ *options; ///< Variable possible values + RzSetS *options; ///< Variable possible values ut32 flags; ///< Define the type of the data via RzConfigVar (see RzConfigVarFlags) union { RzConfigOwned value; ///< owned value @@ -135,39 +135,39 @@ RZ_API bool rz_config_add_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char * RZ_API bool rz_config_add_integer(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut64 value); RZ_API bool rz_config_add_string(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, RZ_NULLABLE const char *value); RZ_API bool rz_config_add_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...); -RZ_API bool rz_config_add_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...); +RZ_API bool rz_config_add_set(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...); RZ_API bool rz_config_add_interval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut64 from, ut64 to); RZ_API bool rz_config_add_bind(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut32 type, RZ_NONNULL RzConfigBindGet get, RZ_NULLABLE RzConfigBindSet set, RZ_NULLABLE RzConfigBindOpts opts, RZ_NULLABLE void *user); #define rz_config_add_bool_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_BOOL, get, set, opts, user) #define rz_config_add_integer_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_INT, get, set, opts, user) #define rz_config_add_string_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_STR, get, set, opts, user) -#define rz_config_add_list_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_LIST, get, set, opts, user) +#define rz_config_add_set_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_SET, get, set, opts, user) #define rz_config_add_interval_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_ITV, get, set, opts, user) RZ_API bool rz_config_set_string(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *value); RZ_API bool rz_config_set_integer(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ut64 value); RZ_API bool rz_config_set_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, bool value); RZ_API bool rz_config_toggle_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name); -RZ_API bool rz_config_set_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const RzList /**/ *value); -RZ_API bool rz_config_set_list2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...); -RZ_API bool rz_config_set_list3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_list); +RZ_API bool rz_config_set_set(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const RzSetS *value); +RZ_API bool rz_config_set_set2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...); +RZ_API bool rz_config_set_set3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_list); RZ_API bool rz_config_set_interval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RzInterval value); RZ_API bool rz_config_set_interval2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ut64 from, ut64 to); RZ_API bool rz_config_set_interval3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_itv); RZ_API bool rz_config_set_any(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *value); -RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RZ_OWN RzList /**/ *options); +RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RZ_OWN RzSetS *options); RZ_API bool rz_config_set_options2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...); RZ_API bool rz_config_set_validator(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RzConfigBindSet validator, RZ_NULLABLE void *user); RZ_API bool rz_config_get_bool(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API ut64 rz_config_get_integer(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API const char *rz_config_get_string(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); -RZ_API RZ_OWN RzList /**/ *rz_config_get_list(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); +RZ_API RZ_OWN RzSetS *rz_config_get_set(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API RzInterval rz_config_get_interval(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API RZ_OWN char *rz_config_get_as_string(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); -RZ_API const RzList /**/ *rz_config_get_options(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); +RZ_API const RzSetS *rz_config_get_options(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API ut32 rz_config_get_flags(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name); RZ_API bool rz_config_var_as_json(RZ_NONNULL const RzConfigVar *var, RZ_NONNULL PJ *pj, RZ_NONNULL const char *key); @@ -176,7 +176,7 @@ RZ_API bool rz_config_var_is_readonly(RZ_NONNULL const RzConfigVar *var); RZ_API bool rz_config_var_get_bool(RZ_NONNULL const RzConfigVar *var); RZ_API ut64 rz_config_var_get_integer(RZ_NONNULL const RzConfigVar *var); RZ_API const char *rz_config_var_get_string(RZ_NONNULL const RzConfigVar *var); -RZ_API RZ_OWN RzList /**/ *rz_config_var_get_list(RZ_NONNULL const RzConfigVar *var); +RZ_API RZ_OWN RzSetS *rz_config_var_get_set(RZ_NONNULL const RzConfigVar *var); RZ_API RzInterval rz_config_var_get_interval(RZ_NONNULL const RzConfigVar *var); RZ_API bool rz_config_var_has_type(RZ_NONNULL const RzConfigVar *var, ut32 etype); RZ_API bool rz_config_var_has_flags(RZ_NONNULL const RzConfigVar *var, ut32 eflags); @@ -184,7 +184,7 @@ RZ_API RZ_OWN char *rz_config_var_flags_as_string(ut32 flags); RZ_API ut32 rz_config_var_get_flags(RZ_NONNULL const RzConfigVar *var); RZ_API const char *rz_config_var_get_name(RZ_NONNULL const RzConfigVar *var); RZ_API const char *rz_config_var_get_desc(RZ_NONNULL const RzConfigVar *var); -RZ_API const RzList /**/ *rz_config_var_get_options(RZ_NONNULL const RzConfigVar *var); +RZ_API const RzSetS *rz_config_var_get_options(RZ_NONNULL const RzConfigVar *var); /* to deprecate */ RZ_API const char *rz_config_entry_get_name(RZ_NONNULL const RzConfigEntry *entry); diff --git a/librz/include/rz_util/rz_set.h b/librz/include/rz_util/rz_set.h index df7d255e66..11d5175478 100644 --- a/librz/include/rz_util/rz_set.h +++ b/librz/include/rz_util/rz_set.h @@ -16,6 +16,7 @@ extern "C" { typedef HtSP RzSetS; RZ_API RZ_OWN RzSetS *rz_set_s_new(HtStrOption opt); +RZ_API RZ_OWN RzSetS *rz_str_split_dupset(RZ_NONNULL const char *_str, RZ_NONNULL const char *c, bool trim); RZ_API void rz_set_s_free(RZ_NULLABLE RzSetS *set); RZ_API void rz_set_s_add(RZ_NONNULL RzSetS *set, const char *str); RZ_API bool rz_set_s_contains(const RZ_NONNULL RzSetS *set, const char *str); diff --git a/librz/util/set.c b/librz/util/set.c index 0f56adac1d..d254f7daee 100644 --- a/librz/util/set.c +++ b/librz/util/set.c @@ -4,6 +4,8 @@ #include #include +#include +#include /** * \brief Create a new hash set with C-string as elements. @@ -13,6 +15,37 @@ RZ_API RZ_OWN RzSetS *rz_set_s_new(HtStrOption opt) { return ht_sp_new(opt, NULL, NULL); } +/** + * \brief Split the string \p str according to the substring \p c and returns a \p RzSetS with the result. + * + * Split a string \p str according to the delimiter specified in \p c. It can + * optionally trim (aka remove spaces) the tokens. The result is a \p RzSetS with newly allocated strings for each + * token. + * + * \param _str Input string to split + * \param c Delimiter string used to split \p str + * \param trim If true each token is considered without trailing/leading whitespaces. + */ +RZ_API RZ_OWN RzSetS *rz_str_split_dupset(RZ_NONNULL const char *_str, RZ_NONNULL const char *c, bool trim) { + rz_return_val_if_fail(_str && c, NULL); + RzList *list = rz_str_split_duplist(_str, c, trim); + if (!list) { + return NULL; + } + RzSetS *set = rz_set_s_new(HT_STR_DUP); + if (!set) { + rz_list_free(list); + return NULL; + } + RzListIter *it; + const char *val; + rz_list_foreach (list, it, val) { + rz_set_s_add(set, val); + } + rz_list_free(list); + return set; +} + /** * \brief Add element \p str to hash set \p set. */ diff --git a/test/db/cmd/cmd_eval b/test/db/cmd/cmd_eval index 0208ffb83c..5171009459 100644 --- a/test/db/cmd/cmd_eval +++ b/test/db/cmd/cmd_eval @@ -53,15 +53,15 @@ FILE== CMDS=e asm.os=? EXPECT=<get++; return true; } - case RZ_CONFIG_VAR_TYPE_LIST: { - const RzList **value = p; - *value = bt->list; + case RZ_CONFIG_VAR_TYPE_SET: { + RzSetS **value = p; + RzSetS *dup = rz_set_s_new(HT_STR_DUP); + RzIterator *iter = rz_set_s_as_iter(bt->set_val_set); + const char **elem; + rz_iterator_foreach(iter, elem) { + rz_set_s_add(dup, *elem); + } + rz_iterator_free(iter); + *value = dup; bt->get++; return true; } @@ -433,7 +428,7 @@ static bool any_set(void *user, const void *p) { return true; case RZ_CONFIG_VAR_TYPE_STR: /* fall-thru */ - case RZ_CONFIG_VAR_TYPE_LIST: + case RZ_CONFIG_VAR_TYPE_SET: bt->set_val = p; bt->set++; return true; @@ -449,18 +444,22 @@ static bool any_set(void *user, const void *p) { } } -static bool any_opts(void *user, RzList /**/ **options) { +static bool any_opts(void *user, RzSetS **options) { bind_test_t *bt = user; switch (bt->bind) { - case RZ_CONFIG_VAR_TYPE_STR: - *options = rz_str_split_duplist("foo,bar", ",", true); + case RZ_CONFIG_VAR_TYPE_STR: { + RzSetS *opts_set = rz_set_s_new(HT_STR_DUP); + rz_set_s_add(opts_set, "foo"); + rz_set_s_add(opts_set, "bar"); + *options = opts_set; bt->opts++; return true; + } case RZ_CONFIG_VAR_TYPE_BOOL: /* fall-thru */ case RZ_CONFIG_VAR_TYPE_INT: /* fall-thru */ - case RZ_CONFIG_VAR_TYPE_LIST: + case RZ_CONFIG_VAR_TYPE_SET: /* fall-thru */ case RZ_CONFIG_VAR_TYPE_ITV: bt->opts++; @@ -478,8 +477,10 @@ bool test_config_binds() { RzConfig *cfg = rz_config_new(NULL); mu_assert_notnull(cfg, "alloc RzConfig"); - bt.list = rz_str_split_duplist("init,fini", ",", true); - mu_assert_notnull(bt.list, "alloc list"); + bt.set_val_set = rz_set_s_new(HT_STR_DUP); + rz_set_s_add(bt.set_val_set, "init"); + rz_set_s_add(bt.set_val_set, "fini"); + mu_assert_notnull(bt.set_val_set, "alloc set"); // add binds bt.bind = RZ_CONFIG_VAR_TYPE_BOOL; @@ -503,11 +504,11 @@ bool test_config_binds() { ret = rz_config_set_validator(cfg, "bind.string", test_config_validator, &ret); mu_assert_false(ret, "cannot set validator when bind"); - bt.bind = RZ_CONFIG_VAR_TYPE_LIST; - ret = rz_config_add_list_bind(cfg, "bind.list", "is bind.list desc", any_get, any_set, any_opts, &bt); - mu_assert_true(ret, "added bind.list"); + bt.bind = RZ_CONFIG_VAR_TYPE_SET; + ret = rz_config_add_set_bind(cfg, "bind.set", "is bind.set desc", any_get, any_set, any_opts, &bt); + mu_assert_true(ret, "added bind.set"); - ret = rz_config_set_validator(cfg, "bind.list", test_config_validator, &ret); + ret = rz_config_set_validator(cfg, "bind.set", test_config_validator, &ret); mu_assert_false(ret, "cannot set validator when bind"); bt.bind = RZ_CONFIG_VAR_TYPE_ITV; @@ -526,8 +527,15 @@ bool test_config_binds() { bt.bind = RZ_CONFIG_VAR_TYPE_STR; mu_assert_streq(rz_config_get_string(cfg, "bind.string"), "what", "get bind.string"); - bt.bind = RZ_CONFIG_VAR_TYPE_LIST; - mu_assert_ptreq(rz_config_get_list(cfg, "bind.list"), bt.list, "get bind.list"); + bt.bind = RZ_CONFIG_VAR_TYPE_SET; + { + RzSetS *bind_set = rz_config_get_set(cfg, "bind.set"); + mu_assert_notnull(bind_set, "get bind.set"); + mu_assert_eq(rz_set_s_size(bind_set), 2, "bind.set size is 2"); + mu_assert_true(rz_set_s_contains(bind_set, "init"), "bind.set contains init"); + mu_assert_true(rz_set_s_contains(bind_set, "fini"), "bind.set contains fini"); + rz_set_s_free(bind_set); + } bt.bind = RZ_CONFIG_VAR_TYPE_ITV; itv = rz_config_get_interval(cfg, "bind.interval"); @@ -549,10 +557,10 @@ bool test_config_binds() { mu_assert_true(ret, "set bind.string"); mu_assert_streq(bt.set_val, "foo", "has actually set bind.string"); - bt.bind = RZ_CONFIG_VAR_TYPE_LIST; - ret = rz_config_set_list(cfg, "bind.list", bt.list); - mu_assert_true(ret, "set bind.list"); - mu_assert_ptreq(bt.set_val, bt.list, "has actually set bind.list"); + bt.bind = RZ_CONFIG_VAR_TYPE_SET; + ret = rz_config_set_set(cfg, "bind.set", bt.set_val_set); + mu_assert_true(ret, "set bind.set"); + mu_assert_notnull(bt.set_val, "has actually set bind.set"); bt.bind = RZ_CONFIG_VAR_TYPE_ITV; bt.set_val = &itv; @@ -566,7 +574,7 @@ bool test_config_binds() { mu_assert_eq(bt.set, 5, "called bind.set_value"); rz_config_free(cfg); - rz_list_free(bt.list); + rz_set_s_free(bt.set_val_set); mu_end; } @@ -574,7 +582,7 @@ bool all_tests() { mu_run_test(test_config_strings); mu_run_test(test_config_intergers); mu_run_test(test_config_booleans); - mu_run_test(test_config_lists); + mu_run_test(test_config_sets); mu_run_test(test_config_itv); mu_run_test(test_config_invalid); mu_run_test(test_config_binds);