summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bftw.c18
-rw-r--r--src/list.h63
2 files changed, 65 insertions, 16 deletions
diff --git a/src/bftw.c b/src/bftw.c
index 9ff526d..aa36b87 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -69,14 +69,8 @@ struct bftw_file {
};
/** Move from a list entry to a bftw_file. */
-static struct bftw_file *bftw_file_entry(struct slink *link) {
- return BFS_CONTAINER_OF(link, struct bftw_file, link);
-}
-
-/** Move from an LRU entry to a bftw_file. */
-static struct bftw_file *bftw_lru_file(struct link *link) {
- return BFS_CONTAINER_OF(link, struct bftw_file, lru);
-}
+#define BFTW_FILE(...) \
+ LIST_ITEM(struct bftw_file, __VA_ARGS__)
/**
* A cache of open directories.
@@ -126,7 +120,7 @@ static int bftw_cache_pop(struct bftw_cache *cache) {
return -1;
}
- struct bftw_file *file = bftw_lru_file(cache->list.tail);
+ struct bftw_file *file = BFTW_FILE(cache->list.tail, lru);
bftw_file_close(cache, file);
return 0;
}
@@ -810,7 +804,7 @@ static int bftw_pop(struct bftw_state *state) {
return 0;
}
- state->file = bftw_file_entry(slist_pop(&state->queue));
+ state->file = BFTW_FILE(slist_pop(&state->queue));
if (bftw_build_path(state) != 0) {
return -1;
@@ -974,9 +968,7 @@ static int bftw_state_destroy(struct bftw_state *state) {
/** Comparison function for BFTW_SORT. */
static bool bftw_file_cmp(struct slink *left, struct slink *right, const void *ptr) {
- struct bftw_file *lfile = bftw_file_entry(left);
- struct bftw_file *rfile = bftw_file_entry(right);
- return strcoll(lfile->name, rfile->name) <= 0;
+ return strcoll(BFTW_FILE(left)->name, BFTW_FILE(right)->name) <= 0;
}
/** Finish adding a batch of files. */
diff --git a/src/list.h b/src/list.h
index 1985413..b47bed7 100644
--- a/src/list.h
+++ b/src/list.h
@@ -107,10 +107,67 @@ struct link *list_pop(struct list *list);
/** Check if a link is attached to a list. */
bool list_attached(const struct list *list, const struct link *link);
+// LIST_ITEM() helper
+#define LIST_ITEM_IMPL(type, entry, member, ...) \
+ BFS_CONTAINER_OF(entry, type, member)
+
+/**
+ * Convert a list entry to its container.
+ *
+ * @param type
+ * The type of the list entries.
+ * @param entry
+ * The list entry to convert.
+ * @param member
+ * The name of the list link field (default: link).
+ * @return
+ * The item that contains the given entry.
+ */
+#define LIST_ITEM(...) \
+ LIST_ITEM_IMPL(__VA_ARGS__, link,)
+
+// LIST_NEXT() helper
+#define LIST_NEXT_IMPL(type, entry, member, ...) \
+ LIST_ITEM(type, (entry)->member.next, member)
+
+/**
+ * Get the next item in a list.
+ *
+ * @param type
+ * The type of the list entries.
+ * @param entry
+ * The current entry.
+ * @param member
+ * The name of the list link field (default: link).
+ * @return
+ * The next item in the list.
+ */
+#define LIST_NEXT(...) \
+ LIST_NEXT_IMPL(__VA_ARGS__, link,)
+
+// LIST_PREV() helper
+#define LIST_PREV_IMPL(type, entry, member, ...) \
+ LIST_ITEM(type, (entry)->member.prev, member)
+
+/**
+ * Get the previous entry in a list.
+ *
+ * @param type
+ * The type of the list entries.
+ * @param entry
+ * The current entry.
+ * @param member
+ * The name of the list link field (default: link).
+ * @return
+ * The previous item in the list.
+ */
+#define LIST_PREV(...) \
+ LIST_PREV_IMPL(__VA_ARGS__, link,)
+
// Helper for LIST_FOR_EACH_*()
#define LIST_FOR_EACH_IMPL(entry, type, i, member, ...) \
- for (type *_next, *i = BFS_CONTAINER_OF(entry, type, member); \
- i && (_next = BFS_CONTAINER_OF(i->member.next, type, member), true); \
+ for (type *_next, *i = LIST_ITEM(type, entry, member); \
+ i && (_next = LIST_NEXT(type, i, member), true); \
i = _next)
/**
@@ -150,7 +207,7 @@ bool list_attached(const struct list *list, const struct link *link);
// Helper for LIST_DRAIN()
#define LIST_DRAIN_IMPL(list, type, i, member, ...) \
- for (type *i; (i = BFS_CONTAINER_OF(LIST_POP(list), type, member));)
+ for (type *i; (i = LIST_ITEM(type, LIST_POP(list), member));)
/**
* Drain the entries from a list.