OSDN Git Service

Added snd_config_update_free_global().
authorJaroslav Kysela <perex@perex.cz>
Sat, 15 Dec 2001 19:50:36 +0000 (19:50 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sat, 15 Dec 2001 19:50:36 +0000 (19:50 +0000)
Added snd_config_delete_compound_members().
'const' changes.
Fixed memory leaks.

include/conf.h
src/conf.c
src/confmisc.c

index 6c868f3..5d2fe99 100644 (file)
@@ -73,6 +73,7 @@ int snd_config_save(snd_config_t *config, snd_output_t *out);
 int snd_config_update(void);
 int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const char *path);
 int snd_config_update_free(snd_config_update_t *update);
+int snd_config_update_free_global(void);
 
 int snd_config_search(snd_config_t *config, const char *key,
                      snd_config_t **result);
@@ -90,6 +91,7 @@ int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
 
 int snd_config_add(snd_config_t *config, snd_config_t *leaf);
 int snd_config_delete(snd_config_t *config);
+int snd_config_delete_compound_members(const snd_config_t *config);
 int snd_config_copy(snd_config_t **dst, snd_config_t *src);
 
 int snd_config_make(snd_config_t **config, const char *key,
@@ -105,7 +107,7 @@ int snd_config_imake_real(snd_config_t **config, const char *key, const double v
 int snd_config_imake_string(snd_config_t **config, const char *key, const char *ascii);
 int snd_config_imake_pointer(snd_config_t **config, const char *key, const void *ptr);
 
-snd_config_type_t snd_config_get_type(snd_config_t *config);
+snd_config_type_t snd_config_get_type(const snd_config_t *config);
 
 int snd_config_set_id(snd_config_t *config, const char *id);
 int snd_config_set_integer(snd_config_t *config, long value);
@@ -113,19 +115,19 @@ int snd_config_set_real(snd_config_t *config, double value);
 int snd_config_set_string(snd_config_t *config, const char *value);
 int snd_config_set_ascii(snd_config_t *config, const char *ascii);
 int snd_config_set_pointer(snd_config_t *config, const void *ptr);
-int snd_config_get_id(snd_config_t *config, const char **value);
-int snd_config_get_integer(snd_config_t *config, long *value);
-int snd_config_get_real(snd_config_t *config, double *value);
-int snd_config_get_ireal(snd_config_t *config, double *value);
-int snd_config_get_string(snd_config_t *config, const char **value);
-int snd_config_get_ascii(snd_config_t *config, char **value);
-int snd_config_get_pointer(snd_config_t *config, const void **value);
-int snd_config_test_id(snd_config_t *config, const char *id);
-
-snd_config_iterator_t snd_config_iterator_first(snd_config_t *node);
-snd_config_iterator_t snd_config_iterator_next(snd_config_iterator_t iterator);
-snd_config_iterator_t snd_config_iterator_end(snd_config_t *node);
-snd_config_t *snd_config_iterator_entry(snd_config_iterator_t iterator);
+int snd_config_get_id(const snd_config_t *config, const char **value);
+int snd_config_get_integer(const snd_config_t *config, long *value);
+int snd_config_get_real(const snd_config_t *config, double *value);
+int snd_config_get_ireal(const snd_config_t *config, double *value);
+int snd_config_get_string(const snd_config_t *config, const char **value);
+int snd_config_get_ascii(const snd_config_t *config, char **value);
+int snd_config_get_pointer(const snd_config_t *config, const void **value);
+int snd_config_test_id(const snd_config_t *config, const char *id);
+
+const snd_config_iterator_t snd_config_iterator_first(const snd_config_t *node);
+const snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator);
+const snd_config_iterator_t snd_config_iterator_end(const snd_config_t *node);
+snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator);
 
 /** Helper for compound config node leaves traversal
  * \param pos Current node iterator
@@ -140,9 +142,9 @@ snd_config_t *snd_config_iterator_entry(snd_config_iterator_t iterator);
 /* Misc functions */
 
 int snd_config_get_bool_ascii(const char *ascii);
-int snd_config_get_bool(snd_config_t *conf);
+int snd_config_get_bool(const snd_config_t *conf);
 int snd_config_get_ctl_iface_ascii(const char *ascii);
-int snd_config_get_ctl_iface(snd_config_t *conf);
+int snd_config_get_ctl_iface(const snd_config_t *conf);
 
 /** \} */
 
index 6e554b0..9eb3488 100644 (file)
@@ -484,8 +484,10 @@ static int get_char_skip_comments(input_t *input)
                                return err;
                        }
                        fd = malloc(sizeof(*fd));
-                       if (!fd)
+                       if (!fd) {
+                               free(str);
                                return -ENOMEM;
+                       }
                        fd->name = str;
                        fd->in = in;
                        fd->next = input->current;
@@ -1272,11 +1274,19 @@ static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsi
  * \param dst Destination node
  * \param src Source node (invalid after call)
  * \return zero if success, otherwise a negative error code
+ *
+ * If both nodes are compounds, the source compound node members are
+ * appended to the destination compound node.
+ *
+ * If the destination node is a compound and the source node is
+ * an ordinary type, the compound members are deleted (including
+ * contents).
  */
 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
 {
        assert(dst && src);
-       if (src->type == SND_CONFIG_TYPE_COMPOUND) {    /* append */
+       if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
+           src->type == SND_CONFIG_TYPE_COMPOUND) {    /* append */
                snd_config_iterator_t i, next;
                snd_config_for_each(i, next, src) {
                        snd_config_t *n = snd_config_iterator_entry(i);
@@ -1284,6 +1294,11 @@ int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
                }
                src->u.compound.fields.next->prev = &dst->u.compound.fields;
                src->u.compound.fields.prev->next = &dst->u.compound.fields;
+       } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
+               int err;
+               err = snd_config_delete_compound_members(dst);
+               if (err < 0)
+                       return err;
        }
        if (dst->id)
                free(dst->id);
@@ -1326,7 +1341,7 @@ int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
  * \param config Config node handle
  * \return node type
  */
-snd_config_type_t snd_config_get_type(snd_config_t *config)
+snd_config_type_t snd_config_get_type(const snd_config_t *config)
 {
        return config->type;
 }
@@ -1337,7 +1352,7 @@ snd_config_type_t snd_config_get_type(snd_config_t *config)
  * \param value The result id
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_id(snd_config_t *config, const char **id)
+int snd_config_get_id(const snd_config_t *config, const char **id)
 {
        assert(config && id);
        *id = config->id;
@@ -1352,7 +1367,9 @@ int snd_config_get_id(snd_config_t *config, const char **id)
  */
 int snd_config_set_id(snd_config_t *config, const char *id)
 {
-       free(config->id);
+       assert(config && id);
+       if (config->id)
+               free(config->id);
        config->id = strdup(id);
        if (!config->id)
                return -ENOMEM;
@@ -1380,7 +1397,7 @@ int snd_config_load(snd_config_t *config, snd_input_t *in)
 {
        int err;
        input_t input;
-       struct filedesc *fd;
+       struct filedesc *fd, *fd_next;
        assert(config && in);
        fd = malloc(sizeof(*fd));
        if (!fd)
@@ -1423,10 +1440,11 @@ int snd_config_load(snd_config_t *config, snd_input_t *in)
        }
  _end:
        while (fd->next) {
+               fd_next = fd->next;
                snd_input_close(fd->in);
                free(fd->name);
                free(fd);
-               fd = fd->next;
+               fd = fd_next;
        }
        free(fd);
        return err;
@@ -1499,12 +1517,38 @@ int snd_config_delete(snd_config_t *config)
        }
        if (config->father)
                list_del(&config->list);
-       free(config->id);
+       if (config->id)
+               free(config->id);
        free(config);
        return 0;
 }
 
 /**
+ * \brief Remove a compound config node members (freeing all the related resources)
+ * \param config Compound config node handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_config_delete_compound_members(const snd_config_t *config)
+{
+       int err;
+       struct list_head *i;
+
+       assert(config);
+       if (config->type != SND_CONFIG_TYPE_COMPOUND)
+               return -EINVAL;
+       i = config->u.compound.fields.next;
+       while (i != &config->u.compound.fields) {
+               struct list_head *nexti = i->next;
+               snd_config_t *leaf = snd_config_iterator_entry(i);
+               err = snd_config_delete(leaf);
+               if (err < 0)
+                       return err;
+               i = nexti;
+       }
+       return 0;
+}
+
+/**
  * \brief Build a config node
  * \param config Returned config node handle pointer
  * \param id Node id
@@ -1785,7 +1829,7 @@ int snd_config_set_ascii(snd_config_t *config, const char *ascii)
  * \param ptr Returned value pointer
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_integer(snd_config_t *config, long *ptr)
+int snd_config_get_integer(const snd_config_t *config, long *ptr)
 {
        assert(config && ptr);
        if (config->type != SND_CONFIG_TYPE_INTEGER)
@@ -1800,7 +1844,7 @@ int snd_config_get_integer(snd_config_t *config, long *ptr)
  * \param ptr Returned value pointer
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_real(snd_config_t *config, double *ptr)
+int snd_config_get_real(const snd_config_t *config, double *ptr)
 {
        assert(config && ptr);
        if (config->type != SND_CONFIG_TYPE_REAL)
@@ -1818,7 +1862,7 @@ int snd_config_get_real(snd_config_t *config, double *ptr)
  * Note: If the config type is integer, it is converted
  * to the double type on the fly.
  */
-int snd_config_get_ireal(snd_config_t *config, double *ptr)
+int snd_config_get_ireal(const snd_config_t *config, double *ptr)
 {
        assert(config && ptr);
        if (config->type == SND_CONFIG_TYPE_REAL)
@@ -1836,7 +1880,7 @@ int snd_config_get_ireal(snd_config_t *config, double *ptr)
  * \param ptr Returned value pointer
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_string(snd_config_t *config, const char **ptr)
+int snd_config_get_string(const snd_config_t *config, const char **ptr)
 {
        assert(config && ptr);
        if (config->type != SND_CONFIG_TYPE_STRING)
@@ -1851,7 +1895,7 @@ int snd_config_get_string(snd_config_t *config, const char **ptr)
  * \param ptr Returned value pointer
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_pointer(snd_config_t *config, const void **ptr)
+int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
 {
        assert(config && ptr);
        if (config->type != SND_CONFIG_TYPE_POINTER)
@@ -1866,7 +1910,7 @@ int snd_config_get_pointer(snd_config_t *config, const void **ptr)
  * \param ascii Returned dynamically allocated ASCII string
  * \return 0 on success otherwise a negative error code
  */
-int snd_config_get_ascii(snd_config_t *config, char **ascii)
+int snd_config_get_ascii(const snd_config_t *config, char **ascii)
 {
        assert(config && ascii);
        switch (config->type) {
@@ -1920,7 +1964,7 @@ int snd_config_get_ascii(snd_config_t *config, char **ascii)
  * \param id ASCII id
  * \return the same value as result of the strcmp function
  */
-int snd_config_test_id(snd_config_t *config, const char *id)
+int snd_config_test_id(const snd_config_t *config, const char *id)
 {
        assert(config && id);
        return strcmp(config->id, id);
@@ -1935,7 +1979,10 @@ int snd_config_test_id(snd_config_t *config, const char *id)
 int snd_config_save(snd_config_t *config, snd_output_t *out)
 {
        assert(config && out);
-       return _snd_config_save_leaves(config, out, 0, 0);
+       if (config->type == SND_CONFIG_TYPE_COMPOUND)
+               return _snd_config_save_leaves(config, out, 0, 0);
+       else
+               return _snd_config_save_leaf(config, out, 0);
 }
 
 /*
@@ -2302,7 +2349,7 @@ static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_c
                        SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
                snd_dlclose(h);
                if (err >= 0 && nroot)
-                       snd_config_substitute(root, nroot);
+                       err = snd_config_substitute(root, nroot);
        }
        if (buf)
                free(buf);
@@ -2357,7 +2404,7 @@ static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
  */
 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
 {
-       snd_config_t *n, *res = NULL;
+       snd_config_t *n;
        snd_config_iterator_t i, next;
        struct finfo *fi = NULL;
        int err, idx = 0, fi_count = 0, errors = 1, hit;
@@ -2443,9 +2490,6 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
                        }
                }
        } while (hit);
-       err = snd_config_top(&res);
-       if (err < 0)
-               goto _err;
        for (idx = 0; idx < fi_count; idx++) {
                snd_input_t *in;
                if (!errors && access(fi[idx].name, R_OK) < 0)
@@ -2463,7 +2507,6 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
                }
        }
        *dst = NULL;
-       res = NULL;
        err = 0;
        _err:
        for (idx = 0; idx < fi_count; idx++)
@@ -2471,8 +2514,6 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
                                free(fi[idx].name);
                if (fi)
                        free(fi);
-               if (res)
-                       snd_config_delete(res);
        snd_config_delete(n);
        return err;
 }
@@ -2740,7 +2781,7 @@ int snd_config_update(void)
  */
 int snd_config_update_free(snd_config_update_t *update)
 {
-       int k;
+       unsigned int k;
 
        assert(update);
        assert(update->count > 0 && update->finfo);
@@ -2752,12 +2793,29 @@ int snd_config_update_free(snd_config_update_t *update)
        return 0;
 }
 
+/** 
+ * \brief Free global configuration in snd_config
+ * \return non-negative value on success, otherwise a negative error code
+ */
+int snd_config_update_free_global(void)
+{
+       pthread_mutex_lock(&snd_config_update_mutex);
+       if (snd_config)
+               snd_config_delete(snd_config);
+       snd_config = NULL;
+       if (snd_config_global_update)
+               snd_config_update_free(snd_config_global_update);
+       snd_config_global_update = NULL;
+       pthread_mutex_unlock(&snd_config_update_mutex);
+       return 0;
+}
+
 /**
  * \brief Return an iterator pointing to first leaf of a compound config node
  * \param node Config node handle
  * \return iterator value for first leaf
  */
-snd_config_iterator_t snd_config_iterator_first(snd_config_t *node)
+const snd_config_iterator_t snd_config_iterator_first(const snd_config_t *node)
 {
        assert(node->type == SND_CONFIG_TYPE_COMPOUND);
        return node->u.compound.fields.next;
@@ -2768,7 +2826,7 @@ snd_config_iterator_t snd_config_iterator_first(snd_config_t *node)
  * \param iterator Config node iterator
  * \return iterator value for next leaf
  */
-snd_config_iterator_t snd_config_iterator_next(snd_config_iterator_t iterator)
+const snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
 {
        return iterator->next;
 }
@@ -2778,10 +2836,10 @@ snd_config_iterator_t snd_config_iterator_next(snd_config_iterator_t iterator)
  * \param node Config node handle
  * \return iterator value for end
  */
-snd_config_iterator_t snd_config_iterator_end(snd_config_t *node)
+const snd_config_iterator_t snd_config_iterator_end(const snd_config_t *node)
 {
        assert(node->type == SND_CONFIG_TYPE_COMPOUND);
-       return &node->u.compound.fields;
+       return (const snd_config_iterator_t)&node->u.compound.fields;
 }
 
 /**
@@ -2789,7 +2847,7 @@ snd_config_iterator_t snd_config_iterator_end(snd_config_t *node)
  * \param iterator Config node iterator
  * \return config node handle
  */
-snd_config_t *snd_config_iterator_entry(snd_config_iterator_t iterator)
+snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
 {
        return list_entry(iterator, snd_config_t, list);
 }
@@ -2820,6 +2878,7 @@ static int snd_config_walk(snd_config_t *src,
 {
        int err;
        snd_config_iterator_t i, next;
+
        switch (snd_config_get_type(src)) {
        case SND_CONFIG_TYPE_COMPOUND:
                err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
@@ -3063,11 +3122,13 @@ static int _snd_config_evaluate(snd_config_t *src,
                err = 0;
                if (!h) {
                        SNDERR("Cannot open shared library %s", lib);
-                       return -ENOENT;
+                       err = -ENOENT;
+                       goto _errbuf;
                } else if (!func) {
                        SNDERR("symbol %s is not defined inside %s", func_name, lib);
                        snd_dlclose(h);
-                       return -ENXIO;
+                       err = -ENXIO;
+                       goto _errbuf;
                }
               _err:
                if (func_conf)
@@ -3078,9 +3139,15 @@ static int _snd_config_evaluate(snd_config_t *src,
                        if (err < 0)
                                SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
                        snd_dlclose(h);
-                       if (err >= 0 && eval)
-                               snd_config_substitute(src, eval);
+                       if (err >= 0 && eval) {
+                               /* substitute merges compound members */
+                               /* we don't want merging at all */
+                               err = snd_config_delete_compound_members(src);
+                               if (err >= 0)
+                                       err = snd_config_substitute(src, eval);
+                       }
                }
+              _errbuf:
                if (buf)
                        free(buf);
                if (err < 0)
@@ -3131,8 +3198,10 @@ static int load_defaults(snd_config_t *subs, snd_config_t *defs)
                                        return err;
                                }
                                err = snd_config_add(subs, deflt);
-                               if (err < 0)
+                               if (err < 0) {
+                                       snd_config_delete(deflt);
                                        return err;
+                               }
                                continue;
                        }
                        SNDERR("Unknown field %s", id);
@@ -3266,8 +3335,9 @@ static int parse_string(const char **ptr, char **val)
                        if (old_alloc == bufsize) {
                                buf = malloc(alloc);
                                memcpy(buf, _buf, old_alloc);
-                       } else
+                       } else {
                                buf = realloc(buf, alloc);
+                       }
                        if (!buf)
                                return -ENOMEM;
                }
index 30e4207..0afecab 100644 (file)
@@ -105,7 +105,7 @@ int snd_config_get_bool_ascii(const char *ascii)
  * \param conf The configuration node to be parsed
  * \return a positive value when success otherwise a negative error number
  */
-int snd_config_get_bool(snd_config_t *conf)
+int snd_config_get_bool(const snd_config_t *conf)
 {
        long v;
        const char *str, *id;
@@ -162,7 +162,7 @@ int snd_config_get_ctl_iface_ascii(const char *ascii)
  * \param conf The configuration node to be parsed
  * \return a positive value when success otherwise a negative error number
  */ 
-int snd_config_get_ctl_iface(snd_config_t *conf)
+int snd_config_get_ctl_iface(const snd_config_t *conf)
 {
        long v;
        const char *str, *id;
@@ -325,11 +325,16 @@ int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
        if (err < 0)
                return err;
        err = snd_config_get_string(d, &str);
-       if (err < 0)
+       if (err < 0) {
+               snd_config_delete(d);
                return err;
+       }
        err = safe_strtol(str, &v);
-       if (err < 0)
-               return err;;
+       if (err < 0) {
+               snd_config_delete(d);
+               return err;
+       }
+       snd_config_delete(d);
        err = snd_config_get_id(src, &id);
        if (err < 0)
                return err;