aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2023-02-07 09:08:13 +0100
committerFabian Groffen <grobian@gentoo.org>2023-02-07 09:08:13 +0100
commite2ebb44db31d4e0e9bfc0a9974d36eff63c8b2b1 (patch)
tree992157f1f78251bd617bf445c6b818a2314440dd
parentqmerge: add some braindump notes about how things could be (diff)
downloadportage-utils-e2ebb44db31d4e0e9bfc0a9974d36eff63c8b2b1.tar.gz
portage-utils-e2ebb44db31d4e0e9bfc0a9974d36eff63c8b2b1.tar.bz2
portage-utils-e2ebb44db31d4e0e9bfc0a9974d36eff63c8b2b1.zip
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@gentoo.org>
-rw-r--r--libq/set.c47
-rw-r--r--libq/set.h4
-rw-r--r--libq/tree.c5
-rw-r--r--main.c6
-rw-r--r--qkeyword.c6
-rw-r--r--qlop.c12
6 files changed, 59 insertions, 21 deletions
diff --git a/libq/set.c b/libq/set.c
index 6c9fae0e..fa485c75 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 - <solar@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 5d53f957..219602e0 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 76190ed3..a05a86e2 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 347a50bb..c5b27fe2 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 - <solar@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 5bc10108..4899d47a 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 - <tcort@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 16bf69f4..3e6db53a 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 - <solar@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;