From 0b6b03c47211dc45dda03d047c24925edbdbf099 Mon Sep 17 00:00:00 2001 From: timeyyy Date: Thu, 28 Jul 2016 16:30:26 +0200 Subject: kbtree.h --- src/nvim/lib/kbtree.h | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 src/nvim/lib/kbtree.h (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h new file mode 100644 index 0000000000..b58c3f97a4 --- /dev/null +++ b/src/nvim/lib/kbtree.h @@ -0,0 +1,423 @@ +/*- + * Copyright 1997-1999, 2001, John-Mark Gurney. + * 2008-2009, Attractive Chaos + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NVIM_LIB_KBTREE_H +#define NVIM_LIB_KBTREE_H + +#include +#include +#include + +#define KB_MAX_DEPTH 64 + +typedef struct { + int32_t is_internal:1, n:31; +} kbnode_t; + + +typedef struct { + kbnode_t *x; + int i; +} kbpos_t; + +typedef struct { + kbpos_t stack[KB_MAX_DEPTH], *p; +} kbitr_t; + +#define __KB_KEY(type, x) ((type*)((char*)x + 4)) +#define __KB_PTR(btr, x) ((kbnode_t**)((char*)x + btr->off_ptr)) + +#define __KB_TREE_T(name) \ + typedef struct { \ + kbnode_t *root; \ + int off_key, off_ptr, ilen, elen; \ + int n, t; \ + int n_keys, n_nodes; \ + } kbtree_##name##_t; + +#define __KB_INIT(name, key_t) \ + static inline kbtree_##name##_t *kb_init_##name(unsigned int size) \ + { \ + kbtree_##name##_t *b; \ + b = (kbtree_##name##_t*)calloc(1, sizeof(kbtree_##name##_t)); \ + b->t = (int)((size - 4 - sizeof(void*)) / (sizeof(void*) + sizeof(key_t)) + 1) >> 1; \ + if (b->t < 2) { \ + free(b); return 0; \ + } \ + b->n = 2 * b->t - 1; \ + b->off_ptr = (int)(4 + (unsigned int)b->n * sizeof(key_t)); \ + b->ilen = (int)(4 + sizeof(void*) + (unsigned int)b->n * (sizeof(void*) + sizeof(key_t)) + 3) >> 2 << 2; \ + b->elen = (b->off_ptr + 3) >> 2 << 2; \ + b->root = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \ + ++b->n_nodes; \ + return b; \ + } + +#define __kb_destroy(b) do { \ + int i; \ + unsigned int max = 8; \ + kbnode_t *x, **top, **stack = 0; \ + if (b) { \ + top = stack = (kbnode_t**)calloc(max, sizeof(kbnode_t*)); \ + *top++ = (b)->root; \ + while (top != stack) { \ + x = *--top; \ + if (x->is_internal == 0) { free(x); continue; } \ + for (i = 0; i <= x->n; ++i) \ + if (__KB_PTR(b, x)[i]) { \ + if (top - stack == (int)max) { \ + max <<= 1; \ + stack = (kbnode_t**)realloc(stack, max * sizeof(kbnode_t*)); \ + top = stack + (max>>1); \ + } \ + *top++ = __KB_PTR(b, x)[i]; \ + } \ + free(x); \ + } \ + } \ + free(b); free(stack); \ + } while (0) + +#define __KB_GET_AUX1(name, key_t, __cmp) \ + static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, const key_t * __restrict k, int *r) \ + { \ + int tr, *rr, begin = 0, end = x->n; \ + if (x->n == 0) return -1; \ + rr = r? r : &tr; \ + while (begin < end) { \ + int mid = (begin + end) >> 1; \ + if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \ + else end = mid; \ + } \ + if (begin == x->n) { *rr = 1; return x->n - 1; } \ + if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \ + return begin; \ + } + +#define __KB_GET(name, key_t) \ + static key_t *kb_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + { \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \ + if (x->is_internal == 0) return 0; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + return 0; \ + } \ + static inline key_t *kb_get_##name(kbtree_##name##_t *b, const key_t k) \ + { \ + return kb_getp_##name(b, &k); \ + } + +#define __KB_INTERVAL(name, key_t) \ + static void kb_intervalp_##name(kbtree_##name##_t *b, const key_t * __restrict k, key_t **lower, key_t **upper) \ + { \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + *lower = *upper = 0; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) { \ + *lower = *upper = &__KB_KEY(key_t, x)[i]; \ + return; \ + } \ + if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \ + if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \ + if (x->is_internal == 0) return; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + } \ + static inline void kb_interval_##name(kbtree_##name##_t *b, const key_t k, key_t **lower, key_t **upper) \ + { \ + kb_intervalp_##name(b, &k, lower, upper); \ + } + +#define __KB_PUT(name, key_t, __cmp) \ + /* x must be an internal node */ \ + static void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ + { \ + kbnode_t *z; \ + z = (kbnode_t*)calloc(1, y->is_internal? (unsigned int)b->ilen : (unsigned int)b->elen); \ + ++b->n_nodes; \ + z->is_internal = y->is_internal; \ + z->n = b->t - 1; \ + memcpy(__KB_KEY(key_t, z), __KB_KEY(key_t, y) + b->t, sizeof(key_t) * (unsigned int)(b->t - 1)); \ + if (y->is_internal) memcpy(__KB_PTR(b, z), __KB_PTR(b, y) + (unsigned int)b->t, sizeof(void*) * (unsigned int)b->t); \ + y->n = b->t - 1; \ + memmove(__KB_PTR(b, x) + i + 2, __KB_PTR(b, x) + i + 1, sizeof(void*) * (unsigned int)(x->n - i)); \ + __KB_PTR(b, x)[i + 1] = z; \ + memmove(__KB_KEY(key_t, x) + i + 1, __KB_KEY(key_t, x) + i, sizeof(key_t) * (unsigned int)(x->n - i)); \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[b->t - 1]; \ + ++x->n; \ + } \ + static key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k) \ + { \ + int i = x->n - 1; \ + key_t *ret; \ + if (x->is_internal == 0) { \ + i = __kb_getp_aux_##name(x, k, 0); \ + if (i != x->n - 1) \ + memmove(__KB_KEY(key_t, x) + i + 2, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + ret = &__KB_KEY(key_t, x)[i + 1]; \ + *ret = *k; \ + ++x->n; \ + } else { \ + i = __kb_getp_aux_##name(x, k, 0) + 1; \ + if (__KB_PTR(b, x)[i]->n == 2 * b->t - 1) { \ + __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ + if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ + } \ + ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \ + } \ + return ret; \ + } \ + static key_t *kb_putp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + { \ + kbnode_t *r, *s; \ + ++b->n_keys; \ + r = b->root; \ + if (r->n == 2 * b->t - 1) { \ + ++b->n_nodes; \ + s = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \ + b->root = s; s->is_internal = 1; s->n = 0; \ + __KB_PTR(b, s)[0] = r; \ + __kb_split_##name(b, s, 0, r); \ + r = s; \ + } \ + return __kb_putp_aux_##name(b, r, k); \ + } \ + static inline void kb_put_##name(kbtree_##name##_t *b, const key_t k) \ + { \ + kb_putp_##name(b, &k); \ + } + + +#define __KB_DEL(name, key_t) \ + static key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k, int s) \ + { \ + int yn, zn, i, r = 0; \ + kbnode_t *xp, *y, *z; \ + key_t kp; \ + if (x == 0) return *k; \ + if (s) { /* s can only be 0, 1 or 2 */ \ + r = x->is_internal == 0? 0 : s == 1? 1 : -1; \ + i = s == 1? x->n - 1 : -1; \ + } else i = __kb_getp_aux_##name(x, k, &r); \ + if (x->is_internal == 0) { \ + if (s == 2) ++i; \ + kp = __KB_KEY(key_t, x)[i]; \ + memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + --x->n; \ + return kp; \ + } \ + if (r == 0) { \ + if ((yn = __KB_PTR(b, x)[i]->n) >= b->t) { \ + xp = __KB_PTR(b, x)[i]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ + return kp; \ + } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= b->t) { \ + xp = __KB_PTR(b, x)[i + 1]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ + return kp; \ + } else if (yn == b->t - 1 && zn == b->t - 1) { \ + y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ + __KB_KEY(key_t, y)[y->n++] = *k; \ + memmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, z), (unsigned int)(z->n + 1) * sizeof(void*)); \ + y->n += z->n; \ + memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + free(z); \ + return __kb_delp_aux_##name(b, y, k, s); \ + } \ + } \ + ++i; \ + if ((xp = __KB_PTR(b, x)[i])->n == b->t - 1) { \ + if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= b->t) { \ + memmove(__KB_KEY(key_t, xp) + 1, __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(__KB_PTR(b, xp) + 1, __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ + __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ + if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ + --y->n; ++xp->n; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= b->t) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ + if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ + --y->n; \ + memmove(__KB_KEY(key_t, y), __KB_KEY(key_t, y) + 1, (unsigned int)y->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y), __KB_PTR(b, y) + 1, (unsigned int)(y->n + 1) * sizeof(void*)); \ + } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == b->t - 1) { \ + __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ + memmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + y->n += xp->n; \ + memmove(__KB_KEY(key_t, x) + i - 1, __KB_KEY(key_t, x) + i, (unsigned int)(x->n - i) * sizeof(key_t)); \ + memmove(__KB_PTR(b, x) + i, __KB_PTR(b, x) + i + 1, (unsigned int)(x->n - i) * sizeof(void*)); \ + --x->n; \ + free(xp); \ + xp = y; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == b->t - 1) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + memmove(__KB_KEY(key_t, xp) + xp->n, __KB_KEY(key_t, y), (unsigned int)y->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(__KB_PTR(b, xp) + xp->n, __KB_PTR(b, y), (unsigned int)(y->n + 1) * sizeof(void*)); \ + xp->n += y->n; \ + memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + --x->n; \ + free(y); \ + } \ + } \ + return __kb_delp_aux_##name(b, xp, k, s); \ + } \ + static key_t kb_delp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + { \ + kbnode_t *x; \ + key_t ret; \ + ret = __kb_delp_aux_##name(b, b->root, k, 0); \ + --b->n_keys; \ + if (b->root->n == 0 && b->root->is_internal) { \ + --b->n_nodes; \ + x = b->root; \ + b->root = __KB_PTR(b, x)[0]; \ + free(x); \ + } \ + return ret; \ + } \ + static inline key_t kb_del_##name(kbtree_##name##_t *b, const key_t k) \ + { \ + return kb_delp_##name(b, &k); \ + } + +#define __KB_ITR(name, key_t) \ + static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + { \ + itr->p = 0; \ + if (b->n_keys == 0) return; \ + itr->p = itr->stack; \ + itr->p->x = b->root; itr->p->i = 0; \ + while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \ + kbnode_t *x = itr->p->x; \ + ++itr->p; \ + itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ + } \ + } \ + static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + ++itr->p->i; \ + while (itr->p->x && itr->p->i <= itr->p->x->n) { \ + itr->p[1].i = 0; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ + } \ + } + +#define KBTREE_INIT(name, key_t, __cmp) \ + __KB_TREE_T(name) \ + __KB_INIT(name, key_t) \ + __KB_GET_AUX1(name, key_t, __cmp) \ + __KB_GET(name, key_t) \ + __KB_INTERVAL(name, key_t) \ + __KB_PUT(name, key_t, __cmp) \ + __KB_DEL(name, key_t) \ + __KB_ITR(name, key_t) + +#define KB_DEFAULT_SIZE 512 + +#define kbtree_t(name) kbtree_##name##_t +#define kb_init(name, s) kb_init_##name(s) +#define kb_destroy(name, b) __kb_destroy(b) +#define kb_get(name, b, k) kb_get_##name(b, k) +#define kb_put(name, b, k) kb_put_##name(b, k) +#define kb_del(name, b, k) kb_del_##name(b, k) +#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u) +#define kb_getp(name, b, k) kb_getp_##name(b, k) +#define kb_putp(name, b, k) kb_putp_##name(b, k) +#define kb_delp(name, b, k) kb_delp_##name(b, k) +#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) + +#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) +#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) +#define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i] +#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) + +#define kb_size(b) ((b)->n_keys) + +#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) +#define kb_str_cmp(a, b) strcmp(a, b) + +/* The following is *DEPRECATED*!!! Use the iterator interface instead! */ + +typedef struct { + kbnode_t *x; + int i; +} __kbstack_t; + +#define __kb_traverse(key_t, b, __func) do { \ + int __kmax = 8; \ + __kbstack_t *__kstack, *__kp; \ + __kp = __kstack = (__kbstack_t*)calloc(__kmax, sizeof(__kbstack_t)); \ + __kp->x = (b)->root; __kp->i = 0; \ + for (;;) { \ + while (__kp->x && __kp->i <= __kp->x->n) { \ + if (__kp - __kstack == __kmax - 1) { \ + __kmax <<= 1; \ + __kstack = (__kbstack_t*)realloc(__kstack, __kmax * sizeof(__kbstack_t)); \ + __kp = __kstack + (__kmax>>1) - 1; \ + } \ + (__kp+1)->i = 0; (__kp+1)->x = __kp->x->is_internal? __KB_PTR(b, __kp->x)[__kp->i] : 0; \ + ++__kp; \ + } \ + --__kp; \ + if (__kp >= __kstack) { \ + if (__kp->x && __kp->i < __kp->x->n) __func(&__KB_KEY(key_t, __kp->x)[__kp->i]); \ + ++__kp->i; \ + } else break; \ + } \ + free(__kstack); \ + } while (0) + +#define __kb_get_first(key_t, b, ret) do { \ + kbnode_t *__x = (b)->root; \ + while (__KB_PTR(b, __x)[0] != 0) \ + __x = __KB_PTR(b, __x)[0]; \ + (ret) = __KB_KEY(key_t, __x)[0]; \ + } while (0) + +#endif // NVIM_LIB_KBTREE_H -- cgit From 6712e08bba2d50899853bf98b786bdf48c3c79be Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 29 Jul 2016 20:27:50 +0200 Subject: kbtree: allow iterators to start at arbitrary position --- src/nvim/lib/kbtree.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index b58c3f97a4..ec83d4d124 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -57,7 +57,9 @@ typedef struct { int off_key, off_ptr, ilen, elen; \ int n, t; \ int n_keys, n_nodes; \ - } kbtree_##name##_t; + } kbtree_##name##_t; \ + + #define __KB_INIT(name, key_t) \ static inline kbtree_##name##_t *kb_init_##name(unsigned int size) \ @@ -75,7 +77,7 @@ typedef struct { b->root = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \ ++b->n_nodes; \ return b; \ - } + } \ #define __kb_destroy(b) do { \ int i; \ @@ -346,7 +348,48 @@ typedef struct { if (itr->p < itr->stack) return 0; \ if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ } \ - } + } \ + static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + { \ + if (itr->p < itr->stack) return 0; \ + for (;;) { \ + while (itr->p->x && itr->p->i >= 0) { \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \ + ++itr->p; \ + } \ + --itr->p; \ + if (itr->p < itr->stack) return 0; \ + --itr->p->i; \ + if (itr->p->x && itr->p->i >= 0) return 1; \ + } \ + } \ + static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_t *itr) \ + { \ + int i, r = 0; \ + itr->p = itr->stack; \ + itr->p->x = b->root; \ + while (itr->p->x) { \ + i = __kb_getp_aux_##name(itr->p->x, k, &r); \ + itr->p->i = i; \ + if (i >= 0 && r == 0) return 1; \ + ++itr->p->i; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ + ++itr->p; \ + } \ + return 0; \ + } \ + static int kb_itr_get_##name(kbtree_##name##_t *b, const key_t k, kbitr_t *itr) \ + { \ + return kb_itr_getp_##name(b,&k,itr); \ + } \ + static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + { \ + key_t k = kb_itr_key(key_t, itr); \ + kb_delp_##name(b, &k); \ + kb_itr_getp_##name(b, &k, itr); \ + } + #define KBTREE_INIT(name, key_t, __cmp) \ __KB_TREE_T(name) \ @@ -373,7 +416,11 @@ typedef struct { #define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) #define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) +#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i) +#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i) #define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) +#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) +#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) #define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i] #define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) -- cgit From 53cf88c27bcea1099d48a1ca6dc0a4d7c44e0a98 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 6 Aug 2016 09:15:43 +0200 Subject: kbtree: use proper structs --- src/nvim/lib/kbtree.h | 212 +++++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 106 deletions(-) (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index ec83d4d124..bfea068206 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -32,79 +32,71 @@ #include #include -#define KB_MAX_DEPTH 64 - -typedef struct { - int32_t is_internal:1, n:31; -} kbnode_t; - - -typedef struct { - kbnode_t *x; - int i; -} kbpos_t; +#include "nvim/memory.h" -typedef struct { - kbpos_t stack[KB_MAX_DEPTH], *p; -} kbitr_t; - -#define __KB_KEY(type, x) ((type*)((char*)x + 4)) -#define __KB_PTR(btr, x) ((kbnode_t**)((char*)x + btr->off_ptr)) +#define KB_MAX_DEPTH 64 -#define __KB_TREE_T(name) \ +#define __KB_KEY(type, x) (x->key) +#define __KB_PTR(btr, x) (x->ptr) + +#define __KB_TREE_T(name,key_t,T) \ +typedef struct kbnode_##name##_s kbnode_##name##_t; \ +struct kbnode_##name##_s { \ + int32_t n; \ + bool is_internal; \ + key_t key[2*T-1]; \ + kbnode_##name##_t *ptr[0]; \ +} ; \ + \ typedef struct { \ - kbnode_t *root; \ - int off_key, off_ptr, ilen, elen; \ - int n, t; \ + kbnode_##name##_t *root; \ int n_keys, n_nodes; \ } kbtree_##name##_t; \ + typedef struct { \ + kbnode_##name##_t *x; \ + int i; \ + } kbpos_##name##_t; \ + typedef struct { \ + kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \ + } kbitr_##name##_t; \ - -#define __KB_INIT(name, key_t) \ - static inline kbtree_##name##_t *kb_init_##name(unsigned int size) \ +#define __KB_INIT(name, key_t, kbnode_t, T, ILEN) \ + static inline kbtree_##name##_t *kb_init_##name() \ { \ kbtree_##name##_t *b; \ - b = (kbtree_##name##_t*)calloc(1, sizeof(kbtree_##name##_t)); \ - b->t = (int)((size - 4 - sizeof(void*)) / (sizeof(void*) + sizeof(key_t)) + 1) >> 1; \ - if (b->t < 2) { \ - free(b); return 0; \ - } \ - b->n = 2 * b->t - 1; \ - b->off_ptr = (int)(4 + (unsigned int)b->n * sizeof(key_t)); \ - b->ilen = (int)(4 + sizeof(void*) + (unsigned int)b->n * (sizeof(void*) + sizeof(key_t)) + 3) >> 2 << 2; \ - b->elen = (b->off_ptr + 3) >> 2 << 2; \ - b->root = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \ + b = (kbtree_##name##_t*)xcalloc(1, sizeof(kbtree_##name##_t)); \ + b->root = (kbnode_t*)xcalloc(1, ILEN); \ ++b->n_nodes; \ return b; \ } \ -#define __kb_destroy(b) do { \ +#define __kb_destroy(kbnode_t,b) do { \ int i; \ unsigned int max = 8; \ kbnode_t *x, **top, **stack = 0; \ if (b) { \ - top = stack = (kbnode_t**)calloc(max, sizeof(kbnode_t*)); \ + top = stack = (kbnode_t**)xcalloc(max, sizeof(kbnode_t*)); \ *top++ = (b)->root; \ while (top != stack) { \ x = *--top; \ - if (x->is_internal == 0) { free(x); continue; } \ + if (x->is_internal == 0) { xfree(x); continue; } \ for (i = 0; i <= x->n; ++i) \ if (__KB_PTR(b, x)[i]) { \ if (top - stack == (int)max) { \ max <<= 1; \ - stack = (kbnode_t**)realloc(stack, max * sizeof(kbnode_t*)); \ + stack = (kbnode_t**)xrealloc(stack, max * sizeof(kbnode_t*)); \ top = stack + (max>>1); \ } \ *top++ = __KB_PTR(b, x)[i]; \ } \ - free(x); \ + xfree(x); \ } \ } \ - free(b); free(stack); \ + xfree(b); xfree(stack); \ } while (0) -#define __KB_GET_AUX1(name, key_t, __cmp) \ +#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, const key_t * __restrict k, int *r) \ { \ int tr, *rr, begin = 0, end = x->n; \ @@ -120,7 +112,7 @@ typedef struct { return begin; \ } -#define __KB_GET(name, key_t) \ +#define __KB_GET(name, key_t, kbnode_t) \ static key_t *kb_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ { \ int i, r = 0; \ @@ -138,7 +130,7 @@ typedef struct { return kb_getp_##name(b, &k); \ } -#define __KB_INTERVAL(name, key_t) \ +#define __KB_INTERVAL(name, key_t, kbnode_t) \ static void kb_intervalp_##name(kbtree_##name##_t *b, const key_t * __restrict k, key_t **lower, key_t **upper) \ { \ int i, r = 0; \ @@ -161,22 +153,22 @@ typedef struct { kb_intervalp_##name(b, &k, lower, upper); \ } -#define __KB_PUT(name, key_t, __cmp) \ +#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ /* x must be an internal node */ \ static void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ { \ kbnode_t *z; \ - z = (kbnode_t*)calloc(1, y->is_internal? (unsigned int)b->ilen : (unsigned int)b->elen); \ + z = (kbnode_t*)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ ++b->n_nodes; \ z->is_internal = y->is_internal; \ - z->n = b->t - 1; \ - memcpy(__KB_KEY(key_t, z), __KB_KEY(key_t, y) + b->t, sizeof(key_t) * (unsigned int)(b->t - 1)); \ - if (y->is_internal) memcpy(__KB_PTR(b, z), __KB_PTR(b, y) + (unsigned int)b->t, sizeof(void*) * (unsigned int)b->t); \ - y->n = b->t - 1; \ - memmove(__KB_PTR(b, x) + i + 2, __KB_PTR(b, x) + i + 1, sizeof(void*) * (unsigned int)(x->n - i)); \ + z->n = T - 1; \ + memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \ + if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void*) * T); \ + y->n = T - 1; \ + memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, x)[i + 1], sizeof(void*) * (unsigned int)(x->n - i)); \ __KB_PTR(b, x)[i + 1] = z; \ - memmove(__KB_KEY(key_t, x) + i + 1, __KB_KEY(key_t, x) + i, sizeof(key_t) * (unsigned int)(x->n - i)); \ - __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[b->t - 1]; \ + memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], sizeof(key_t) * (unsigned int)(x->n - i)); \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ ++x->n; \ } \ static key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k) \ @@ -186,13 +178,13 @@ typedef struct { if (x->is_internal == 0) { \ i = __kb_getp_aux_##name(x, k, 0); \ if (i != x->n - 1) \ - memmove(__KB_KEY(key_t, x) + i + 2, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ ret = &__KB_KEY(key_t, x)[i + 1]; \ *ret = *k; \ ++x->n; \ } else { \ i = __kb_getp_aux_##name(x, k, 0) + 1; \ - if (__KB_PTR(b, x)[i]->n == 2 * b->t - 1) { \ + if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \ __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ } \ @@ -205,9 +197,9 @@ typedef struct { kbnode_t *r, *s; \ ++b->n_keys; \ r = b->root; \ - if (r->n == 2 * b->t - 1) { \ + if (r->n == 2 * T - 1) { \ ++b->n_nodes; \ - s = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \ + s = (kbnode_t*)xcalloc(1, ILEN); \ b->root = s; s->is_internal = 1; s->n = 0; \ __KB_PTR(b, s)[0] = r; \ __kb_split_##name(b, s, 0, r); \ @@ -221,7 +213,7 @@ typedef struct { } -#define __KB_DEL(name, key_t) \ +#define __KB_DEL(name, key_t, kbnode_t, T) \ static key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k, int s) \ { \ int yn, zn, i, r = 0; \ @@ -235,69 +227,69 @@ typedef struct { if (x->is_internal == 0) { \ if (s == 2) ++i; \ kp = __KB_KEY(key_t, x)[i]; \ - memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ --x->n; \ return kp; \ } \ if (r == 0) { \ - if ((yn = __KB_PTR(b, x)[i]->n) >= b->t) { \ + if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \ xp = __KB_PTR(b, x)[i]; \ kp = __KB_KEY(key_t, x)[i]; \ __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ return kp; \ - } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= b->t) { \ + } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \ xp = __KB_PTR(b, x)[i + 1]; \ kp = __KB_KEY(key_t, x)[i]; \ __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ return kp; \ - } else if (yn == b->t - 1 && zn == b->t - 1) { \ + } else if (yn == T - 1 && zn == T - 1) { \ y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ __KB_KEY(key_t, y)[y->n++] = *k; \ - memmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ - if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, z), (unsigned int)(z->n + 1) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, z), (unsigned int)(z->n + 1) * sizeof(void*)); \ y->n += z->n; \ - memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ --x->n; \ - free(z); \ + xfree(z); \ return __kb_delp_aux_##name(b, y, k, s); \ } \ } \ ++i; \ - if ((xp = __KB_PTR(b, x)[i])->n == b->t - 1) { \ - if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= b->t) { \ - memmove(__KB_KEY(key_t, xp) + 1, __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ - if (xp->is_internal) memmove(__KB_PTR(b, xp) + 1, __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \ + if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \ + memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ --y->n; ++xp->n; \ - } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= b->t) { \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \ __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ --y->n; \ - memmove(__KB_KEY(key_t, y), __KB_KEY(key_t, y) + 1, (unsigned int)y->n * sizeof(key_t)); \ - if (y->is_internal) memmove(__KB_PTR(b, y), __KB_PTR(b, y) + 1, (unsigned int)(y->n + 1) * sizeof(void*)); \ - } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == b->t - 1) { \ + memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, y)[1], (unsigned int)(y->n + 1) * sizeof(void*)); \ + } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \ __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ - memmove(__KB_KEY(key_t, y) + y->n, __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ - if (y->is_internal) memmove(__KB_PTR(b, y) + y->n, __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, xp), (unsigned int)(xp->n + 1) * sizeof(void*)); \ y->n += xp->n; \ - memmove(__KB_KEY(key_t, x) + i - 1, __KB_KEY(key_t, x) + i, (unsigned int)(x->n - i) * sizeof(key_t)); \ - memmove(__KB_PTR(b, x) + i, __KB_PTR(b, x) + i + 1, (unsigned int)(x->n - i) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, x)[i], (unsigned int)(x->n - i) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, x)[i + 1], (unsigned int)(x->n - i) * sizeof(void*)); \ --x->n; \ - free(xp); \ + xfree(xp); \ xp = y; \ - } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == b->t - 1) { \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ - memmove(__KB_KEY(key_t, xp) + xp->n, __KB_KEY(key_t, y), (unsigned int)y->n * sizeof(key_t)); \ - if (xp->is_internal) memmove(__KB_PTR(b, xp) + xp->n, __KB_PTR(b, y), (unsigned int)(y->n + 1) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), (unsigned int)y->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), (unsigned int)(y->n + 1) * sizeof(void*)); \ xp->n += y->n; \ - memmove(__KB_KEY(key_t, x) + i, __KB_KEY(key_t, x) + i + 1, (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - memmove(__KB_PTR(b, x) + i + 1, __KB_PTR(b, x) + i + 2, (unsigned int)(x->n - i - 1) * sizeof(void*)); \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ --x->n; \ - free(y); \ + xfree(y); \ } \ } \ return __kb_delp_aux_##name(b, xp, k, s); \ @@ -312,7 +304,7 @@ typedef struct { --b->n_nodes; \ x = b->root; \ b->root = __KB_PTR(b, x)[0]; \ - free(x); \ + xfree(x); \ } \ return ret; \ } \ @@ -321,8 +313,8 @@ typedef struct { return kb_delp_##name(b, &k); \ } -#define __KB_ITR(name, key_t) \ - static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_t *itr) \ +#define __KB_ITR(name, key_t, kbnode_t) \ + static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ { \ itr->p = 0; \ if (b->n_keys == 0) return; \ @@ -334,7 +326,7 @@ typedef struct { itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ } \ } \ - static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ { \ if (itr->p < itr->stack) return 0; \ for (;;) { \ @@ -349,7 +341,7 @@ typedef struct { if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ } \ } \ - static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ { \ if (itr->p < itr->stack) return 0; \ for (;;) { \ @@ -364,7 +356,7 @@ typedef struct { if (itr->p->x && itr->p->i >= 0) return 1; \ } \ } \ - static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_t *itr) \ + static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_##name##_t *itr) \ { \ int i, r = 0; \ itr->p = itr->stack; \ @@ -379,33 +371,37 @@ typedef struct { } \ return 0; \ } \ - static int kb_itr_get_##name(kbtree_##name##_t *b, const key_t k, kbitr_t *itr) \ + static int kb_itr_get_##name(kbtree_##name##_t *b, const key_t k, kbitr_##name##_t *itr) \ { \ return kb_itr_getp_##name(b,&k,itr); \ } \ - static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_t *itr) \ + static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ { \ - key_t k = kb_itr_key(key_t, itr); \ + const key_t k = kb_itr_key(itr); \ kb_delp_##name(b, &k); \ kb_itr_getp_##name(b, &k, itr); \ } +#define KBTREE_INIT(name, key_t, __cmp, T) \ + KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, (sizeof(kbnode_##name##_t)+(2*T)*sizeof(void *))) + -#define KBTREE_INIT(name, key_t, __cmp) \ - __KB_TREE_T(name) \ - __KB_INIT(name, key_t) \ - __KB_GET_AUX1(name, key_t, __cmp) \ - __KB_GET(name, key_t) \ - __KB_INTERVAL(name, key_t) \ - __KB_PUT(name, key_t, __cmp) \ - __KB_DEL(name, key_t) \ - __KB_ITR(name, key_t) +#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_TREE_T(name, key_t, T) \ + __KB_INIT(name, key_t, kbnode_t, T, ILEN) \ + __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + __KB_GET(name, key_t, kbnode_t) \ + __KB_INTERVAL(name, key_t, kbnode_t) \ + __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_DEL(name, key_t, kbnode_t, T) \ + __KB_ITR(name, key_t, kbnode_t) #define KB_DEFAULT_SIZE 512 #define kbtree_t(name) kbtree_##name##_t -#define kb_init(name, s) kb_init_##name(s) -#define kb_destroy(name, b) __kb_destroy(b) +#define kbitr_t(name) kbitr_##name##_t +#define kb_init(name) kb_init_##name() +#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) #define kb_get(name, b, k) kb_get_##name(b, k) #define kb_put(name, b, k) kb_put_##name(b, k) #define kb_del(name, b, k) kb_del_##name(b, k) @@ -421,7 +417,7 @@ typedef struct { #define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) #define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) #define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) -#define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i] +#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i] #define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) #define kb_size(b) ((b)->n_keys) @@ -431,6 +427,8 @@ typedef struct { /* The following is *DEPRECATED*!!! Use the iterator interface instead! */ +#if 0 + typedef struct { kbnode_t *x; int i; @@ -467,4 +465,6 @@ typedef struct { (ret) = __KB_KEY(key_t, __x)[0]; \ } while (0) +#endif + #endif // NVIM_LIB_KBTREE_H -- cgit From 14e19b8aaf458270ec94deb941be8ee78706851a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 28 Aug 2016 13:01:33 +0200 Subject: kbtree: eliminate unneccesary heap allocation --- src/nvim/lib/kbtree.h | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index bfea068206..d72c1d5690 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -40,18 +40,19 @@ #define __KB_PTR(btr, x) (x->ptr) #define __KB_TREE_T(name,key_t,T) \ -typedef struct kbnode_##name##_s kbnode_##name##_t; \ -struct kbnode_##name##_s { \ - int32_t n; \ - bool is_internal; \ - key_t key[2*T-1]; \ - kbnode_##name##_t *ptr[0]; \ -} ; \ - \ - typedef struct { \ - kbnode_##name##_t *root; \ - int n_keys, n_nodes; \ - } kbtree_##name##_t; \ + typedef struct kbnode_##name##_s kbnode_##name##_t; \ + struct kbnode_##name##_s { \ + int32_t n; \ + bool is_internal; \ + key_t key[2*T-1]; \ + kbnode_##name##_t *ptr[0]; \ + } ; \ + \ + typedef struct { \ + kbnode_##name##_t *root; \ + int n_keys, n_nodes; \ + } kbtree_##name##_t; \ + \ typedef struct { \ kbnode_##name##_t *x; \ int i; \ @@ -61,21 +62,11 @@ struct kbnode_##name##_s { \ } kbitr_##name##_t; \ -#define __KB_INIT(name, key_t, kbnode_t, T, ILEN) \ - static inline kbtree_##name##_t *kb_init_##name() \ - { \ - kbtree_##name##_t *b; \ - b = (kbtree_##name##_t*)xcalloc(1, sizeof(kbtree_##name##_t)); \ - b->root = (kbnode_t*)xcalloc(1, ILEN); \ - ++b->n_nodes; \ - return b; \ - } \ - #define __kb_destroy(kbnode_t,b) do { \ int i; \ unsigned int max = 8; \ kbnode_t *x, **top, **stack = 0; \ - if (b) { \ + if (b->root) { \ top = stack = (kbnode_t**)xcalloc(max, sizeof(kbnode_t*)); \ *top++ = (b)->root; \ while (top != stack) { \ @@ -93,7 +84,7 @@ struct kbnode_##name##_s { \ xfree(x); \ } \ } \ - xfree(b); xfree(stack); \ + xfree(stack); \ } while (0) #define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ @@ -115,6 +106,9 @@ struct kbnode_##name##_s { \ #define __KB_GET(name, key_t, kbnode_t) \ static key_t *kb_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ { \ + if (!b->root) { \ + return 0; \ + } \ int i, r = 0; \ kbnode_t *x = b->root; \ while (x) { \ @@ -133,6 +127,9 @@ struct kbnode_##name##_s { \ #define __KB_INTERVAL(name, key_t, kbnode_t) \ static void kb_intervalp_##name(kbtree_##name##_t *b, const key_t * __restrict k, key_t **lower, key_t **upper) \ { \ + if (!b->root) { \ + return; \ + } \ int i, r = 0; \ kbnode_t *x = b->root; \ *lower = *upper = 0; \ @@ -194,6 +191,10 @@ struct kbnode_##name##_s { \ } \ static key_t *kb_putp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ { \ + if (!b->root) { \ + b->root = (kbnode_t*)xcalloc(1, ILEN); \ + ++b->n_nodes; \ + } \ kbnode_t *r, *s; \ ++b->n_keys; \ r = b->root; \ @@ -358,6 +359,7 @@ struct kbnode_##name##_s { \ } \ static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_##name##_t *itr) \ { \ + if (b->n_keys == 0) return 0; \ int i, r = 0; \ itr->p = itr->stack; \ itr->p->x = b->root; \ @@ -388,7 +390,6 @@ struct kbnode_##name##_s { \ #define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ __KB_TREE_T(name, key_t, T) \ - __KB_INIT(name, key_t, kbnode_t, T, ILEN) \ __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ __KB_GET(name, key_t, kbnode_t) \ __KB_INTERVAL(name, key_t, kbnode_t) \ @@ -400,7 +401,6 @@ struct kbnode_##name##_s { \ #define kbtree_t(name) kbtree_##name##_t #define kbitr_t(name) kbitr_##name##_t -#define kb_init(name) kb_init_##name() #define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) #define kb_get(name, b, k) kb_get_##name(b, k) #define kb_put(name, b, k) kb_put_##name(b, k) -- cgit From 28a549d597a286330ba87ff4fffe1e2d09e0f611 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 28 Aug 2016 13:26:01 +0200 Subject: kbtree: make warning free and delete deprecated macros --- src/nvim/lib/kbtree.h | 95 +++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 59 deletions(-) (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index d72c1d5690..f836dec48f 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -45,7 +45,7 @@ int32_t n; \ bool is_internal; \ key_t key[2*T-1]; \ - kbnode_##name##_t *ptr[0]; \ + kbnode_##name##_t *ptr[]; \ } ; \ \ typedef struct { \ @@ -88,7 +88,7 @@ } while (0) #define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ - static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, const key_t * __restrict k, int *r) \ + static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, int *r) \ { \ int tr, *rr, begin = 0, end = x->n; \ if (x->n == 0) return -1; \ @@ -104,7 +104,7 @@ } #define __KB_GET(name, key_t, kbnode_t) \ - static key_t *kb_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ { \ if (!b->root) { \ return 0; \ @@ -119,13 +119,13 @@ } \ return 0; \ } \ - static inline key_t *kb_get_##name(kbtree_##name##_t *b, const key_t k) \ + static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \ { \ return kb_getp_##name(b, &k); \ } #define __KB_INTERVAL(name, key_t, kbnode_t) \ - static void kb_intervalp_##name(kbtree_##name##_t *b, const key_t * __restrict k, key_t **lower, key_t **upper) \ + static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, key_t **upper) \ { \ if (!b->root) { \ return; \ @@ -145,14 +145,14 @@ x = __KB_PTR(b, x)[i + 1]; \ } \ } \ - static inline void kb_interval_##name(kbtree_##name##_t *b, const key_t k, key_t **lower, key_t **upper) \ + static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \ { \ kb_intervalp_##name(b, &k, lower, upper); \ } #define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ /* x must be an internal node */ \ - static void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ + static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ { \ kbnode_t *z; \ z = (kbnode_t*)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ @@ -168,7 +168,7 @@ __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ ++x->n; \ } \ - static key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k) \ + static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \ { \ int i = x->n - 1; \ key_t *ret; \ @@ -189,7 +189,7 @@ } \ return ret; \ } \ - static key_t *kb_putp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ { \ if (!b->root) { \ b->root = (kbnode_t*)xcalloc(1, ILEN); \ @@ -208,14 +208,14 @@ } \ return __kb_putp_aux_##name(b, r, k); \ } \ - static inline void kb_put_##name(kbtree_##name##_t *b, const key_t k) \ + static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \ { \ kb_putp_##name(b, &k); \ } #define __KB_DEL(name, key_t, kbnode_t, T) \ - static key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, const key_t * __restrict k, int s) \ + static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, int s) \ { \ int yn, zn, i, r = 0; \ kbnode_t *xp, *y, *z; \ @@ -295,7 +295,7 @@ } \ return __kb_delp_aux_##name(b, xp, k, s); \ } \ - static key_t kb_delp_##name(kbtree_##name##_t *b, const key_t * __restrict k) \ + static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ { \ kbnode_t *x; \ key_t ret; \ @@ -309,7 +309,7 @@ } \ return ret; \ } \ - static inline key_t kb_del_##name(kbtree_##name##_t *b, const key_t k) \ + static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ { \ return kb_delp_##name(b, &k); \ } @@ -357,7 +357,7 @@ if (itr->p->x && itr->p->i >= 0) return 1; \ } \ } \ - static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_##name##_t *itr) \ + static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, kbitr_##name##_t *itr) \ { \ if (b->n_keys == 0) return 0; \ int i, r = 0; \ @@ -373,13 +373,13 @@ } \ return 0; \ } \ - static int kb_itr_get_##name(kbtree_##name##_t *b, const key_t k, kbitr_##name##_t *itr) \ + static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \ { \ return kb_itr_getp_##name(b,&k,itr); \ } \ static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ { \ - const key_t k = kb_itr_key(itr); \ + key_t k = kb_itr_key(itr); \ kb_delp_##name(b, &k); \ kb_itr_getp_##name(b, &k, itr); \ } @@ -387,15 +387,34 @@ #define KBTREE_INIT(name, key_t, __cmp, T) \ KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, (sizeof(kbnode_##name##_t)+(2*T)*sizeof(void *))) +#if (!defined(__clang__) && !defined(__INTEL_COMPILER)) && (__GNUC__ > 4 ) + +// The index trickery shouldn't be UB anymore, +// still it is to much for gcc:s -Werror=array-bounds +# define __KB_PRAGMA_START \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Warray-bounds\"") + +# define __KB_PRAGMA_END \ + _Pragma("GCC diagnostic pop") \ + +#else + +# define __KB_PRAGMA_START +# define __KB_PRAGMA_END + +#endif #define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_PRAGMA_START \ __KB_TREE_T(name, key_t, T) \ __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ __KB_GET(name, key_t, kbnode_t) \ __KB_INTERVAL(name, key_t, kbnode_t) \ __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ __KB_DEL(name, key_t, kbnode_t, T) \ - __KB_ITR(name, key_t, kbnode_t) + __KB_ITR(name, key_t, kbnode_t) \ + __KB_PRAGMA_END #define KB_DEFAULT_SIZE 512 @@ -425,46 +444,4 @@ #define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) #define kb_str_cmp(a, b) strcmp(a, b) -/* The following is *DEPRECATED*!!! Use the iterator interface instead! */ - -#if 0 - -typedef struct { - kbnode_t *x; - int i; -} __kbstack_t; - -#define __kb_traverse(key_t, b, __func) do { \ - int __kmax = 8; \ - __kbstack_t *__kstack, *__kp; \ - __kp = __kstack = (__kbstack_t*)calloc(__kmax, sizeof(__kbstack_t)); \ - __kp->x = (b)->root; __kp->i = 0; \ - for (;;) { \ - while (__kp->x && __kp->i <= __kp->x->n) { \ - if (__kp - __kstack == __kmax - 1) { \ - __kmax <<= 1; \ - __kstack = (__kbstack_t*)realloc(__kstack, __kmax * sizeof(__kbstack_t)); \ - __kp = __kstack + (__kmax>>1) - 1; \ - } \ - (__kp+1)->i = 0; (__kp+1)->x = __kp->x->is_internal? __KB_PTR(b, __kp->x)[__kp->i] : 0; \ - ++__kp; \ - } \ - --__kp; \ - if (__kp >= __kstack) { \ - if (__kp->x && __kp->i < __kp->x->n) __func(&__KB_KEY(key_t, __kp->x)[__kp->i]); \ - ++__kp->i; \ - } else break; \ - } \ - free(__kstack); \ - } while (0) - -#define __kb_get_first(key_t, b, ret) do { \ - kbnode_t *__x = (b)->root; \ - while (__KB_PTR(b, __x)[0] != 0) \ - __x = __KB_PTR(b, __x)[0]; \ - (ret) = __KB_KEY(key_t, __x)[0]; \ - } while (0) - -#endif - #endif // NVIM_LIB_KBTREE_H -- cgit From 8b375cf471359ad7632af7fa6a2298c9b7596691 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 28 Aug 2016 15:36:18 +0200 Subject: bufhl: fix move --- src/nvim/lib/kbtree.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/lib') diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index f836dec48f..a3943054e6 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -359,7 +359,10 @@ } \ static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, kbitr_##name##_t *itr) \ { \ - if (b->n_keys == 0) return 0; \ + if (b->n_keys == 0) { \ + itr->p = NULL; \ + return 0; \ + } \ int i, r = 0; \ itr->p = itr->stack; \ itr->p->x = b->root; \ @@ -420,6 +423,7 @@ #define kbtree_t(name) kbtree_##name##_t #define kbitr_t(name) kbitr_##name##_t +#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0) #define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) #define kb_get(name, b, k) kb_get_##name(b, k) #define kb_put(name, b, k) kb_put_##name(b, k) -- cgit