commit:     e2ebb44db31d4e0e9bfc0a9974d36eff63c8b2b1
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Tue Feb  7 08:08:13 2023 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Tue Feb  7 08:08:13 2023 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=e2ebb44d

set: ensure NULL is empty behaviour is retained throughout

Not all set functions respected NULL is empty behaviour, changed
add_set_value signature to return a set instead so it can conform.

Bug: https://bugs.gentoo.org/893424
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/set.c  | 47 +++++++++++++++++++++++++++++++++++++++--------
 libq/set.h  |  4 ++--
 libq/tree.c |  5 +++--
 main.c      |  6 ++++--
 qkeyword.c  |  6 +++---
 qlop.c      | 12 ++++++++----
 6 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/libq/set.c b/libq/set.c
index 6c9fae0..fa485c7 100644
--- a/libq/set.c
+++ b/libq/set.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2019 Gentoo Foundation
+ * Copyright 2005-2023 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2010 Ned Ludd        - <so...@gentoo.org>
@@ -112,17 +112,22 @@ add_set_unique(const char *name, set *q, bool *unique)
 
 /* add ptr to set with name as key, return existing value when key
  * already exists or NULL otherwise */
-void *
-add_set_value(const char *name, void *ptr, set *q)
+set *
+add_set_value(const char *name, void *ptr, void **prevptr, set *q)
 {
        unsigned int hash;
        int pos;
        set_elem *ll;
        set_elem *w;
 
+       if (q == NULL)
+               q = create_set();
+
        hash = fnv1a32(name);
        pos = hash % _SET_HASH_SIZE;
 
+       if (prevptr != NULL)
+               *prevptr = NULL;
        if (q->buckets[pos] == NULL) {
                q->buckets[pos] = ll = xmalloc(sizeof(*ll));
                ll->next = NULL;
@@ -132,8 +137,11 @@ add_set_value(const char *name, void *ptr, set *q)
        } else {
                ll = NULL;
                for (w = q->buckets[pos]; w != NULL; ll = w, w = w->next) {
-                       if (w->hash == hash && strcmp(w->name, name) == 0)
-                               return w->val;
+                       if (w->hash == hash && strcmp(w->name, name) == 0) {
+                               if (prevptr != NULL)
+                                       *prevptr = w->val;
+                               return q;
+                       }
                }
                if (w == NULL) {
                        ll = ll->next = xmalloc(sizeof(*ll));
@@ -145,7 +153,7 @@ add_set_value(const char *name, void *ptr, set *q)
        }
 
        q->len++;
-       return NULL;
+       return q;
 }
 
 /* returns whether name is in set, and if so, the set-internal key
@@ -158,6 +166,9 @@ contains_set(const char *name, set *q)
        set_elem *w;
        const char *found;
 
+       if (q == NULL)
+               return NULL;
+
        hash = fnv1a32(name);
        pos = hash % _SET_HASH_SIZE;
 
@@ -183,6 +194,9 @@ get_set(const char *name, set *q)
        int pos;
        set_elem *w;
 
+       if (q == NULL)
+               return NULL;
+
        hash = fnv1a32(name);
        pos = hash % _SET_HASH_SIZE;
 
@@ -211,6 +225,12 @@ del_set(const char *s, set *q, bool *removed)
        void *ret;
        bool rmd;
 
+       if (q == NULL) {
+               if (removed != NULL)
+                       *removed = false;
+               return NULL;
+       }
+
        hash = fnv1a32(s);
        pos = hash % _SET_HASH_SIZE;
 
@@ -252,8 +272,8 @@ list_set(set *q, char ***l)
        set_elem *w;
        char **ret;
 
-       ret = *l = xmalloc(sizeof(char *) * (q->len + 1));
-       for (i = 0; i < _SET_HASH_SIZE; i++) {
+       ret = *l = xmalloc(sizeof(char *) * (cnt_set(q) + 1));
+       for (i = 0; q != NULL && i < _SET_HASH_SIZE; i++) {
                for (w = q->buckets[i]; w != NULL; w = w->next) {
                        *ret = w->name;
                        ret++;
@@ -292,6 +312,11 @@ values_set(set *q, array_t *ret)
        array_t blank = array_init_decl;
 
        *ret = blank;
+
+       /* allow using empty set */
+       if (q == NULL)
+               return 0;
+
        for (i = 0; i < _SET_HASH_SIZE; i++) {
                for (w = q->buckets[i]; w != NULL; w = w->next)
                        xarraypush_ptr(ret, w->val);
@@ -314,6 +339,9 @@ clear_set(set *q)
        set_elem *w;
        set_elem *e;
 
+       if (q == NULL)
+               return;
+
        for (i = 0; i < _SET_HASH_SIZE; i++) {
                for (w = q->buckets[i]; w != NULL; w = e) {
                        e = w->next;
@@ -329,6 +357,9 @@ clear_set(set *q)
 void
 free_set(set *q)
 {
+       if (q == NULL)
+               return;
+
        clear_set(q);
        free(q);
 }

diff --git a/libq/set.h b/libq/set.h
index 5d53f95..219602e 100644
--- a/libq/set.h
+++ b/libq/set.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2019 Gentoo Foundation
+ * Copyright 2005-2023 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  */
 
@@ -30,7 +30,7 @@ struct set_t {
 set *create_set(void);
 set *add_set(const char *name, set *q);
 set *add_set_unique(const char *name, set *q, bool *unique);
-void *add_set_value(const char *name, void *ptr, set *q);
+set *add_set_value(const char *name, void *ptr, void **prevptr, set *q);
 const char *contains_set(const char *name, set *q);
 void *get_set(const char *name, set *q);
 void *del_set(const char *s, set *q, bool *removed);

diff --git a/libq/tree.c b/libq/tree.c
index 76190ed..a05a86e 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -297,7 +297,8 @@ tree_open_cat(tree_ctx *ctx, const char *name)
        cat_ctx->pkg_cnt = 0;
 
        if (ctx->cache.categories != NULL) {
-               add_set_value(name, cat_ctx, ctx->cache.categories);
+               ctx->cache.categories =
+                       add_set_value(name, cat_ctx, NULL, 
ctx->cache.categories);
                /* ensure name doesn't expire after this instantiation is 
closed */
                cat_ctx->name = contains_set(name, ctx->cache.categories);
        }
@@ -1708,7 +1709,7 @@ tree_match_atom_cache_populate_cb(tree_pkg_ctx *ctx, void 
*priv)
        cat_ctx = get_set(atom->CATEGORY, cache);
        if (cat_ctx == NULL) {
                cat_ctx = tree_open_cat(tctx, ".");
-               add_set_value(atom->CATEGORY, cat_ctx, cache);
+               cache = add_set_value(atom->CATEGORY, cat_ctx, NULL, cache);
                /* get a pointer from the set */
                cat_ctx->name = contains_set(atom->CATEGORY, cache);
        }

diff --git a/main.c b/main.c
index 347a50b..c5b27fe 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2022 Gentoo Foundation
+ * Copyright 2005-2023 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2008 Ned Ludd        - <so...@gentoo.org>
@@ -581,10 +581,12 @@ read_portage_file(const char *file, enum 
portage_file_type type, void *data)
                                if ((p = del_set(buf + 1, masks, NULL)) != NULL)
                                        free(p);
                        } else {
+                               void *e;
                                snprintf(npath, sizeof(npath), "%s:%zu:%zu-%zu",
                                                file, line, cbeg, cend);
                                p = xstrdup(npath);
-                               if (add_set_value(buf, p, masks) != NULL)
+                               masks = add_set_value(buf, p, &e, masks);
+                               if (e != NULL)
                                        free(p);
                        }
                }

diff --git a/qkeyword.c b/qkeyword.c
index 5bc1010..4899d47 100644
--- a/qkeyword.c
+++ b/qkeyword.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2022 Gentoo Foundation
+ * Copyright 2005-2023 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2006      Thomas A. Cort - <tc...@gentoo.org>
@@ -913,8 +913,8 @@ int qkeyword_main(int argc, char **argv)
                                continue;
                        bucket = xzalloc(sizeof(array_t));
                        xarraypush_ptr(bucket, atom);
-                       ebuck = add_set_value(atom_format("%[CAT]%[PN]", atom),
-                                       bucket, pmasks);
+                       pmasks = add_set_value(atom_format("%[CAT]%[PN]", atom),
+                                                                  bucket, 
(void **)&ebuck, pmasks);
                        if (ebuck != NULL) {
                                xarraypush_ptr(ebuck, atom);
                                xarrayfree_int(bucket);

diff --git a/qlop.c b/qlop.c
index 16bf69f..3e6db53 100644
--- a/qlop.c
+++ b/qlop.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2022 Gentoo Foundation
+ * Copyright 2005-2023 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2010 Ned Ludd        - <so...@gentoo.org>
@@ -523,7 +523,7 @@ static int do_emerge_log(
                                        last_merge = tstart_emerge;
                                }
 
-                               atomw = add_set_value(afmt, atom, atomset);
+                               atomset = add_set_value(afmt, atom, (void 
**)&atomw, atomset);
                                if (atomw != NULL)
                                        atom_implode(atom);
                        }
@@ -807,7 +807,9 @@ static int do_emerge_log(
                                                                        
pkgw->atom->CATEGORY, pkgw->atom->PN);
                                                }
 
-                                               pkg = add_set_value(afmt, pkgw, 
merge_averages);
+                                               merge_averages =
+                                                       add_set_value(afmt, 
pkgw,
+                                                                               
  (void **)&pkg, merge_averages);
                                                if (pkg != NULL) {
                                                        pkg->cnt++;
                                                        pkg->time += elapsed;
@@ -952,7 +954,9 @@ static int do_emerge_log(
                                                                        
pkgw->atom->CATEGORY, pkgw->atom->PN);
                                                }
 
-                                               pkg = add_set_value(afmt, pkgw, 
unmerge_averages);
+                                               unmerge_averages =
+                                                       add_set_value(afmt, 
pkgw,
+                                                                               
  (void **)&pkg, unmerge_averages);
                                                if (pkg != NULL) {
                                                        pkg->cnt++;
                                                        pkg->time += elapsed;

Reply via email to