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, &sectkey, &sectkeyLength, &sectval);
+    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;
+}

Reply via email to