diff options
Diffstat (limited to 'src/nvim/lib')
-rw-r--r-- | src/nvim/lib/kbtree.h | 477 | ||||
-rw-r--r-- | src/nvim/lib/khash.h | 730 | ||||
-rw-r--r-- | src/nvim/lib/klist.h | 144 | ||||
-rw-r--r-- | src/nvim/lib/kvec.h | 236 | ||||
-rw-r--r-- | src/nvim/lib/ringbuf.h | 11 |
5 files changed, 3 insertions, 1595 deletions
diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h deleted file mode 100644 index 99f79952d7..0000000000 --- a/src/nvim/lib/kbtree.h +++ /dev/null @@ -1,477 +0,0 @@ -/*- - * Copyright 1997-1999, 2001, John-Mark Gurney. - * 2008-2009, Attractive Chaos <attractor@live.co.uk> - * - * 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. - */ - -// Gotchas -// ------- -// -// if you delete from a kbtree while iterating over it you must use -// kb_del_itr and not kb_del otherwise the iterator might point to freed memory. - -#ifndef NVIM_LIB_KBTREE_H -#define NVIM_LIB_KBTREE_H - -#include <assert.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "nvim/memory.h" - -#define KB_MAX_DEPTH 64 - -#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[]; \ - }; \ - typedef struct { \ - 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_destroy(kbnode_t, b) do { \ - int i; \ - unsigned int max = 8; \ - kbnode_t *x, **top, **stack = 0; \ - if (b->root) { \ - top = stack = (kbnode_t **)xcalloc(max, sizeof(kbnode_t *)); \ - *top++ = (b)->root; \ - while (top != stack) { \ - x = *--top; \ - if (x->is_internal == 0) { XFREE_CLEAR(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 **)xrealloc(stack, max * sizeof(kbnode_t *)); \ - top = stack + (max>>1); \ - } \ - *top++ = __KB_PTR(b, x)[i]; \ - } \ - XFREE_CLEAR(x); \ - } \ - } \ - XFREE_CLEAR(stack); \ -} while (0) - -#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ - 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; \ - 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, kbnode_t) \ - static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ - { \ - if (!b->root) { \ - return 0; \ - } \ - 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, key_t k) \ - { \ - return kb_getp_##name(b, &k); \ - } - -#define __KB_INTERVAL(name, key_t, kbnode_t) \ - static inline void kb_intervalp_##name(kbtree_##name##_t *b, 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; \ - 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, 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 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)); \ - ++b->n_nodes; \ - z->is_internal = y->is_internal; \ - 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)[T - 1]; \ - ++x->n; \ - } \ - 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; \ - 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 * 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 inline key_t *kb_putp_##name(kbtree_##name##_t *b, 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; \ - if (r->n == 2 * T - 1) { \ - ++b->n_nodes; \ - 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); \ - r = s; \ - } \ - return __kb_putp_aux_##name(b, r, 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 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; \ - 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) >= 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) >= 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 == 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 *)); \ - 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; \ - XFREE_CLEAR(z); \ - return __kb_delp_aux_##name(b, y, k, s); \ - } \ - } \ - ++i; \ - 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 >= 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 == 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; \ - XFREE_CLEAR(xp); \ - xp = y; \ - } 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 *)); \ - 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; \ - XFREE_CLEAR(y); \ - } \ - } \ - return __kb_delp_aux_##name(b, xp, k, s); \ - } \ - static inline key_t kb_delp_##name(kbtree_##name##_t *b, 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]; \ - XFREE_CLEAR(x); \ - } \ - return ret; \ - } \ - static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ - { \ - return kb_delp_##name(b, &k); \ - } - -#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 = NULL; \ - 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_##name##_t *itr) \ - { \ - if (itr->p == NULL) return 0; \ - for (;;) { \ - ++itr->p->i; \ - assert(itr->p->i <= 21); \ - 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; \ - } \ - if (itr->p == itr->stack) { \ - itr->p = NULL; \ - return 0; \ - } \ - --itr->p; \ - 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_##name##_t *itr) \ - { \ - if (itr->p == NULL) 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; \ - } \ - if (itr->p == itr->stack) { \ - itr->p = NULL; \ - return 0; \ - } \ - --itr->p; \ - --itr->p->i; \ - if (itr->p->x && itr->p->i >= 0) return 1; \ - } \ - } \ - static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, \ - kbitr_##name##_t *itr) \ - { \ - if (b->n_keys == 0) { \ - itr->p = NULL; \ - return 0; \ - } \ - 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; \ - assert(itr->p->i <= 21); \ - itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ - ++itr->p; \ - } \ - itr->p->i = 0; \ - return 0; \ - } \ - 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) \ - { \ - 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_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ - __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) - -#define KB_DEFAULT_SIZE 512 - -#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) -#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_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(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) - -#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) -#define kb_str_cmp(a, b) strcmp(a, b) - -#endif // NVIM_LIB_KBTREE_H diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h deleted file mode 100644 index 57a41f9c13..0000000000 --- a/src/nvim/lib/khash.h +++ /dev/null @@ -1,730 +0,0 @@ -/* The MIT License - - Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk> - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -/* - Example: - - #include "nvim/khash.h" - KHASH_MAP_INIT_INT(32, char) - int main() { - int ret, is_missing; - khiter_t k; - khash_t(32) *h = kh_init(32); - k = kh_put(32, h, 5, &ret); - kh_value(h, k) = 10; - k = kh_get(32, h, 10); - is_missing = (k == kh_end(h)); - k = kh_get(32, h, 5); - kh_del(32, h, k); - for (k = kh_begin(h); k != kh_end(h); ++k) - if (kh_exist(h, k)) kh_value(h, k) = 1; - kh_destroy(32, h); - return 0; - } - */ - -/* - 2013-05-02 (0.2.8): - - * Use quadratic probing. When the capacity is power of 2, stepping function - i*(i+1)/2 guarantees to traverse each bucket. It is better than double - hashing on cache performance and is more robust than linear probing. - - In theory, double hashing should be more robust than quadratic probing. - However, my implementation is probably not for large hash tables, because - the second hash function is closely tied to the first hash function, - which reduce the effectiveness of double hashing. - - Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php - - 2011-12-29 (0.2.7): - - * Minor code clean up; no actual effect. - - 2011-09-16 (0.2.6): - - * The capacity is a power of 2. This seems to dramatically improve the - speed for simple keys. Thank Zilong Tan for the suggestion. Reference: - - - http://code.google.com/p/ulib/ - - http://nothings.org/computer/judy/ - - * Allow to optionally use linear probing which usually has better - performance for random input. Double hashing is still the default as it - is more robust to certain non-random input. - - * Added Wang's integer hash function (not used by default). This hash - function is more robust to certain non-random input. - - 2011-02-14 (0.2.5): - - * Allow to declare global functions. - - 2009-09-26 (0.2.4): - - * Improve portability - - 2008-09-19 (0.2.3): - - * Corrected the example - * Improved interfaces - - 2008-09-11 (0.2.2): - - * Improved speed a little in kh_put() - - 2008-09-10 (0.2.1): - - * Added kh_clear() - * Fixed a compiling error - - 2008-09-02 (0.2.0): - - * Changed to token concatenation which increases flexibility. - - 2008-08-31 (0.1.2): - - * Fixed a bug in kh_get(), which has not been tested previously. - - 2008-08-31 (0.1.1): - - * Added destructor - */ - -#ifndef NVIM_LIB_KHASH_H -#define NVIM_LIB_KHASH_H - -/*! - @header - - Generic hash table library. - */ - -#define AC_VERSION_KHASH_H "0.2.8" - -#include <limits.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "nvim/func_attr.h" -#include "nvim/memory.h" - -// compiler specific configuration - -#if UINT_MAX == 0xffffffffu -typedef unsigned int khint32_t; -#elif ULONG_MAX == 0xffffffffu -typedef unsigned long khint32_t; -#endif - -#if ULONG_MAX == ULLONG_MAX -typedef unsigned long khint64_t; -#else -typedef unsigned long long khint64_t; -#endif - -#ifdef _MSC_VER -# define kh_inline __inline -#else -# define kh_inline inline -#endif - -typedef khint32_t khint_t; -typedef khint_t khiter_t; - -#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) -#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) -#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) -#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(khint_t)(1ul<<((i&0xfU)<<1))) -#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(khint_t)(2ul<<((i&0xfU)<<1))) -#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(khint_t)(3ul<<((i&0xfU)<<1))) -#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=(khint_t)1ul<<((i&0xfU)<<1)) - -#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) - -#ifndef kroundup32 -# define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, \ - ++(x)) -#endif - -#ifndef kcalloc -# define kcalloc(N, Z) xcalloc(N, Z) -#endif -#ifndef kmalloc -# define kmalloc(Z) xmalloc(Z) -#endif -#ifndef krealloc -# define krealloc(P, Z) xrealloc(P, Z) -#endif -#ifndef kfree -# define kfree(P) XFREE_CLEAR(P) -#endif - -#define __ac_HASH_UPPER 0.77 - -#define __KHASH_TYPE(name, khkey_t, khval_t) \ - typedef struct { \ - khint_t n_buckets, size, n_occupied, upper_bound; \ - khint32_t *flags; \ - khkey_t *keys; \ - khval_t *vals; \ - } kh_##name##_t; - -#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ - extern kh_##name##_t *kh_init_##name(void); \ - extern void kh_dealloc_##name(kh_##name##_t *h); \ - extern void kh_destroy_##name(kh_##name##_t *h); \ - extern void kh_clear_##name(kh_##name##_t *h); \ - extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ - extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ - extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ - extern void kh_del_##name(kh_##name##_t *h, khint_t x); - -#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \ - __hash_equal) \ - SCOPE kh_##name##_t *kh_init_##name(void) \ - REAL_FATTR_UNUSED; \ - SCOPE kh_##name##_t *kh_init_##name(void) { \ - return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); \ - } \ - SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ - { \ - kfree(h->keys); \ - kfree(h->flags); \ - kfree(h->vals); \ - } \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - { \ - if (h) { \ - kh_dealloc_##name(h); \ - kfree(h); \ - } \ - } \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - { \ - if (h && h->flags) { \ - memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ - h->size = h->n_occupied = 0; \ - } \ - } \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - REAL_FATTR_UNUSED; \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - { \ - if (h->n_buckets) { \ - khint_t k, i, last, mask, step = 0; \ - mask = h->n_buckets - 1; \ - k = __hash_func(key); i = k & mask; \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || \ - !__hash_equal(h->keys[i], key))) { \ - i = (i + (++step)) & mask; \ - if (i == last) { \ - return h->n_buckets; \ - } \ - } \ - return __ac_iseither(h->flags, i) ? h->n_buckets : i; \ - } else { \ - return 0; \ - } \ - } \ - SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - { /* This function uses 0.25*n_buckets bytes of working space instead of */ \ - /* [sizeof(key_t+val_t)+.25]*n_buckets. */ \ - khint32_t *new_flags = 0; \ - khint_t j = 1; \ - { \ - kroundup32(new_n_buckets); \ - if (new_n_buckets < 4) { \ - new_n_buckets = 4; \ - } \ - /* requested size is too small */ \ - if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) { \ - j = 0; \ - } else { /* hash table size to be changed (shrink or expand); rehash */ \ - new_flags = (khint32_t *)kmalloc(__ac_fsize(new_n_buckets) \ - * sizeof(khint32_t)); \ - memset(new_flags, 0xaa, \ - __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (h->n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - h->keys = new_keys; \ - if (kh_is_map) { \ - khval_t *new_vals = \ - (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - h->vals = new_vals; \ - } \ - } /* otherwise shrink */ \ - } \ - } \ - if (j) { /* rehashing is needed */ \ - for (j = 0; j != h->n_buckets; ++j) { \ - if (__ac_iseither(h->flags, j) == 0) { \ - khkey_t key = h->keys[j]; \ - khval_t val; \ - khint_t new_mask; \ - new_mask = new_n_buckets - 1; \ - if (kh_is_map) { \ - val = h->vals[j]; \ - } \ - __ac_set_isdel_true(h->flags, j); \ - /* kick-out process; sort of like in Cuckoo hashing */ \ - while (1) { \ - khint_t k, i, step = 0; \ - k = __hash_func(key); \ - i = k & new_mask; \ - while (!__ac_isempty(new_flags, i)) { \ - i = (i + (++step)) & new_mask; \ - } \ - __ac_set_isempty_false(new_flags, i); \ - /* kick out the existing element */ \ - if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \ - { \ - khkey_t tmp = h->keys[i]; \ - h->keys[i] = key; \ - key = tmp; \ - } \ - if (kh_is_map) { \ - khval_t tmp = h->vals[i]; \ - h->vals[i] = val; \ - val = tmp; \ - } \ - /* mark it as deleted in the old hash table */ \ - __ac_set_isdel_true(h->flags, i); \ - } else { /* write the element and jump out of the loop */ \ - h->keys[i] = key; \ - if (kh_is_map) { \ - h->vals[i] = val; \ - } \ - break; \ - } \ - } \ - } \ - } \ - if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ - h->keys = (khkey_t *)krealloc((void *)h->keys, \ - new_n_buckets * sizeof(khkey_t)); \ - if (kh_is_map) { \ - h->vals = (khval_t *)krealloc((void *)h->vals, \ - new_n_buckets * sizeof(khval_t)); \ - } \ - } \ - kfree(h->flags); /* free the working space */ \ - h->flags = new_flags; \ - h->n_buckets = new_n_buckets; \ - h->n_occupied = h->size; \ - h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ - } \ - } \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - REAL_FATTR_UNUSED; \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - { \ - khint_t x; \ - if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ - if (h->n_buckets > (h->size << 1)) { \ - kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \ - } else { \ - kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \ - } \ - } /* TODO: implement automatically shrinking; */ \ - /* resize() already support shrinking */ \ - { \ - khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ - x = site = h->n_buckets; \ - k = __hash_func(key); \ - i = k & mask; \ - if (__ac_isempty(h->flags, i)) { \ - x = i; /* for speed up */ \ - } else { \ - last = i; \ - while (!__ac_isempty(h->flags, i) \ - && (__ac_isdel(h->flags, i) \ - || !__hash_equal(h->keys[i], key))) { \ - if (__ac_isdel(h->flags, i)) { \ - site = i; \ - } \ - i = (i + (++step)) & mask; \ - if (i == last) { \ - x = site; \ - break; \ - } \ - } \ - if (x == h->n_buckets) { \ - if (__ac_isempty(h->flags, i) && site != h->n_buckets) { \ - x = site; \ - } else { \ - x = i; \ - } \ - } \ - } \ - } \ - if (__ac_isempty(h->flags, x)) { /* not present at all */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - h->size++; \ - h->n_occupied++; \ - *ret = 1; \ - } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - h->size++; \ - *ret = 2; \ - } else { \ - *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ - } \ - return x; \ - } \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - { \ - if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ - __ac_set_isdel_true(h->flags, x); \ - --h->size; \ - } \ - } - -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_PROTOTYPES(name, khkey_t, khval_t) - -#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -// --- BEGIN OF HASH FUNCTIONS --- - -/*! @function - @abstract Integer hash function - @param key The integer [khint32_t] - @return The hash value [khint_t] - */ -#define kh_int_hash_func(key) (khint32_t)(key) -/*! @function - @abstract Integer comparison function - */ -#define kh_int_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract 64-bit integer hash function - @param key The integer [khint64_t] - @return The hash value [khint_t] - */ -#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) -/*! @function - @abstract 64-bit integer comparison function - */ -#define kh_int64_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract const char* hash function - @param s Pointer to a null terminated string - @return The hash value - */ -static kh_inline khint_t __ac_X31_hash_string(const char *s) -{ - khint_t h = (khint_t)*s; - if (h) { - for (++s; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; } - } - return h; -} -/*! @function - @abstract Another interface to const char* hash function - @param key Pointer to a null terminated string [const char*] - @return The hash value [khint_t] - */ -#define kh_str_hash_func(key) __ac_X31_hash_string(key) -/*! @function - @abstract Const char* comparison function - */ -#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) - -static kh_inline khint_t __ac_Wang_hash(khint_t key) -{ - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} -#define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key) - -// --- END OF HASH FUNCTIONS --- - -// Other convenient macros... - -/*! - @abstract Type of the hash table. - @param name Name of the hash table [symbol] - */ -#define khash_t(name) kh_##name##_t - -/*! @function - @abstract Initiate a hash table. - @param name Name of the hash table [symbol] - @return Pointer to the hash table [khash_t(name)*] - */ -#define kh_init(name) kh_init_##name() - -/*! @function - @abstract Destroy a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_destroy(name, h) kh_destroy_##name(h) - -/*! @function - @abstract Free memory referenced directly inside a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_dealloc(name, h) kh_dealloc_##name(h) - -/*! @function - @abstract Reset a hash table without deallocating memory. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_clear(name, h) kh_clear_##name(h) - -/*! @function - @abstract Resize a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param s New size [khint_t] - */ -#define kh_resize(name, h, s) kh_resize_##name(h, s) - -/*! @function - @abstract Insert a key to the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @param r Extra return code: -1 if the operation failed; - 0 if the key is present in the hash table; - 1 if the bucket is empty (never used); 2 if the element in - the bucket has been deleted [int*] - @return Iterator to the inserted element [khint_t] - */ -#define kh_put(name, h, k, r) kh_put_##name(h, k, r) - -/*! @function - @abstract Retrieve a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] - */ -#define kh_get(name, h, k) kh_get_##name(h, k) - -/*! @function - @abstract Remove a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Iterator to the element to be deleted [khint_t] - */ -#define kh_del(name, h, k) kh_del_##name(h, k) - -/*! @function - @abstract Test whether a bucket contains data. - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return 1 if containing data; 0 otherwise [int] - */ -#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) - -/*! @function - @abstract Get key given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Key [type of keys] - */ -#define kh_key(h, x) ((h)->keys[x]) - -/*! @function - @abstract Get value given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Value [type of values] - @discussion For hash sets, calling this results in segfault. - */ -#define kh_val(h, x) ((h)->vals[x]) - -/*! @function - @abstract Alias of kh_val() - */ -#define kh_value(h, x) ((h)->vals[x]) - -/*! @function - @abstract Get the start iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The start iterator [khint_t] - */ -#define kh_begin(h) (khint_t)(0) - -/*! @function - @abstract Get the end iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The end iterator [khint_t] - */ -#define kh_end(h) ((h)->n_buckets) - -/*! @function - @abstract Get the number of elements in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of elements in the hash table [khint_t] - */ -#define kh_size(h) ((h)->size) - -/*! @function - @abstract Get the number of buckets in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of buckets in the hash table [khint_t] - */ -#define kh_n_buckets(h) ((h)->n_buckets) - -/*! @function - @abstract Iterate over the entries in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which key will be assigned - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (kvar) = kh_key(h, __i); \ - (vvar) = kh_val(h, __i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the values in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_value(h, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (vvar) = kh_val(h, __i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the keys in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_key(h, kvar, code) \ - { \ - khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); __i++) { \ - if (!kh_exist(h, __i)) { \ - continue; \ - } \ - (kvar) = kh_key(h, __i); \ - code; \ - } \ - } - -// More convenient interfaces - -/*! @function - @abstract Instantiate a hash set containing integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT(name) \ - KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT(name, khval_t) \ - KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT64(name) \ - KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT64(name, khval_t) \ - KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) - -typedef const char *kh_cstr_t; -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_STR(name) \ - KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_STR(name, khval_t) \ - KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Return a literal for an empty hash table. - @param name Name of the hash table [symbol] - */ -#define KHASH_EMPTY_TABLE(name) \ - ((kh_##name##_t) { \ - .n_buckets = 0, \ - .size = 0, \ - .n_occupied = 0, \ - .upper_bound = 0, \ - .flags = NULL, \ - .keys = NULL, \ - .vals = NULL, \ - }) -#endif // NVIM_LIB_KHASH_H diff --git a/src/nvim/lib/klist.h b/src/nvim/lib/klist.h deleted file mode 100644 index a9abbc6dc2..0000000000 --- a/src/nvim/lib/klist.h +++ /dev/null @@ -1,144 +0,0 @@ -/* The MIT License - - Copyright (c) 2008-2009, by Attractive Chaos <attractor@live.co.uk> - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#ifndef _AC_KLIST_H -#define _AC_KLIST_H - -#include <assert.h> -#include <stdlib.h> - -#include "nvim/func_attr.h" -#include "nvim/memory.h" - -#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ - typedef struct { \ - size_t cnt, n, max; \ - kmptype_t **buf; \ - } kmp_##name##_t; \ - static inline kmp_##name##_t *kmp_init_##name(void) { \ - return xcalloc(1, sizeof(kmp_##name##_t)); \ - } \ - static inline void kmp_destroy_##name(kmp_##name##_t *mp) \ - REAL_FATTR_UNUSED; \ - static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ - size_t k; \ - for (k = 0; k < mp->n; k++) { \ - kmpfree_f(mp->buf[k]); XFREE_CLEAR(mp->buf[k]); \ - } \ - XFREE_CLEAR(mp->buf); XFREE_CLEAR(mp); \ - } \ - static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ - mp->cnt++; \ - if (mp->n == 0) { \ - return xcalloc(1, sizeof(kmptype_t)); \ - } \ - return mp->buf[--mp->n]; \ - } \ - static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ - mp->cnt--; \ - if (mp->n == mp->max) { \ - mp->max = mp->max ? (mp->max << 1) : 16; \ - mp->buf = xrealloc(mp->buf, sizeof(kmptype_t *) * mp->max); \ - } \ - mp->buf[mp->n++] = p; \ - } - -#define kmempool_t(name) kmp_##name##_t -#define kmp_init(name) kmp_init_##name() -#define kmp_destroy(name, mp) kmp_destroy_##name(mp) -#define kmp_alloc(name, mp) kmp_alloc_##name(mp) -#define kmp_free(name, mp, p) kmp_free_##name(mp, p) - -#define KLIST_INIT(name, kltype_t, kmpfree_t) \ - struct __kl1_##name { \ - kltype_t data; \ - struct __kl1_##name *next; \ - }; \ - typedef struct __kl1_##name kl1_##name; \ - KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \ - typedef struct { \ - kl1_##name *head, *tail; \ - kmp_##name##_t *mp; \ - size_t size; \ - } kl_##name##_t; \ - static inline kl_##name##_t *kl_init_##name(void) { \ - kl_##name##_t *kl = xcalloc(1, sizeof(kl_##name##_t)); \ - kl->mp = kmp_init(name); \ - kl->head = kl->tail = kmp_alloc(name, kl->mp); \ - kl->head->next = 0; \ - return kl; \ - } \ - static inline void kl_destroy_##name(kl_##name##_t *kl) \ - REAL_FATTR_UNUSED; \ - static inline void kl_destroy_##name(kl_##name##_t *kl) { \ - kl1_##name *p; \ - for (p = kl->head; p != kl->tail; p = p->next) { \ - kmp_free(name, kl->mp, p); \ - } \ - kmp_free(name, kl->mp, p); \ - kmp_destroy(name, kl->mp); \ - XFREE_CLEAR(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++; \ - q->data = d; \ - } \ - static inline kltype_t kl_shift_at_##name(kl_##name##_t *kl, \ - kl1_##name **n) { \ - assert((*n)->next); \ - kl1_##name *p; \ - kl->size--; \ - p = *n; \ - *n = (*n)->next; \ - if (p == kl->head) { \ - kl->head = *n; \ - } \ - kltype_t d = p->data; \ - kmp_free(name, kl->mp, p); \ - return d; \ - } - -#define kliter_t(name) kl1_##name -#define klist_t(name) kl_##name##_t -#define kl_val(iter) ((iter)->data) -#define kl_next(iter) ((iter)->next) -#define kl_begin(kl) ((kl)->head) -#define kl_end(kl) ((kl)->tail) - -#define kl_init(name) kl_init_##name() -#define kl_destroy(name, kl) kl_destroy_##name(kl) -#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 diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h deleted file mode 100644 index b5b3adf7d2..0000000000 --- a/src/nvim/lib/kvec.h +++ /dev/null @@ -1,236 +0,0 @@ -// The MIT License -// -// Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk> -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// An example: -// -// #include "kvec.h" -// int main() { -// kvec_t(int) array = KV_INITIAL_VALUE; -// kv_push(array, 10); // append -// kv_a(array, 20) = 5; // dynamic -// kv_A(array, 20) = 4; // static -// kv_destroy(array); -// return 0; -// } - -#ifndef NVIM_LIB_KVEC_H -#define NVIM_LIB_KVEC_H - -#include <stdlib.h> -#include <string.h> - -#include "nvim/memory.h" -#include "nvim/os/os_defs.h" - -#define kv_roundup32(x) \ - ((--(x)), \ - ((x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16), \ - (++(x))) - -#define KV_INITIAL_VALUE { .size = 0, .capacity = 0, .items = NULL } - -#define kvec_t(type) \ - struct { \ - size_t size; \ - size_t capacity; \ - type *items; \ - } - -#define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0) -#define kv_destroy(v) \ - do { \ - xfree((v).items); \ - kv_init(v); \ - } while (0) -#define kv_A(v, i) ((v).items[(i)]) -#define kv_pop(v) ((v).items[--(v).size]) -#define kv_size(v) ((v).size) -#define kv_max(v) ((v).capacity) -#define kv_Z(v, i) kv_A(v, kv_size(v) - (i) - 1) -#define kv_last(v) kv_Z(v, 0) - -/// Drop last n items from kvec without resizing -/// -/// Previously spelled as `(void)kv_pop(v)`, repeated n times. -/// -/// @param[out] v Kvec to drop items from. -/// @param[in] n Number of elements to drop. -#define kv_drop(v, n) ((v).size -= (n)) - -#define kv_resize(v, s) \ - ((v).capacity = (s), \ - (v).items = xrealloc((v).items, sizeof((v).items[0]) * (v).capacity)) - -#define kv_resize_full(v) \ - kv_resize(v, (v).capacity ? (v).capacity << 1 : 8) - -#define kv_copy(v1, v0) \ - do { \ - if ((v1).capacity < (v0).size) { \ - kv_resize(v1, (v0).size); \ - } \ - (v1).size = (v0).size; \ - memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \ - } while (0) - -/// fit at least "len" more items -#define kv_ensure_space(v, len) \ - do { \ - if ((v).capacity < (v).size + len) { \ - (v).capacity = (v).size + len; \ - kv_roundup32((v).capacity); \ - kv_resize((v), (v).capacity); \ - } \ - } while (0) - -#define kv_concat_len(v, data, len) \ - do { \ - kv_ensure_space(v, len); \ - memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \ - (v).size = (v).size + len; \ - } while (0) - -#define kv_concat(v, str) kv_concat_len(v, str, STRLEN(str)) -#define kv_splice(v1, v0) kv_concat_len(v1, (v0).items, (v0).size) - -#define kv_pushp(v) \ - ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \ - ((v).items + ((v).size++))) - -#define kv_push(v, x) \ - (*kv_pushp(v) = (x)) - -#define kv_pushp_c(v) ((v).items + ((v).size++)) -#define kv_push_c(v, x) (*kv_pushp_c(v) = (x)) - -#define kv_a(v, i) \ - (*(((v).capacity <= (size_t)(i) \ - ? ((v).capacity = (v).size = (i) + 1, \ - kv_roundup32((v).capacity), \ - kv_resize((v), (v).capacity), 0UL) \ - : ((v).size <= (size_t)(i) \ - ? (v).size = (i) + 1 \ - : 0UL)), \ - &(v).items[(i)])) - -#define kv_printf(v, ...) kv_do_printf(&(v), __VA_ARGS__) - -/// Type of a vector with a few first members allocated on stack -/// -/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last. -/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push, -/// #kv_pushp, #kv_a, #kv_destroy. -/// -/// @param[in] type Type of vector elements. -/// @param[in] init_size Number of the elements in the initial array. -#define kvec_withinit_t(type, INIT_SIZE) \ - struct { \ - size_t size; \ - size_t capacity; \ - type *items; \ - type init_array[INIT_SIZE]; \ - } - -/// Initialize vector with preallocated array -/// -/// @param[out] v Vector to initialize. -#define kvi_init(v) \ - ((v).capacity = ARRAY_SIZE((v).init_array), \ - (v).size = 0, \ - (v).items = (v).init_array) - -/// Move data to a new destination and free source -static inline void *_memcpy_free(void *const restrict dest, void *const restrict src, - const size_t size) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE -{ - memcpy(dest, src, size); - XFREE_CLEAR(src); - return dest; -} - -// -V:kvi_push:512 - -/// Resize vector with preallocated array -/// -/// @note May not resize to an array smaller then init_array: if requested, -/// init_array will be used. -/// -/// @param[out] v Vector to resize. -/// @param[in] s New size. -#define kvi_resize(v, s) \ - ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \ - ? (s) \ - : ARRAY_SIZE((v).init_array)), \ - (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \ - ? ((v).items == (v).init_array \ - ? (v).items \ - : _memcpy_free((v).init_array, (v).items, \ - (v).size * sizeof((v).items[0]))) \ - : ((v).items == (v).init_array \ - ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \ - (v).items, \ - (v).size * sizeof((v).items[0])) \ - : xrealloc((v).items, \ - (v).capacity * sizeof((v).items[0]))))) - -/// Resize vector with preallocated array when it is full -/// -/// @param[out] v Vector to resize. -#define kvi_resize_full(v) \ - /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \ - /* Thus when vector is full capacity may not be zero and it is safe */ \ - /* not to bother with checking whether (v).capacity is 0. But now */ \ - /* capacity is not guaranteed to have size that is a power of 2, it is */ \ - /* hard to fix this here and is not very necessary if users will use */ \ - /* 2^x initial array size. */ \ - kvi_resize(v, (v).capacity << 1) - -/// Get location where to store new element to a vector with preallocated array -/// -/// @param[in,out] v Vector to push to. -/// -/// @return Pointer to the place where new value should be stored. -#define kvi_pushp(v) \ - ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \ - ((v).items + ((v).size++))) - -/// Push value to a vector with preallocated array -/// -/// @param[out] v Vector to push to. -/// @param[in] x Value to push. -#define kvi_push(v, x) \ - (*kvi_pushp(v) = (x)) - -/// Free array of elements of a vector with preallocated array if needed -/// -/// @param[out] v Vector to free. -#define kvi_destroy(v) \ - do { \ - if ((v).items != (v).init_array) { \ - XFREE_CLEAR((v).items); \ - } \ - } while (0) - -#endif // NVIM_LIB_KVEC_H diff --git a/src/nvim/lib/ringbuf.h b/src/nvim/lib/ringbuf.h index 4fd110a531..907018a06e 100644 --- a/src/nvim/lib/ringbuf.h +++ b/src/nvim/lib/ringbuf.h @@ -25,14 +25,9 @@ #define _RINGBUF_LENGTH(rb) \ ((rb)->first == NULL ? 0 \ - : ((rb)->next == (rb)->first) ? (size_t)((rb)->buf_end - (rb)->buf) + 1 \ - : ((rb)->next > \ - (rb)->first) ? (size_t)((rb)->next - \ - (rb)->first) \ - : (size_t)((rb)-> \ - next - (rb)->buf + \ - (rb)->buf_end - \ - (rb)->first + 1)) + : ((rb)->next == (rb)->first) ? (size_t)((rb)->buf_end - (rb)->buf) + 1 \ + : ((rb)->next > (rb)->first) ? (size_t)((rb)->next - (rb)->first) \ + : (size_t)((rb)->next - (rb)->buf + (rb)->buf_end - (rb)->first + 1)) #define _RINGBUF_NEXT(rb, var) \ ((var) == (rb)->buf_end ? (rb)->buf : (var) + 1) |