+/* Licensed under LGPL - see LICENSE file for details */
#ifndef CCAN_TLIST_H
#define CCAN_TLIST_H
#include <ccan/list/list.h>
+#include <ccan/tcon/tcon.h>
-#if HAVE_FLEXIBLE_ARRAY_MEMBER
/**
* TLIST_TYPE - declare a typed list type (struct tlist)
* @suffix: the name to use (struct tlist_@suffix)
* struct list_node list;
* };
*/
-#define TLIST_TYPE(suffix, type) \
- struct tlist_##suffix { \
- struct list_head raw; \
- const type *tcheck[]; \
+#define TLIST_TYPE(suffix, type) \
+ struct tlist_##suffix { \
+ struct list_head raw; \
+ TCON(type *canary); \
}
-/**
- * tlist_raw - access the raw list inside a typed list head.
- * @h: the head of the typed list (struct tlist_@suffix)
- * @test_var: a pointer to the expected element type.
- *
- * This elaborate macro usually causes the compiler to emit a warning
- * if the variable is of an unexpected type. It is used internally
- * where we need to access the raw underlying list.
- */
-#define tlist_raw(h, test_var) \
- (sizeof((h)->tcheck[0] == (test_var)) ? &(h)->raw : &(h)->raw)
-#else
-#define TLIST_TYPE(suffix, type) \
- struct tlist_##suffix { \
- struct list_head raw; \
- }
-#define tlist_raw(h, test_var) (&(h)->raw)
-#endif
-
/**
* TLIST_INIT - initalizer for an empty tlist
* @name: the name of the list.
*/
#define tlist_init(h) list_head_init(&(h)->raw)
+/**
+ * tlist_raw - unwrap the typed list and check the type
+ * @h: the tlist
+ * @expr: the expression to check the type against (not evaluated)
+ *
+ * This macro usually causes the compiler to emit a warning if the
+ * variable is of an unexpected type. It is used internally where we
+ * need to access the raw underlying list.
+ */
+#define tlist_raw(h, expr) (&tcon_check((h), canary, (expr))->raw)
+
/**
* tlist_add - add an entry at the start of a linked list.
* @h: the tlist to add the node to
#define tlist_for_each(h, i, member) \
list_for_each(tlist_raw((h), (i)), (i), member)
+/**
+ * tlist_for_each - iterate through a list backwards.
+ * @h: the tlist
+ * @i: an iterator of suitable type for this list.
+ * @member: the list_node member of @i
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * tlist_for_each_rev(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define tlist_for_each_rev(h, i, member) \
+ list_for_each_rev(tlist_raw((h), (i)), (i), member)
+
/**
* tlist_for_each_safe - iterate through a list, maybe during deletion
* @h: the tlist