From bfc3dbae88dc70a832e82c5b44474fdf5a5e65a5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 18 Sep 2012 16:08:17 +0200 Subject: 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. --- m_config.c | 11 +++++------ m_option.h | 19 +++++++++++++++++++ m_property.c | 20 ++++++-------------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/m_config.c b/m_config.c index ae7f528060..11272766d2 100644 --- a/m_config.c +++ b/m_config.c @@ -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); } } } diff --git a/m_option.h b/m_option.h index f05fe17bd4..2bd9054ac2 100644 --- a/m_option.h +++ b/m_option.h @@ -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 diff --git a/m_property.c b/m_property.c index e75cbe43ac..ac68d86163 100644 --- a/m_property.c +++ b/m_property.c @@ -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); -- cgit v1.2.3