aboutsummaryrefslogtreecommitdiff
path: root/src/list.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-08-25 16:06:58 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2016-08-25 16:06:58 +0300
commitc2f02c56a38a3e6d50b8ca2081db9d2de658b8ed (patch)
treea6c80fd81a6b5aad899d8fb0e3e41ece650eed9b /src/list.c
parent102d1b9c1a94548dfa0c498845c77933db6a7738 (diff)
downloadgrecs-c2f02c56a38a3e6d50b8ca2081db9d2de658b8ed.tar.gz
grecs-c2f02c56a38a3e6d50b8ca2081db9d2de658b8ed.tar.bz2
symtabs: allow to modify the list during iteration over it.
* include/grecs/list.h (grecs_list_remove): New proto. * include/grecs/symtab.h (grecs_symtab_count_entries): Rename to grecs_symtab_count. * src/list.c (grecs_list_remove): New function. (grecs_list_remove_tail, grecs_list_clear) (grecs_list_locate,grecs_list_index): Treat NULL list as empty list. * src/symtab.c: Defer table modifications during iteration (symtab_defer_type): New enum. (grecs_symtab)<elcount,itr_level,defer_list>: New members. (symtab_defer_op): New static function. (grecs_symtab_remove): When called during iteration, add the entry to the defer_del deferment list, unless it is already in defer_add, in which case remove it from there. Update elcount. (grecs_symtab_lookup_or_install): Defer addition when iterating. Update elcount. (grecs_symtab_clear): Reset elcount to 0. (grecs_symtab_create): Initialize elcount. (grecs_symtab_foreach): Process deferred modifications.
Diffstat (limited to 'src/list.c')
-rw-r--r--src/list.c84
1 files changed, 59 insertions, 25 deletions
diff --git a/src/list.c b/src/list.c
index b2d9f13..afd1b5d 100644
--- a/src/list.c
+++ b/src/list.c
@@ -86,6 +86,46 @@ grecs_list_remove_entry(struct grecs_list *lp, struct grecs_list_entry *ent)
lp->count--;
}
+void *
+grecs_list_remove_tail(struct grecs_list *lp)
+{
+ void *data;
+ struct grecs_list_entry *ep;
+
+ if (!lp || !lp->tail)
+ return NULL;
+ ep = lp->tail;
+ data = lp->tail->data;
+ grecs_list_remove_entry(lp, ep);
+ return data;
+}
+
+static int
+_ptrcmp(const void *a, const void *b)
+{
+ return a != b;
+}
+
+int
+grecs_list_remove(struct grecs_list *lp, void *data)
+{
+ struct grecs_list_entry *ep;
+ int (*cmp)(const void *, const void *);
+
+
+ if (!lp)
+ return 1;
+
+ cmp = lp->cmp ? lp->cmp : _ptrcmp;
+ for (ep = lp->head; ep; ep = ep->next) {
+ if (cmp(ep->data, data) == 0) {
+ grecs_list_remove_entry(lp, ep);
+ return 0;
+ }
+ }
+ return 1;
+}
+
void
grecs_list_append(struct grecs_list *lp, void *val)
{
@@ -123,7 +163,11 @@ void *
grecs_list_pop(struct grecs_list *lp)
{
void *data;
- struct grecs_list_entry *ep = lp->head;
+ struct grecs_list_entry *ep;
+
+ if (!lp)
+ return NULL;
+ ep = lp->head;
if (ep) {
data = ep->data;
grecs_list_remove_entry(lp, ep);
@@ -132,25 +176,14 @@ grecs_list_pop(struct grecs_list *lp)
return data;
}
-void *
-grecs_list_remove_tail(struct grecs_list *lp)
-{
- void *data;
- struct grecs_list_entry *ep;
-
- if (!lp->tail)
- return NULL;
- ep = lp->tail;
- data = lp->tail->data;
- grecs_list_remove_entry(lp, ep);
- return data;
-}
-
void
grecs_list_clear(struct grecs_list *lp)
{
- struct grecs_list_entry *ep = lp->head;
+ struct grecs_list_entry *ep;
+ if (!lp)
+ return;
+ ep = lp->head;
while (ep) {
struct grecs_list_entry *next = ep->next;
if (lp->free_entry)
@@ -171,17 +204,16 @@ grecs_list_free(struct grecs_list *lp)
}
}
-static int
-_ptrcmp(const void *a, const void *b)
-{
- return a != b;
-}
-
void *
grecs_list_locate(struct grecs_list *lp, void *data)
{
struct grecs_list_entry *ep;
- int (*cmp)(const void *, const void *) = lp->cmp ? lp->cmp : _ptrcmp;
+ int (*cmp)(const void *, const void *);
+
+ if (!lp)
+ return NULL;
+
+ cmp = lp->cmp ? lp->cmp : _ptrcmp;
for (ep = lp->head; ep; ep = ep->next) {
if (cmp(ep->data, data) == 0)
@@ -194,7 +226,9 @@ void *
grecs_list_index(struct grecs_list *lp, size_t idx)
{
struct grecs_list_entry *ep;
-
+
+ if (!lp)
+ return NULL;
for (ep = lp->head; ep && idx; ep = ep->next, idx--)
;
return ep ? ep->data : NULL;
@@ -219,7 +253,7 @@ grecs_list_compare(struct grecs_list *a, struct grecs_list *b)
cmp = a->cmp ? a->cmp : _ptrcmp;
for (ap = a->head, bp = b->head; ap; ap = ap->next, bp = bp->next)
- if (cmp (ap->data, bp->data))
+ if (cmp(ap->data, bp->data))
return 1;
return 0;

Return to:

Send suggestions and report system problems to the System administrator.