From bec2d50c843ec4fd98bbbb212848ce4f24b96ebb Mon Sep 17 00:00:00 2001
From: 3gg <3gg@shellblade.net>
Date: Sat, 15 Jun 2024 11:43:10 -0700
Subject: More convenient list iteration.

---
 list/include/list.h   | 44 ++++++++++++++++++++++----------------------
 list/test/list_test.c | 20 ++++++++++----------
 plugin/src/plugin.c   | 15 +++++++--------
 3 files changed, 39 insertions(+), 40 deletions(-)

diff --git a/list/include/list.h b/list/include/list.h
index facf820..24291e1 100644
--- a/list/include/list.h
+++ b/list/include/list.h
@@ -5,15 +5,15 @@
 #include <stddef.h>
 #include <stdlib.h>
 
-#define DEF_LIST(type)         \
-  typedef struct type##_node { \
+#define DEF_LIST(name, type)   \
+  typedef struct name##_node { \
     type                val;   \
-    struct type##_node* prev;  \
-    struct type##_node* next;  \
-  } type##_node;               \
-  typedef struct type##_list { \
-    type##_node* head;         \
-  } type##_list;
+    struct name##_node* prev;  \
+    struct name##_node* next;  \
+  } name##_node;               \
+  typedef struct name##_list { \
+    name##_node* head;         \
+  } name##_list;
 
 static inline void* alloc(size_t size) {
   void* ptr = calloc(1, size);
@@ -35,7 +35,7 @@ static inline void* alloc(size_t size) {
   list.head = 0;
 
 /// Prepend a value to the list.
-#define list_push(list, value)                              \
+#define list_add(list, value)                               \
   {                                                         \
     __typeof__(list.head) node = alloc(sizeof(*list.head)); \
     node->val                  = value;                     \
@@ -86,13 +86,13 @@ static inline void* alloc(size_t size) {
 ///
 /// Use 'value' to refer to the address of the current node's value during
 /// iteration.
-#define list_foreach(list, body)                       \
+#define list_foreach(list, value, body)                \
   {                                                    \
-    __typeof__(list.head) node = list.head;            \
-    while (node) {                                     \
-      const __typeof__(node->val)* value = &node->val; \
+    __typeof__(list.head)* pNode = &list.head;         \
+    while (*pNode) {                                   \
+      __typeof__((*pNode)->val) value = (*pNode)->val; \
       body;                                            \
-      node = node->next;                               \
+      pNode = &(*pNode)->next;                         \
     }                                                  \
   }
 
@@ -100,12 +100,12 @@ static inline void* alloc(size_t size) {
 ///
 /// Use 'value' to refer to the address of the current node's value during
 /// iteration.
-#define list_foreach_mut(list, body)             \
-  {                                              \
-    __typeof__(list.head) node = list.head;      \
-    while (node) {                               \
-      __typeof__(node->val)* value = &node->val; \
-      body;                                      \
-      node = node->next;                         \
-    }                                            \
+#define list_foreach_mut(list, value, body)    \
+  {                                            \
+    __typeof__(list.head) node = list.head;    \
+    while (node) {                             \
+      __typeof__(node->val) value = node->val; \
+      body;                                    \
+      node = node->next;                       \
+    }                                          \
   }
diff --git a/list/test/list_test.c b/list/test/list_test.c
index 9ff10c1..418e156 100644
--- a/list/test/list_test.c
+++ b/list/test/list_test.c
@@ -4,20 +4,20 @@
 
 #define TEST_LIST_SIZE 10
 
-DEF_LIST(int);
+DEF_LIST(int, int);
 
 // Iterate over a list.
 TEST_CASE(list_traverse) {
   int_list list = make_list(int);
   for (int i = 0; i < TEST_LIST_SIZE; ++i) {
-    list_push(list, i + 1);
+    list_add(list, i + 1);
   }
 
   int count = 0;
   int sum   = 0;
-  list_foreach(list, {
+  list_foreach(list, value, {
     count++;
-    sum += *value;
+    sum += value;
   });
 
   TEST_EQUAL(count, TEST_LIST_SIZE);
@@ -30,16 +30,16 @@ TEST_CASE(list_traverse) {
 TEST_CASE(list_remove_by_value) {
   int_list list = make_list(int);
   for (int i = 0; i < TEST_LIST_SIZE; ++i) {
-    list_push(list, i + 1);
+    list_add(list, i + 1);
   }
 
   list_remove(list, 5);
 
   int count = 0;
   int sum   = 0;
-  list_foreach(list, {
+  list_foreach(list, value, {
     count++;
-    sum += *value;
+    sum += value;
   });
 
   TEST_EQUAL(count, TEST_LIST_SIZE - 1);
@@ -56,7 +56,7 @@ TEST_CASE(list_remove_by_address) {
 
   int_list list = make_list(int);
   for (int i = 0; i < N; ++i) {
-    list_push(list, i + 1);
+    list_add(list, i + 1);
     ptrs[i] = &list.head->val;
   }
 
@@ -64,9 +64,9 @@ TEST_CASE(list_remove_by_address) {
 
   int count = 0;
   int sum   = 0;
-  list_foreach(list, {
+  list_foreach(list, value, {
     count++;
-    sum += *value;
+    sum += value;
   });
 
   TEST_EQUAL(count, 2);
diff --git a/plugin/src/plugin.c b/plugin/src/plugin.c
index cd05faf..e2aae1f 100644
--- a/plugin/src/plugin.c
+++ b/plugin/src/plugin.c
@@ -34,7 +34,7 @@ typedef struct Plugin {
   mstring       filename;
 } Plugin;
 
-DEF_LIST(Plugin);
+DEF_LIST(Plugin, Plugin);
 
 /// Plugin engine.
 typedef struct PluginEngine {
@@ -121,7 +121,7 @@ Plugin* load_plugin(PluginEngine* eng, const char* filename) {
     return 0;
   }
 
-  list_push(eng->plugins, plugin);
+  list_add(eng->plugins, plugin);
   return &eng->plugins.head->val;
 }
 
@@ -180,7 +180,7 @@ void delete_plugin_engine(PluginEngine** pEng) {
   assert(pEng);
   PluginEngine* eng = *pEng;
   if (eng) {
-    list_foreach_mut(eng->plugins, { destroy_plugin(value); });
+    list_foreach_mut(eng->plugins, plugin, { destroy_plugin(&plugin); });
     del_list(eng->plugins);
     if (eng->dir_watch != -1) {
       inotify_rm_watch(eng->dir_watch, eng->inotify_instance);
@@ -226,11 +226,10 @@ void plugin_engine_update(PluginEngine* eng) {
               if (event->len > 0) {
                 // Name does not include directory, e.g., libfoo.so
                 const mstring file = mstring_make(event->name);
-                list_foreach_mut(eng->plugins, {
-                  Plugin* plugin = value;
-                  if (mstring_eq(file, plugin_lib_name(plugin))) {
-                    if (load_library(plugin)) {
-                      plugin->reloaded = true;
+                list_foreach_mut(eng->plugins, plugin, {
+                  if (mstring_eq(file, plugin_lib_name(&plugin))) {
+                    if (load_library(&plugin)) {
+                      plugin.reloaded = true;
                     }
                     break;
                   }
-- 
cgit v1.2.3