lstack: Allow a stack to be initialized from an existing top element
authorDavid Gibson <david@gibson.dropbear.id.au>
Sat, 13 Jun 2015 14:23:39 +0000 (00:23 +1000)
committerDavid Gibson <david@gibson.dropbear.id.au>
Sat, 13 Jun 2015 14:25:24 +0000 (00:25 +1000)
There are occasional cases where you might construct a valid stack, and
retain a direct pointer to the top element, but not the struct lstack
used to build it.

This patch adds a new lstack_init_from_top() macro to reconstruct a valid
struct lstack from the element pointer for cases like this.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
ccan/lstack/lstack.h

index 41a9f05aa8fd222c05077fd8f1f2c3be8d2b1c90..7eb880a5c2f0384cc78b163f671d2a65ee2542f1 100644 (file)
@@ -50,6 +50,33 @@ struct lstack {
 #define LSTACK(name) \
        struct lstack name = { NULL, }
 
+/**
+ * lstack_init_from_top - initialize a stack with a given top element
+ * @s: the lstack to initialize
+ * @e: pointer to the top element of the new stack
+ * @member: member of the element containing the lstack_link
+ *
+ * USE WITH CAUTION: This is for handling unusual cases where you have
+ * a pointer to an element in a previously constructed stack but can't
+ * conveniently pass around a normal struct lstack.  Usually you
+ * should use lstack_init().
+ *
+ * Example:
+ *     LSTACK(stack1);
+ *     struct lstack stack2;
+ *     struct element {
+ *             int value;
+ *             struct lstack_link link;
+ *     } el;
+ *
+ *     lstack_push(&stack1, &el, link);
+ *
+ *     lstack_init_from_top(&stack2,
+ *                          lstack_top(&stack1, struct element, link), link);
+ */
+#define lstack_init_from_top(s, e, member) \
+       (lstack_init_((s), &(e)->member))
+
 /**
  * lstack_init - initialize a stack
  * @h: the lstack to set to an empty stack
@@ -58,9 +85,11 @@ struct lstack {
  *     struct lstack *sp = malloc(sizeof(*sp));
  *     lstack_init(sp);
  */
-static inline void lstack_init(struct lstack *s)
+#define lstack_init(s) \
+       (lstack_init_((s), NULL))
+static inline void lstack_init_(struct lstack *s, struct lstack_link *top)
 {
-       s->top = NULL;
+       s->top = top;
 }
 
 /**