From 65f5fbc5d4457b68a304a68a52a41fecc0b25f15 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 4 Jun 2016 20:48:56 +0200 Subject: vo_opengl: somewhat simplify suboption handling mess Enable m_sub_options_copy() to copy nested sub-options, and also enable it to create an option struct from defaults. We can get rid of most of the crap in assign_options() now. Calling handle_scaler_opt() to get a static allocation for scaler name is still needed. It's moved to reinit_scaler(), which seems to be a better place for it. Without it, dangling pointers could be created when options are changed. (And in fact, this fixes possible dangling pointers for window.name.) In theory we could create a dynamic copy, but that seemed even more messy. Chance of regressions. --- options/m_config.c | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'options') diff --git a/options/m_config.c b/options/m_config.c index d58c406ed8..a3dcb30067 100644 --- a/options/m_config.c +++ b/options/m_config.c @@ -358,6 +358,18 @@ static void add_options(struct m_config *config, m_config_add_option(config, parent_name, optstruct, optstruct_def, &defs[i]); } +// Initialize a field with a given value. In case this is dynamic data, it has +// to be allocated and copied. src can alias dst, also can be NULL. +static void init_opt_inplace(const struct m_option *opt, void *dst, + const void *src) +{ + union m_option_value temp = {0}; + if (src) + memcpy(&temp, src, opt->type->size); + memset(dst, 0, opt->type->size); + m_option_copy(opt, dst, &temp); +} + static void m_config_add_option(struct m_config *config, const char *parent_name, void *optstruct, @@ -418,11 +430,7 @@ static void m_config_add_option(struct m_config *config, assert(0); } } - // In case this is dynamic data, it has to be allocated and copied. - union m_option_value temp = {0}; - memcpy(&temp, co.default_data, arg->type->size); - memset(co.data, 0, arg->type->size); - m_option_copy(arg, co.data, &temp); + init_opt_inplace(arg, co.data, co.default_data); } } @@ -942,24 +950,39 @@ static void free_substruct(void *ptr) } } +// Passing ptr==NULL initializes it from proper defaults. void *m_sub_options_copy(void *talloc_ctx, const struct m_sub_options *opts, const void *ptr) { - void *new = talloc_zero_size(talloc_ctx, opts->size); + void *new = m_config_alloc_struct(talloc_ctx, opts); struct dtor_info *dtor = talloc_ptrtype(new, dtor); *dtor = (struct dtor_info){opts, new}; talloc_set_destructor(dtor, free_substruct); - // also fill/initialize members not described by opts - if (opts->defaults) - memcpy(new, opts->defaults, opts->size); for (int n = 0; opts->opts && opts->opts[n].type; n++) { const struct m_option *opt = &opts->opts[n]; - // not implemented, because it adds lots of complexity - assert(!(opt->type->flags & M_OPT_TYPE_HAS_CHILD)); - void *src = (char *)ptr + opt->offset; + if (opt->offset < 0) + continue; + void *src = ptr ? (char *)ptr + opt->offset : NULL; void *dst = (char *)new + opt->offset; - memset(dst, 0, opt->type->size); - m_option_copy(opt, dst, src); + if (opt->type->flags & M_OPT_TYPE_HAS_CHILD) { + // Specifying a default struct for a sub-option field in the + // containing struct's default struct is not supported here. + // (Out of laziness. Could possibly be supported.) + assert(!substruct_read_ptr(dst)); + + const struct m_sub_options *subopts = opt->priv; + + const void *sub_src = NULL; + if (src) + sub_src = substruct_read_ptr(src); + if (!sub_src) + sub_src = subopts->defaults; + + void *sub_dst = m_sub_options_copy(new, subopts, sub_src); + substruct_write_ptr(dst, sub_dst); + } else { + init_opt_inplace(opt, dst, src); + } } return new; } -- cgit v1.2.3