options: simplify somewhat by introducing a union for option values

The m_option_value union is supposed to contain a field for each
possible option type (as long as it actually stores data). This helps
avoiding silly temporary memory alocations. Using a pointer to an union
and to a field of the union interchangeably should be allowed by
standard C.
This commit is contained in:
wm4 2012-09-18 16:08:17 +02:00
parent 7fe56f1602
commit bfc3dbae88
3 changed files with 30 additions and 20 deletions

View File

@ -334,15 +334,14 @@ static void m_config_add_option(struct m_config *config,
} else if (arg->type->flags & M_OPT_TYPE_DYNAMIC) {
// Initialize dynamically managed fields from static data (like
// string options): copy the option into temporary memory,
// clear the original option (to void m_option freeing the
// clear the original option (to stop m_option from freeing the
// static data), copy it back.
if (co->data) {
void *temp = talloc_zero_size(NULL, arg->type->size);
m_option_copy(arg, temp, co->data);
union m_option_value temp = {0};
m_option_copy(arg, &temp, co->data);
memset(co->data, 0, arg->type->size);
m_option_copy(arg, co->data, temp);
m_option_free(arg, temp);
talloc_free(temp);
m_option_copy(arg, co->data, &temp);
m_option_free(arg, &temp);
}
}
}

View File

@ -178,6 +178,25 @@ struct m_sub_options {
#define CONF_TYPE_TIME (&m_option_type_time)
#define CONF_TYPE_TIME_SIZE (&m_option_type_time_size)
// Possible option values. Code is allowed to access option data without going
// through this union. It serves for self-documentation and to get minimal
// size/alignment requirements for option values in general.
union m_option_value {
int flag; // not the C type "bool"!
int int_;
int64_t int64;
float float_;
double double_;
char *string;
char **string_list;
int imgfmt;
int afmt;
m_span_t span;
m_obj_settings_t *obj_settings_list;
double time;
m_time_size_t time_size;
};
////////////////////////////////////////////////////////////////////////////
// Option type description

View File

@ -69,7 +69,7 @@ int m_property_do(const m_option_t *prop_list, const char *name,
int action, void *arg, void *ctx)
{
const m_option_t *opt;
void *val;
union m_option_value val = {0};
int r;
switch (action) {
@ -85,15 +85,11 @@ int m_property_do(const m_option_t *prop_list, const char *name,
if ((r =
do_action(prop_list, name, M_PROPERTY_GET_TYPE, &opt, ctx)) <= 0)
return r;
val = calloc(1, opt->type->size);
if ((r = do_action(prop_list, name, M_PROPERTY_GET, val, ctx)) <= 0) {
free(val);
if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
return r;
}
if (!arg)
return M_PROPERTY_ERROR;
char *str = m_option_print(opt, val);
free(val);
char *str = m_option_print(opt, &val);
*(char **)arg = str;
return str != NULL;
case M_PROPERTY_PARSE:
@ -107,14 +103,10 @@ int m_property_do(const m_option_t *prop_list, const char *name,
return r;
if (!arg)
return M_PROPERTY_ERROR;
val = calloc(1, opt->type->size);
if ((r = m_option_parse(opt, bstr0(opt->name), bstr0(arg), val)) <= 0) {
free(val);
if ((r = m_option_parse(opt, bstr0(opt->name), bstr0(arg), &val)) <= 0)
return r;
}
r = do_action(prop_list, name, M_PROPERTY_SET, val, ctx);
m_option_free(opt, val);
free(val);
r = do_action(prop_list, name, M_PROPERTY_SET, &val, ctx);
m_option_free(opt, &val);
return r;
}
return do_action(prop_list, name, action, arg, ctx);