summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-06-09 23:46:53 +0200
committerwm4 <wm4@nowhere>2014-06-11 00:34:41 +0200
commit98c0930f9b69122996cc725a08336ee6bd9abc7e (patch)
tree655c8f95cbb1da28e694218dac559fd08a791756
parente033f3c8bcf66de44b0cc25e543a85f19fc9f964 (diff)
downloadmpv-98c0930f9b69122996cc725a08336ee6bd9abc7e.tar.bz2
mpv-98c0930f9b69122996cc725a08336ee6bd9abc7e.tar.xz
m_config: add function to copy subopt-struct
-rw-r--r--options/m_config.c37
-rw-r--r--options/m_config.h6
2 files changed, 43 insertions, 0 deletions
diff --git a/options/m_config.c b/options/m_config.c
index 857d6591b7..b0b06bc271 100644
--- a/options/m_config.c
+++ b/options/m_config.c
@@ -874,6 +874,43 @@ void *m_config_alloc_struct(void *talloc_ctx,
return substruct;
}
+struct dtor_info {
+ const struct m_sub_options *opts;
+ void *ptr;
+};
+
+static void free_substruct(void *ptr)
+{
+ struct dtor_info *d = ptr;
+ for (int n = 0; d->opts->opts && d->opts->opts[n].type; n++) {
+ const struct m_option *opt = &d->opts->opts[n];
+ void *dst = (char *)d->ptr + opt->offset;
+ m_option_free(opt, dst);
+ }
+}
+
+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);
+ 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;
+ void *dst = (char *)new + opt->offset;
+ memset(dst, 0, opt->type->size);
+ m_option_copy(opt, dst, src);
+ }
+ return new;
+}
+
// This is used for printing error messages on unknown options.
static const char *replaced_opts =
"|a52drc#--ad-lavc-ac3drc=level"
diff --git a/options/m_config.h b/options/m_config.h
index 5a6274b945..e20a99853f 100644
--- a/options/m_config.h
+++ b/options/m_config.h
@@ -237,4 +237,10 @@ void m_config_set_profile(struct m_config *config, struct m_profile *p,
void *m_config_alloc_struct(void *talloc_ctx,
const struct m_sub_options *subopts);
+// Create a copy of the struct ptr, described by opts.
+// "opts" must live until the struct is free'd.
+// Freeing the struct frees all members.
+void *m_sub_options_copy(void *talloc_ctx, const struct m_sub_options *opts,
+ const void *ptr);
+
#endif /* MPLAYER_M_CONFIG_H */