Attached is my first draft of the new svn_config_dup() API.
* it does not return an svn_error_t but the duplicate hash directly. The
only API call that could return an error is svn_config_create() but that
API also returns SVN_NO_ERROR unconditionally (for now at least).
* no error checking is done for now, will add some checks for failed
memory allocations later.
* hash keys are duplicated as well (allocated in the passed pool)
Please have a look at this. I think it's correct, at least my first
tests show that it works and solves my problem in TSVN with multiple
threads as well.
be back tomorrow...
Stefan
--
___
oo // \\ "De Chelonian Mobile"
(_,\/ \_/ \ TortoiseSVN
\ \_/_\_/> The coolest Interface to (Sub)Version Control
/_/ \_\ http://tortoisesvn.net
Index: subversion/include/svn_config.h
===================================================================
--- subversion/include/svn_config.h (revision 1380737)
+++ subversion/include/svn_config.h (working copy)
@@ -626,6 +626,16 @@
const char *fname,
apr_pool_t *pool);
+/** Return a deep copy of the config hash.
+ * @note use this function instead of repeated calls
+ * to svn_config_get_config to avoid reading the config file
+ * over and over.
+ *
+ * @since New in 1.8.
+ */
+apr_hash_t *
+svn_config_dup(apr_hash_t * config, apr_pool_t * pool);
+
/** @} */
#ifdef __cplusplus
Index: subversion/libsvn_subr/config.c
===================================================================
--- subversion/libsvn_subr/config.c (revision 1380737)
+++ subversion/libsvn_subr/config.c (working copy)
@@ -1011,3 +1011,88 @@
sec = apr_hash_get(cfg->sections, cfg->tmp_key->data, APR_HASH_KEY_STRING);
return sec != NULL;
}
+
+
+apr_hash_t *
+svn_config_dup(apr_hash_t * config, apr_pool_t * pool)
+{
+ apr_hash_t * rethash;
+ apr_hash_index_t * cidx;
+ apr_hash_index_t * sectidx;
+ apr_hash_index_t * optidx;
+
+ rethash = apr_hash_make(pool);
+ for (cidx = apr_hash_first(pool, config);
+ cidx != NULL;
+ cidx = apr_hash_next(cidx))
+ {
+ const void *ckey = NULL;
+ void *cval = NULL;
+ apr_ssize_t ckeyLength = 0;
+ svn_config_t * c;
+ svn_config_t * newconfig = NULL;
+
+ svn_config_create(&newconfig, FALSE, pool);
+
+ apr_hash_this(cidx, &ckey, &ckeyLength, &cval);
+ c = cval;
+
+ newconfig->sections = apr_hash_make(pool);
+ newconfig->pool = pool;
+ newconfig->x_pool = svn_pool_create(pool);
+ newconfig->x_values = c->x_values;
+ newconfig->tmp_key = svn_stringbuf_dup(c->tmp_key, pool);
+ newconfig->tmp_value = svn_stringbuf_dup(c->tmp_value, pool);
+ newconfig->section_names_case_sensitive = c->section_names_case_sensitive;
+
+ for (sectidx = apr_hash_first(pool, c->sections);
+ sectidx != NULL;
+ sectidx = apr_hash_next(sectidx))
+ {
+ const void *sectkey = NULL;
+ void *sectval = NULL;
+ apr_ssize_t sectkeyLength = 0;
+ cfg_section_t * sect;
+ cfg_section_t * newsec;
+
+ apr_hash_this(sectidx, §key, §keyLength, §val);
+ sect = sectval;
+
+ newsec = apr_palloc(pool, sizeof(*newsec));
+ newsec->name = apr_pstrdup(pool, sect->name);
+ newsec->hash_key = apr_pstrdup(pool, sect->hash_key);
+ newsec->options = apr_hash_make(pool);
+ for (optidx = apr_hash_first(pool, sect->options);
+ optidx != NULL;
+ optidx = apr_hash_next(optidx))
+ {
+ const void *optkey = NULL;
+ void *optval = NULL;
+ apr_ssize_t optkeyLength = 0;
+ cfg_option_t * opt;
+ cfg_option_t * newopt;
+
+ apr_hash_this(optidx, &optkey, &optkeyLength, &optval);
+ opt = optval;
+
+ newopt = apr_palloc(pool, sizeof(*newopt));
+ newopt->name = apr_pstrdup(pool, opt->name);
+ newopt->hash_key = apr_pstrdup(pool, opt->hash_key);
+ newopt->value = apr_pstrdup(pool, opt->value);
+ newopt->x_value = apr_pstrdup(pool, opt->x_value);
+ newopt->expanded = opt->expanded;
+ apr_hash_set(newsec->options,
+ apr_pstrdup(pool, (const char*)optkey),
+ optkeyLength, newopt);
+ }
+ apr_hash_set(newconfig->sections,
+ apr_pstrdup(pool, (const char*)sectkey),
+ sectkeyLength, newsec);
+ }
+ apr_hash_set(rethash,
+ apr_pstrdup(pool, (const char*)ckey),
+ ckeyLength, newconfig);
+ }
+
+ return rethash;
+}