Change rz_config variables to use Set instead of List (#6623)

* Update rz_config list variables to set variables

* Linking error fix

* Update rz_config_get_options in cautocmpl.c

* Update rz_config_get_options in core/tui/config.c

* Test fix

* Assertion error fix
This commit is contained in:
Farhan Saiyed 2026-07-23 11:09:58 -04:00 committed by GitHub
parent 78045e8fc6
commit fa2db74f86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 362 additions and 306 deletions

View file

@ -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 /*<char *>*/ *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 /*<char *>*/ *rz_config_dup_list(RZ_NULLABLE const RzList /*<const char *>*/ *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 /*<char *>*/ *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 /*<const char *>*/ *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 /*<char *>*/ *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 /*<char *>*/ *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 /*<const char *>*/ *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 /*<const char
return false;
}
rz_list_free(var->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 /*<char *>*/ *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 /*<char *>*/
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 /*<const char *>*/ *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 /*<const char *>*/ *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 /*<const char *>*/ *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 /*<char *>*/ *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 /*<char *>*/ *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 /*<char *>*/ *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;
}

View file

@ -15,7 +15,7 @@ typedef struct config_value_t {
char *string;
ut64 integer;
bool boolean;
RzList /*<char *>*/ *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 /*<char *>*/ *rz_config_dup_list(RZ_NULLABLE const RzList /*<const char *>*/ *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 /*<const char *>*/ *value);
RZ_IPI bool rz_config_var_set_list2(RzConfigVar *var, RZ_OWN RzList /*<char *>*/ *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);

View file

@ -3,15 +3,6 @@
#include "config_internal.h"
static RzList /*<char *>*/ *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 /*<const char *>*/ *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);
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -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");

View file

@ -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 /*<char *>*/ *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 /*<char *>*/ *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;
}

View file

@ -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);

View file

@ -43,7 +43,7 @@ typedef struct rz_config_node_t {
char **cb_ptr_s;
RzConfigCallback setter;
char *desc;
RzList /*<char *>*/ *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 /*<char *>*/ **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 /*<char *>*/ *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 /*<char *>*/ *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 /*<const char *>*/ *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 /*<char *>*/ *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 /*<const char *>*/ *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 /*<char *>*/ *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 /*<const char *>*/ *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 /*<char *>*/ *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);

View file

@ -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);

View file

@ -4,6 +4,8 @@
#include <rz_util/rz_set.h>
#include <rz_util/rz_assert.h>
#include <rz_util/rz_str.h>
#include <rz_list.h>
/**
* \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.
*/

View file

@ -53,15 +53,15 @@ FILE==
CMDS=e asm.os=?
EXPECT=<<EOF
ios
dos
darwin
linux
freebsd
openbsd
netbsd
windows
s110
none
darwin
freebsd
windows
dos
openbsd
netbsd
EOF
RUN
@ -174,7 +174,7 @@ elq zoom
EOF
EXPECT=<<EOF
{"zoom.byte":"h","zoom.from":0,"zoom.in":"io.map","zoom.maxsz":512,"zoom.to":0}
[{"name":"zoom.byte","desc":"Zoom callback to calculate each byte (See pz? for help)","flags":"string,bind","options":[],"value":"h"},{"name":"zoom.from","desc":"Zoom start address","flags":"integer","options":[],"value":0},{"name":"zoom.in","desc":"Specify boundaries for zoom","flags":"string,bind","options":["raw","block","bin.section","bin.sections","bin.sections.rwx","bin.sections.r","bin.sections.rw","bin.sections.rx","bin.sections.wx","bin.sections.x","io.map","io.maps","io.maps.rwx","io.maps.r","io.maps.rw","io.maps.rx","io.maps.wx","io.maps.x","dbg.stack","dbg.heap","dbg.map","dbg.maps","dbg.maps.rwx","dbg.maps.r","dbg.maps.rw","dbg.maps.rx","dbg.maps.wx","dbg.maps.x","analysis.fcn","analysis.bb"],"value":"io.map"},{"name":"zoom.maxsz","desc":"Zoom max size of block","flags":"integer","options":[],"value":512},{"name":"zoom.to","desc":"Zoom end address","flags":"integer","options":[],"value":0}]
[{"name":"zoom.byte","desc":"Zoom callback to calculate each byte (See pz? for help)","flags":"string,bind","options":[],"value":"h"},{"name":"zoom.from","desc":"Zoom start address","flags":"integer","options":[],"value":0},{"name":"zoom.in","desc":"Specify boundaries for zoom","flags":"string,bind","options":["io.maps.rw","block","bin.sections.rx","io.maps.rwx","dbg.heap","io.map","dbg.maps.rwx","io.maps.r","bin.sections.r","dbg.maps.r","io.maps.x","analysis.fcn","bin.sections.x","analysis.bb","dbg.maps.rw","dbg.maps.x","dbg.map","io.maps.wx","bin.sections.wx","raw","bin.section","bin.sections.rw","bin.sections.rwx","io.maps","dbg.maps.rx","dbg.maps.wx","bin.sections","dbg.stack","io.maps.rx","dbg.maps"],"value":"io.map"},{"name":"zoom.maxsz","desc":"Zoom max size of block","flags":"integer","options":[],"value":512},{"name":"zoom.to","desc":"Zoom end address","flags":"integer","options":[],"value":0}]
zoom.byte: Zoom callback to calculate each byte (See pz? for help)
zoom.from: Zoom start address
zoom.in: Specify boundaries for zoom
@ -182,7 +182,7 @@ EXPECT=<<EOF
zoom.to: Zoom end address
zoom.byte = h (string,bind); Zoom callback to calculate each byte (See pz? for help)
zoom.from = 0 (integer); Zoom start address
zoom.in = io.map (string,bind); Specify boundaries for zoom [raw, block, bin.section, bin.sections, bin.sections.rwx, bin.sections.r, bin.sections.rw, bin.sections.rx, bin.sections.wx, bin.sections.x, io.map, io.maps, io.maps.rwx, io.maps.r, io.maps.rw, io.maps.rx, io.maps.wx, io.maps.x, dbg.stack, dbg.heap, dbg.map, dbg.maps, dbg.maps.rwx, dbg.maps.r, dbg.maps.rw, dbg.maps.rx, dbg.maps.wx, dbg.maps.x, analysis.fcn, analysis.bb]
zoom.in = io.map (string,bind); Specify boundaries for zoom [io.maps.rw, block, bin.sections.rx, io.maps.rwx, dbg.heap, io.map, dbg.maps.rwx, io.maps.r, bin.sections.r, dbg.maps.r, io.maps.x, analysis.fcn, bin.sections.x, analysis.bb, dbg.maps.rw, dbg.maps.x, dbg.map, io.maps.wx, bin.sections.wx, raw, bin.section, bin.sections.rw, bin.sections.rwx, io.maps, dbg.maps.rx, dbg.maps.wx, bin.sections, dbg.stack, io.maps.rx, dbg.maps]
zoom.maxsz = 512 (integer); Zoom max size of block
zoom.to = 0 (integer); Zoom end address
zoom.byte=h

View file

@ -203,70 +203,58 @@ bool test_config_booleans() {
mu_end;
}
bool test_config_lists() {
bool test_config_sets() {
RzConfig *cfg = rz_config_new(NULL);
bool ret = false;
const char *elem = NULL;
RzList *list = NULL;
RzListIter *it;
RzSetS *set = NULL;
// list variables
ret = rz_config_add_list(cfg, "thy.list", "is thy.list desc", "r1", "r2", "r3", NULL);
mu_assert_true(ret, "added thy.list");
// set variables
ret = rz_config_add_set(cfg, "thy.set", "is thy.set desc", "r1", "r2", "r3", NULL);
mu_assert_true(ret, "added thy.set");
ret = rz_config_set_validator(cfg, "thy.list", test_config_validator, &ret);
mu_assert_true(ret, "can set validator for list");
ret = rz_config_set_validator(cfg, "thy.set", test_config_validator, &ret);
mu_assert_true(ret, "can set validator for set");
list = rz_config_get_list(cfg, "thy.list");
mu_assert_notnull(list, "List is not null variable");
mu_assert_eq(rz_list_length(list), 3, "List size is 3");
set = rz_config_get_set(cfg, "thy.set");
mu_assert_notnull(set, "Set is not null variable");
mu_assert_eq(rz_set_s_size(set), 3, "Set size is 3");
it = rz_list_head(list);
elem = rz_list_val(it);
mu_assert_streq(elem, "r1", "list[0] is r1");
mu_assert_true(rz_set_s_contains(set, "r1"), "set contains r1");
mu_assert_true(rz_set_s_contains(set, "r2"), "set contains r2");
mu_assert_true(rz_set_s_contains(set, "r3"), "set contains r3");
rz_set_s_free(set);
it = rz_list_next(it);
elem = rz_list_val(it);
mu_assert_streq(elem, "r2", "list[1] is r2");
ret = rz_config_set_set2(cfg, "thy.set", "x0", "x1", "x2", "x3", "x4", NULL);
mu_assert_true(ret, "set thy.set");
it = rz_list_next(it);
elem = rz_list_val(it);
mu_assert_streq(elem, "r3", "list[2] is r3");
rz_list_free(list);
set = rz_config_get_set(cfg, "thy.set");
mu_assert_notnull(set, "Set is not null variable");
mu_assert_eq(rz_set_s_size(set), 5, "Set size is 5");
ret = rz_config_set_list2(cfg, "thy.list", "x0", "x1", "x2", "x3", "x4", NULL);
mu_assert_true(ret, "set thy.list");
mu_assert_true(rz_set_s_contains(set, "x0"), "set contains x0");
mu_assert_true(rz_set_s_contains(set, "x1"), "set contains x1");
mu_assert_true(rz_set_s_contains(set, "x2"), "set contains x2");
mu_assert_true(rz_set_s_contains(set, "x3"), "set contains x3");
mu_assert_true(rz_set_s_contains(set, "x4"), "set contains x4");
rz_set_s_free(set);
list = rz_config_get_list(cfg, "thy.list");
mu_assert_notnull(list, "List is not null variable");
mu_assert_eq(rz_list_length(list), 5, "List size is 5");
ret = rz_config_set_set3(cfg, "thy.set", "rax,rbx");
mu_assert_true(ret, "set thy.set as string");
char *s = rz_config_get_as_string(cfg, "thy.list");
mu_assert_streq(s, "x0,x1,x2,x3,x4", "get as string thy.list");
free(s);
set = rz_config_get_set(cfg, "thy.set");
mu_assert_notnull(set, "Set is not null variable");
mu_assert_eq(rz_set_s_size(set), 2, "Set size is 2");
mu_assert_true(rz_set_s_contains(set, "rax"), "set contains rax");
mu_assert_true(rz_set_s_contains(set, "rbx"), "set contains rbx");
rz_set_s_free(set);
elem = rz_list_first_val(list);
mu_assert_streq(elem, "x0", "list[first] is x0");
ret = rz_config_set_set(cfg, "thy.set", NULL);
mu_assert_true(ret, "set thy.set as string");
elem = rz_list_last_val(list);
mu_assert_streq(elem, "x4", "list[last] is x4");
rz_list_free(list);
ret = rz_config_set_list3(cfg, "thy.list", "rax,rbx");
mu_assert_true(ret, "set thy.list as string");
list = rz_config_get_list(cfg, "thy.list");
mu_assert_notnull(list, "List is not null variable");
mu_assert_eq(rz_list_length(list), 2, "List size is 2");
rz_list_free(list);
ret = rz_config_set_list(cfg, "thy.list", NULL);
mu_assert_true(ret, "set thy.list as string");
list = rz_config_get_list(cfg, "thy.list");
mu_assert_notnull(list, "List is not null variable");
mu_assert_eq(rz_list_length(list), 0, "List is empty");
rz_list_free(list);
set = rz_config_get_set(cfg, "thy.set");
mu_assert_notnull(set, "Set is not null variable");
mu_assert_eq(rz_set_s_size(set), 0, "Set is empty");
rz_set_s_free(set);
rz_config_free(cfg);
mu_end;
@ -360,7 +348,7 @@ bool test_config_invalid() {
RzConfig *cfg = rz_config_new(NULL);
mu_assert_null(rz_config_get_string(cfg, "string.here"), "string.here does not exist");
mu_assert_null(rz_config_get_list(cfg, "list.here"), "list.here does not exist");
mu_assert_null(rz_config_get_set(cfg, "set.here"), "set.here does not exist");
mu_assert_eq(rz_config_get_integer(cfg, "int.here"), 0, "int.here does not exist");
mu_assert_false(rz_config_get_bool(cfg, "bool.here"), "bool.here does not exist");
mu_assert_false(rz_config_set_validator(cfg, "self.validator", test_config_validator, &itv), "self.validator does not exist");
@ -378,7 +366,7 @@ typedef struct bind_test_s {
ut32 opts;
ut32 bind;
const void *set_val;
RzList *list;
RzSetS *set_val_set;
} bind_test_t;
static bool any_get(void *user, void *p) {
@ -402,9 +390,16 @@ static bool any_get(void *user, void *p) {
bt->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 /*<char *>*/ **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);