diff options
Diffstat (limited to 'src/nvim/lib')
-rw-r--r-- | src/nvim/lib/klist.h | 35 |
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 |