Change ez_node to use anonymous unions/structs for convenience.
authorNot Zed <notzed@gmail.com>
Tue, 23 Jul 2024 04:26:49 +0000 (13:56 +0930)
committerNot Zed <notzed@gmail.com>
Tue, 23 Jul 2024 04:26:49 +0000 (13:56 +0930)
ez-list.h
ez-node.h
ez-set.c
ez-tree.c
ez-tree.h
test-tree.c

index 5e67e6f..d3494eb 100644 (file)
--- a/ez-list.h
+++ b/ez-list.h
@@ -23,7 +23,7 @@
 
 /**
  * ez-list is a low-level double-linked list implementation that works
- * without memory allocation.  
+ * without memory allocation.
  *
  * o Adding to or removing from either end is an O(1) operation.
  * o Removing any given node is an O(1) operation.
@@ -94,9 +94,9 @@ struct ez_list {
 
 /**
  * Initialise a list at runtime.
- * 
+ *
  */
-static __inline__ void ez_list_init(struct ez_list *l) {
+static __inline__ void ez_list_init(struct ez_list * __restrict l) {
        l->head = (struct ez_node *)&l->tail;
        l->tail = (struct ez_node *)0L;
        l->tail_pred = (struct ez_node *)&l->head;
@@ -105,12 +105,12 @@ static __inline__ void ez_list_init(struct ez_list *l) {
 /**
  * Add a node to the head of the list.
  */
-static __inline__ void ez_list_addhead(struct ez_list *l, void *np) {
+static __inline__ void ez_list_addhead(struct ez_list * __restrict l, void *np) {
        struct ez_node *n = np, *head = l->head;
 
-       n->u.list.succ = head;
-       n->u.list.pred = (struct ez_node *)&l->head;
-       head->u.list.pred = n;
+       n->succ = head;
+       n->pred = (struct ez_node *)&l->head;
+       head->pred = n;
        l->head = n;
 }
 
@@ -120,9 +120,9 @@ static __inline__ void ez_list_addhead(struct ez_list *l, void *np) {
 static __inline__ void ez_list_addtail(struct ez_list *l, void *np) {
        struct ez_node *n = np, *tail_pred = l->tail_pred;
 
-       n->u.list.pred = tail_pred;
-       n->u.list.succ = (struct ez_node *)&l->tail;
-       tail_pred->u.list.succ = n;
+       n->pred = tail_pred;
+       n->succ = (struct ez_node *)&l->tail;
+       tail_pred->succ = n;
        l->tail_pred = n;
 }
 
@@ -134,11 +134,11 @@ static __inline__ void ez_list_addtail(struct ez_list *l, void *np) {
  * This performs a software memory barrier after
  * write do workaround aliasing issues with gcc.
  */
-static __inline__ void ez_node_remove(void *np) {
-       struct ez_node *n = np, *pred = n->u.list.pred, *succ = n->u.list.succ;
-       
-       pred->u.list.succ = succ;
-       succ->u.list.pred = pred;
+static __inline__ void ez_node_remove(void * __restrict np) {
+       struct ez_node *n = np, *pred = n->pred, *succ = n->succ;
+
+       pred->succ = succ;
+       succ->pred = pred;
 }
 
 /**
@@ -146,12 +146,12 @@ static __inline__ void ez_node_remove(void *np) {
  *
  * @return the head node, or NULL if the list is empty.
  */
-static __inline__ void *ez_list_remhead(struct ez_list *l) {
+static __inline__ void *ez_list_remhead(struct ez_list * __restrict l) {
        struct ez_node *n = l->head;
-       struct ez_node *s = n->u.list.succ;
+       struct ez_node *s = n->succ;
 
        if (s) {
-               s->u.list.pred = (struct ez_node *)&l->head;
+               s->pred = (struct ez_node *)&l->head;
                l->head = s;
                return n;
        } else
@@ -163,12 +163,12 @@ static __inline__ void *ez_list_remhead(struct ez_list *l) {
  *
  * @return the tail node, or NULL if the list is empty.
  */
-static __inline__ void *ez_list_remtail(struct ez_list *l) {
+static __inline__ void *ez_list_remtail(struct ez_list * __restrict l) {
        struct ez_node *n = l->tail_pred;
-       struct ez_node *p = n->u.list.pred;
+       struct ez_node *p = n->pred;
 
        if (p) {
-               p->u.list.succ = (struct ez_node *)&l->tail;
+               p->succ = (struct ez_node *)&l->tail;
                l->tail_pred = p;
                return n;
        } else
@@ -182,15 +182,15 @@ static __inline__ void *ez_list_remtail(struct ez_list *l) {
  * @param n node to insert.
  * @param p node that is already present in list, or NULL (insert after head).
  */
-static __inline__ void ez_list_insert_after(struct ez_list *l, void *n, void *p) {
+static __inline__ void ez_list_insert_after(struct ez_list * __restrict l, void *n, void *p) {
        struct ez_node *nn = n;
        struct ez_node *pp = p ? p : (struct ez_node *)&l->head;
-       struct ez_node *succ = pp->u.list.succ;
+       struct ez_node *succ = pp->succ;
 
-       nn->u.list.succ = succ;
-       nn->u.list.pred = pp;
-       succ->u.list.pred = nn;
-       pp->u.list.succ = nn;
+       nn->succ = succ;
+       nn->pred = pp;
+       succ->pred = nn;
+       pp->succ = nn;
 }
 
 /**
@@ -200,15 +200,15 @@ static __inline__ void ez_list_insert_after(struct ez_list *l, void *n, void *p)
  * @param n node to insert.
  * @param p node that is already present in list, or NULL (insert before tail).
  */
-static __inline__ void ez_list_insert(struct ez_list *l, void *n, void *p) {
+static __inline__ void ez_list_insert(struct ez_list * __restrict l, void *n, void *p) {
        struct ez_node *nn = n;
        struct ez_node *pp = p ? p : (struct ez_node *)&l->tail;
-       struct ez_node *pred = pp->u.list.pred;
-       
-       nn->u.list.succ = pp;
-       nn->u.list.pred = pred;
-       pred->u.list.succ = nn;
-       pp->u.list.pred = nn;
+       struct ez_node *pred = pp->pred;
+
+       nn->succ = pp;
+       nn->pred = pred;
+       pred->succ = nn;
+       pp->pred = nn;
 }
 
 /**
@@ -217,11 +217,11 @@ static __inline__ void ez_list_insert(struct ez_list *l, void *n, void *p) {
  * This is an O(n) operation, use ez_list_empty() to check for empty
  * lists.
  */
-static __inline__ int ez_list_size(struct ez_list *l) {
+static __inline__ int ez_list_size(struct ez_list * __restrict l) {
        struct ez_node *w, *n;
        int size = 0;
 
-       for (w = l->head, n = w->u.list.succ; n; w = n, n = n->u.list.succ)
+       for (w = l->head, n = w->succ; n; w = n, n = n->succ)
                size += 1;
 
        return size;
@@ -232,21 +232,21 @@ static __inline__ int ez_list_size(struct ez_list *l) {
  *
  * @param returns true (1) if the list is empty.
  */
-static __inline__ int ez_list_empty(struct ez_list *l) {
+static __inline__ int ez_list_empty(struct ez_list * __restrict l) {
        return l->tail_pred == (struct ez_node *)l;
 }
 
 /**
  * Retrieve the successor to the head node (the first user node).
  */
-static __inline__ void *ez_list_head(struct ez_list *l) {
+static __inline__ void *ez_list_head(struct ez_list * __restrict l) {
        return (void *)l->head;
 }
 
 /**
  * Retrieve the predecessor of the tail node (the last user node).
  */
-static __inline__ void *ez_list_tail(struct ez_list *l) {
+static __inline__ void *ez_list_tail(struct ez_list * __restrict l) {
        return (void *)l->tail_pred;
 }
 
@@ -262,5 +262,5 @@ static void ez_list_insert(struct ez_list *l, void *n, void *p) __attribute__ ((
 static int ez_list_empty(struct ez_list *l) __attribute__ ((always_inline));
 static void *ez_list_head(struct ez_list *l) __attribute__ ((always_inline));
 static void *ez_list_tail(struct ez_list *l) __attribute__ ((always_inline));
+
 #endif
index 7e3a7d5..9664290 100644 (file)
--- a/ez-node.h
+++ b/ez-node.h
@@ -39,15 +39,15 @@ struct ez_node {
                struct {
                        struct ez_node * volatile succ;
                        struct ez_node * volatile pred;
-               } list;
+               };
                struct {
                        intptr_t link[2];
-               } tree;
+               };
                struct {
                        struct ez_node *next;
                        unsigned int hash;
-               } set;
-       } u;
+               };
+       };
 };
 
 /**
@@ -70,7 +70,7 @@ typedef void (*ez_free_fn)(void *);
  * == NULL.
  */
 static __inline__ void *ez_node_succ(void *n) {
-       return (void *)((struct ez_node *)n)->u.list.succ;
+       return (void *)((struct ez_node *)n)->succ;
 }
 
 /**
@@ -80,42 +80,42 @@ static __inline__ void *ez_node_succ(void *n) {
  * == NULL.
  */
 static __inline__ void *ez_node_pred(void *n) {
-       return (void *)((struct ez_node *)n)->u.list.pred;
+       return (void *)((struct ez_node *)n)->pred;
 }
 
 /**
  * Retrieve the left child tree node.
  */
 static __inline__ void *ez_node_left(void *node) {
-       return (void *)(((struct ez_node *)node)->u.tree.link[0] & ~3);
+       return (void *)(((struct ez_node *)node)->link[0] & ~3);
 }
 
 /**
  * Retrieve the right child tree node.
  */
 static __inline__ void *ez_node_right(void *node) {
-       return (void *)(((struct ez_node *)node)->u.tree.link[1] & ~3);
+       return (void *)(((struct ez_node *)node)->link[1] & ~3);
 }
 
 /**
  * Retrieve either the left or right child node.
  */
 static __inline__ void *ez_node_link(void *node, enum ez_node_link_t i) {
-       return (void *)(((struct ez_node *)node)->u.tree.link[i] & ~3);
+       return (void *)(((struct ez_node *)node)->link[i] & ~3);
 }
 
 /**
  * Retrieve the next set hash chain bucket.
  */
 static __inline__ void *ez_node_next(void *node) {
-       return ((struct ez_node *)node)->u.set.next;
+       return ((struct ez_node *)node)->next;
 }
 
 /**
  * Retrieve the set hash bucket hash.
  */
 static __inline__ unsigned int ez_node_hash(void *node) {
-       return ((struct ez_node *)node)->u.set.hash;
+       return ((struct ez_node *)node)->hash;
 }
 
 static void *ez_node_succ(void *n) __attribute__ ((always_inline));
index 0705bef..762eca9 100644 (file)
--- a/ez-set.c
+++ b/ez-set.c
@@ -48,9 +48,9 @@ static ez_node *set_lookup(ez_set *h, const ez_node *key, unsigned int hash, ez_
        ez_node *scan = h->table[idx];
        ez_node *p = (ez_node *)&h->table[idx];
 
-       while (scan && !(hash == scan->u.set.hash && h->equals(key, scan))) {
+       while (scan && !(hash == scan->hash && h->equals(key, scan))) {
                p = scan;
-               scan = scan->u.set.next;
+               scan = scan->next;
        }
        *pp = p;
 
@@ -76,10 +76,10 @@ static void set_rehash(ez_set *h, int newsize) {
                ez_node *e = h->table[i];
 
                while (e) {
-                       ez_node *n = e->u.set.next;
-                       unsigned int nidx = e->u.set.hash & mask;
+                       ez_node *n = e->next;
+                       unsigned int nidx = e->hash & mask;
 
-                       e->u.set.next = table[nidx];
+                       e->next = table[nidx];
                        table[nidx] = e;
 
                        e = n;
@@ -155,17 +155,17 @@ void *ez_set_put(ez_set *h, void *ep) {
        }
 
        // Entries are only ever hashed once, here.
-       e->u.set.hash = h->hash(e);
-       scan = set_lookup(h, e, e->u.set.hash, &p);
+       e->hash = h->hash(e);
+       scan = set_lookup(h, e, e->hash, &p);
 
        // insert new node, possibly unlinking old one
-       p->u.set.next = e;
+       p->next = e;
        if (scan) {
                // link old node tail
-               e->u.set.next = scan->u.set.next;
+               e->next = scan->next;
        } else {
                // new node added
-               e->u.set.next = NULL;
+               e->next = NULL;
                h->count += 1;
                if (h->count > h->mask)
                        set_rehash(h, (h->mask+1) * 2);
@@ -197,7 +197,7 @@ void *ez_set_remove(ez_set *h, const void *ep) {
        scan = set_lookup(h, e, hash, &p);
        if (scan) {
                // unlink old node
-               p->u.set.next = scan->u.set.next;
+               p->next = scan->next;
                h->count -= 1;
                if (h->mask > 15 && h->count*2 < h->mask)
                        set_rehash(h, (h->mask+1)>>1);
@@ -222,7 +222,7 @@ void *ez_set_scan_next(ez_set_scan *scan) {
        if (scan->e) {
                // advance e and p
                scan->p = scan->e;
-               scan->e = scan->e->u.set.next;
+               scan->e = scan->e->next;
 
                if (!scan->e)
                        return scan_next_chain(scan->set, scan, scan->idx);
@@ -234,7 +234,7 @@ void *ez_set_scan_next(ez_set_scan *scan) {
 void *ez_set_scan_remove(ez_set_scan *scan) {
        if (scan->e) {
                // unlink e and advance but don't change p
-               scan->p->u.set.next = scan->e = scan->e->u.set.next;
+               scan->p->next = scan->e = scan->e->next;
                scan->set->count -= 1;
 
                if (!scan->e)
index 5ebb2af..6fcfb08 100644 (file)
--- a/ez-tree.c
+++ b/ez-tree.c
@@ -80,20 +80,20 @@ static void *fail_depth(void) {
 }
 
 static __inline__ int node_balance(struct ez_node *n) {
-       int i = n->u.tree.link[0];
+       int i = n->link[0];
        return i << 30 >> 30;
 }
 
 static __inline__ void node_set_balance(struct ez_node *node, int balance) {
-       node->u.tree.link[0] = (node->u.tree.link[0] & ~3) | (balance & 3);
+       node->link[0] = (node->link[0] & ~3) | (balance & 3);
 }
 
 static __inline__ void *node_link(struct ez_node *n, int i) {
-       return (void *)(n->u.tree.link[i] & ~3);
+       return (void *)(n->link[i] & ~3);
 }
 
 static __inline__ void node_set_link(struct ez_node *n, int i, struct ez_node *link) {
-       n->u.tree.link[i] = (n->u.tree.link[i] & 3) | (intptr_t)link;
+       n->link[i] = (n->link[i] & 3) | (intptr_t)link;
 }
 
 /**
@@ -229,7 +229,7 @@ static void node_remove(struct ez_tree_scan_info *stack, struct ez_tree_scan_inf
                si -= 1;
        }
 
-       stack[0].node->u.tree.link[0] -= 1;
+       stack[0].node->link[0] -= 1;
 }
 
 /**
@@ -251,15 +251,15 @@ static void tree_free(ez_tree *tree, struct ez_node *n, ez_free_fn node_free) {
 /* ********************************************************************** */
 
 void ez_tree_init(struct ez_tree *tree, ez_cmp_fn node_cmp) {
-       tree->root.u.tree.link[0] = 0;
-       tree->root.u.tree.link[1] = 0;
+       tree->root.link[0] = 0;
+       tree->root.link[1] = 0;
        tree->node_cmp = node_cmp;
 }
 
 void ez_tree_clear(ez_tree *tree, ez_free_fn node_free) {
        tree_free(tree, ez_tree_root(tree), node_free);
-       tree->root.u.tree.link[0] = 0;
-       tree->root.u.tree.link[1] = 0;
+       tree->root.link[0] = 0;
+       tree->root.link[1] = 0;
 }
 
 void *ez_tree_get(ez_tree *tree, const void *node) {
@@ -285,12 +285,12 @@ void *ez_tree_put(ez_tree *tree, void *node) {
        struct ez_tree_scan_info *sp = stack, *se = sp + EZ_TREE_MAX_DEPTH - 1;
        ez_cmp_fn node_cmp = tree->node_cmp;
 
-       k->u.tree.link[0] = BALANCE0; // balance=0
+       k->link[0] = BALANCE0; // balance=0
        node_set_link(k, 1, 0);
 
-       if (!tree->root.u.tree.link[1]) {
-               tree->root.u.tree.link[1] = (intptr_t)k;
-               tree->root.u.tree.link[0] += 1;
+       if (!tree->root.link[1]) {
+               tree->root.link[1] = (intptr_t)k;
+               tree->root.link[0] += 1;
                return NULL;
        }
 
@@ -321,7 +321,7 @@ void *ez_tree_put(ez_tree *tree, void *node) {
 
        // Insert new node
        node_set_link(p, cmp > 0, k);
-       tree->root.u.tree.link[0] += 1;
+       tree->root.link[0] += 1;
        *sp = (struct ez_tree_scan_info){ k, 0 };
 
        // Fix balance factors between s and q
index 83c9b7a..c2bcac9 100644 (file)
--- a/ez-tree.h
+++ b/ez-tree.h
@@ -40,7 +40,7 @@ struct ez_tree {
  *
  *   struct ez_tree tree = EZ_INIT_TREE(tree, cmp);
  */
-#define EZ_INIT_TREE(t, cmp) { .root.u.tree.link[0] = 0, .root.u.tree.link[1] = 0, .node_cmp = cmp }
+#define EZ_INIT_TREE(t, cmp) { .root.link[0] = 0, .root.link[1] = 0, .node_cmp = cmp }
 
 typedef struct ez_tree_scan ez_tree_scan;
 
@@ -85,21 +85,21 @@ void ez_tree_init(struct ez_tree *tree, ez_cmp_fn cmp);
  */
 static __inline__ int ez_tree_size(ez_tree *tree) {
        // well if it's good enough for Knuth.
-       return tree->root.u.tree.link[0];
+       return tree->root.link[0];
 }
 
 /**
  * Retrieve the root node of the tree.
  */
 static __inline__ void *ez_tree_root(ez_tree *tree) {
-       return (void *)tree->root.u.tree.link[1];
+       return (void *)tree->root.link[1];
 }
 
 /**
  * Determine if the tree is empty.
  */
 static __inline__ int ez_tree_empty(ez_tree *tree) {
-       return !tree->root.u.tree.link[1];
+       return !tree->root.link[1];
 }
 
 /**
index 030937b..352174d 100644 (file)
@@ -31,7 +31,7 @@ static int node_cmp(const void *a, const void *b) {
 static __inline__ int node_balance(struct ez_node *n) __attribute__((always_inline));
 
 static __inline__ int node_balance(struct ez_node *n) {
-       int i = n->u.tree.link[0];
+       int i = n->link[0];
        return i << 30 >> 30;
 }