Here's my attempt to implement two new APIs to duplicate an svn_config_t
and a hash of those.
I factored out some code from svn_config_set into two new helper
functions which I then used in the new dup functions.
Please review.
Stefan
--
___
oo // \\ "De Chelonian Mobile"
(_,\/ \_/ \ TortoiseSVN
\ \_/_\_/> The coolest Interface to (Sub)Version Control
/_/ \_\ http://tortoisesvn.net
[[[
Add duplicate APIs for configuration objects and configuration
hashes.
* subversion/include/svn_config.h: Add two APIs named
svn_config_dup() and svn_config_copy_config().
* subversion/libsvn_subr/config.c
(svn_config_set): factor out code into svn_config_addsection and
svn_config_create_option.
(svn_config_addsection): new function to add a new section
to the svn_config_t object.
(svn_config_create_option): new function to create a new option.
(svn_config_dup): new function to create a duplicate of an
svn_config_t object.
(svn_config_copy_config): new function to create a duplicate
of an svn_config_t hash.
]]]
Index: include/svn_config.h
===================================================================
--- include/svn_config.h (revision 1381238)
+++ include/svn_config.h (working copy)
@@ -598,6 +598,26 @@
const char *fname,
apr_pool_t *pool);
+/** Create a deep copy of the config object @a src and return
+ * it in @a cfgp, allocating the memory in @a pool.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_config_dup(svn_config_t **cfgp,
+ svn_config_t *src,
+ apr_pool_t *pool);
+
+/** Create a deep copy of the config hash @a src_hash and return
+ * it in @a cfg_hash, allocating the memory in @a pool.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_config_copy_config(apr_hash_t **cfg_hash,
+ apr_hash_t *src_hash,
+ apr_pool_t *pool);
+
/** @} */
#ifdef __cplusplus
Index: libsvn_subr/config.c
===================================================================
--- libsvn_subr/config.c (revision 1381238)
+++ libsvn_subr/config.c (working copy)
@@ -554,7 +554,44 @@
*opt_x_valuep = NULL;
}
+static void
+svn_config_addsection(svn_config_t *cfg,
+ const char *section,
+ cfg_section_t **sec)
+{
+ cfg_section_t *s;
+ s = apr_palloc(cfg->pool, sizeof(cfg_section_t));
+ s->name = apr_pstrdup(cfg->pool, section);
+ if(cfg->section_names_case_sensitive)
+ s->hash_key = s->name;
+ else
+ s->hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
+ s->options = apr_hash_make(cfg->pool);
+ apr_hash_set(cfg->sections, s->hash_key, APR_HASH_KEY_STRING, s);
+
+ *sec = s;
+}
+
+static void
+svn_config_create_option(cfg_option_t **opt,
+ const char *option,
+ const char *value,
+ apr_pool_t *pool)
+{
+ cfg_option_t *o;
+
+ o = apr_palloc(pool, sizeof(cfg_option_t));
+ o->name = apr_pstrdup(pool, option);
+ o->hash_key = make_hash_key(apr_pstrdup(pool, option));
+
+ o->value = apr_pstrdup(pool, value);
+ o->x_value = NULL;
+ o->expanded = FALSE;
+
+ *opt = o;
+}
+
void
svn_config_get(svn_config_t *cfg, const char **valuep,
@@ -612,25 +649,12 @@
}
/* Create a new option */
- opt = apr_palloc(cfg->pool, sizeof(*opt));
- opt->name = apr_pstrdup(cfg->pool, option);
- opt->hash_key = make_hash_key(apr_pstrdup(cfg->pool, option));
+ svn_config_create_option(&opt, option, value, cfg->pool);
- opt->value = apr_pstrdup(cfg->pool, value);
- opt->x_value = NULL;
- opt->expanded = FALSE;
-
if (sec == NULL)
{
/* Even the section doesn't exist. Create it. */
- sec = apr_palloc(cfg->pool, sizeof(*sec));
- sec->name = apr_pstrdup(cfg->pool, section);
- if(cfg->section_names_case_sensitive)
- sec->hash_key = sec->name;
- else
- sec->hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
- sec->options = apr_hash_make(cfg->pool);
- apr_hash_set(cfg->sections, sec->hash_key, APR_HASH_KEY_STRING, sec);
+ svn_config_addsection(cfg, section, &sec);
}
apr_hash_set(sec->options, opt->hash_key, APR_HASH_KEY_STRING, opt);
@@ -976,3 +1000,94 @@
{
return apr_hash_get(cfg->sections, section, APR_HASH_KEY_STRING) != NULL;
}
+
+
+svn_error_t *
+svn_config_dup(svn_config_t **cfgp,
+ svn_config_t *src,
+ apr_pool_t *pool)
+{
+ const void *ckey = NULL;
+ void *cval = NULL;
+ apr_ssize_t ckeyLength = 0;
+ apr_hash_index_t *sectidx;
+ apr_hash_index_t *optidx;
+
+ *cfgp = 0;
+ SVN_ERR(svn_config_create(cfgp, FALSE, pool));
+
+ (*cfgp)->x_values = src->x_values;
+ (*cfgp)->section_names_case_sensitive = src->section_names_case_sensitive;
+
+ for (sectidx = apr_hash_first(pool, src->sections);
+ sectidx != NULL;
+ sectidx = apr_hash_next(sectidx))
+ {
+ const void *sectkey;
+ void *sectval;
+ apr_ssize_t sectkeyLength;
+ cfg_section_t * srcsect;
+ cfg_section_t * destsec;
+
+ apr_hash_this(sectidx, §key, §keyLength, §val);
+ srcsect = sectval;
+
+ svn_config_addsection(*cfgp, srcsect->name, &destsec);
+
+ for (optidx = apr_hash_first(pool, srcsect->options);
+ optidx != NULL;
+ optidx = apr_hash_next(optidx))
+ {
+ const void *optkey;
+ void *optval;
+ apr_ssize_t optkeyLength;
+ cfg_option_t *srcopt;
+ cfg_option_t *destopt;
+
+ apr_hash_this(optidx, &optkey, &optkeyLength, &optval);
+ srcopt = optval;
+
+ svn_config_create_option(&destopt, srcopt->name, srcopt->value, pool);
+
+ destopt->value = apr_pstrdup(pool, srcopt->value);
+ destopt->x_value = apr_pstrdup(pool, srcopt->x_value);
+ destopt->expanded = srcopt->expanded;
+ apr_hash_set(destsec->options,
+ apr_pstrdup(pool, (const char*)optkey),
+ optkeyLength, destopt);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_config_copy_config(apr_hash_t **cfg_hash,
+ apr_hash_t *src_hash,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *cidx;
+
+ *cfg_hash = apr_hash_make(pool);
+ for (cidx = apr_hash_first(pool, src_hash);
+ cidx != NULL;
+ cidx = apr_hash_next(cidx))
+ {
+ const void *ckey;
+ void *cval;
+ apr_ssize_t ckeyLength;
+ svn_config_t * srcconfig;
+ svn_config_t * destconfig;
+
+ apr_hash_this(cidx, &ckey, &ckeyLength, &cval);
+ srcconfig = cval;
+
+ SVN_ERR(svn_config_dup(&destconfig, srcconfig, pool));
+
+ apr_hash_set(*cfg_hash,
+ apr_pstrdup(pool, (const char*)ckey),
+ ckeyLength, destconfig);
+ }
+
+ return SVN_NO_ERROR;
+}