aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/lib')
-rw-r--r--src/nvim/lib/klist.h35
1 files changed, 24 insertions, 11 deletions
diff --git a/src/nvim/lib/klist.h b/src/nvim/lib/klist.h
index 7df809f07b..10d6846133 100644
--- a/src/nvim/lib/klist.h
+++ b/src/nvim/lib/klist.h
@@ -27,10 +27,12 @@
#define _AC_KLIST_H
#include <stdlib.h>
+#include <assert.h>
#include "nvim/memory.h"
#include "nvim/func_attr.h"
+
#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \
typedef struct { \
size_t cnt, n, max; \
@@ -95,23 +97,27 @@
kmp_free(name, kl->mp, p); \
kmp_free(name, kl->mp, p); \
kmp_destroy(name, kl->mp); \
- xfree(kl); \
+ xfree(kl); \
} \
- static inline kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \
+ static inline void kl_push_##name(kl_##name##_t *kl, kltype_t d) { \
kl1_##name *q, *p = kmp_alloc(name, kl->mp); \
q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \
++kl->size; \
- return &q->data; \
+ q->data = d; \
} \
- static inline int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \
+ static inline kltype_t kl_shift_at_##name(kl_##name##_t *kl, \
+ kl1_##name **n) { \
+ assert((*n)->next); \
kl1_##name *p; \
- if (kl->head->next == 0) return -1; \
--kl->size; \
- p = kl->head; kl->head = kl->head->next; \
- if (d) *d = p->data; \
+ p = *n; \
+ *n = (*n)->next; \
+ if (p == kl->head) kl->head = *n; \
+ kltype_t d = p->data; \
kmp_free(name, kl->mp, p); \
- return 0; \
- }
+ return d; \
+ } \
+
#define kliter_t(name) kl1_##name
#define klist_t(name) kl_##name##_t
@@ -122,7 +128,14 @@
#define kl_init(name) kl_init_##name()
#define kl_destroy(name, kl) kl_destroy_##name(kl)
-#define kl_pushp(name, kl) kl_pushp_##name(kl)
-#define kl_shift(name, kl, d) kl_shift_##name(kl, d)
+#define kl_push(name, kl, d) kl_push_##name(kl, d)
+#define kl_shift_at(name, kl, node) kl_shift_at_##name(kl, node)
+#define kl_shift(name, kl) kl_shift_at(name, kl, &kl->head)
#define kl_empty(kl) ((kl)->size == 0)
+// Iteration macros. It's ok to modify the list while iterating as long as a
+// `break` statement is executed before the next iteration.
+#define kl_iter(name, kl, p) kl_iter_at(name, kl, p, NULL)
+#define kl_iter_at(name, kl, p, h) \
+ for (kl1_##name *p = h ? h : kl->head; p != kl->tail; p = p->next)
+
#endif