diff --git a/cmake.config/iwyu/mapping.imp b/cmake.config/iwyu/mapping.imp index 22710d8571..7cdd63a723 100644 --- a/cmake.config/iwyu/mapping.imp +++ b/cmake.config/iwyu/mapping.imp @@ -194,7 +194,6 @@ { include: [ '"nvim/extmark_defs.h"', public, '"nvim/extmark.h"', public ] }, { include: [ '"nvim/grid_defs.h"', public, '"nvim/grid.h"', public ] }, { include: [ '"nvim/highlight_defs.h"', public, '"nvim/highlight.h"', public ] }, - { include: [ '"nvim/map_defs.h"', public, '"nvim/map.h"', public ] }, { include: [ '"nvim/mark_defs.h"', public, '"nvim/mark.h"', public ] }, { include: [ '"nvim/mbyte_defs.h"', public, '"nvim/mbyte.h"', public ] }, { include: [ '"nvim/memfile_defs.h"', public, '"nvim/memfile.h"', public ] }, diff --git a/src/clint.py b/src/clint.py index a6649763c2..ee2d0ecc3c 100755 --- a/src/clint.py +++ b/src/clint.py @@ -2244,6 +2244,7 @@ def CheckSpacing(filename, clean_lines, linenum, error): r'(?vals_buf[val_size*(x)]) +#define kh_copyval(to, from) memcpy(to, from, val_size) + +#define __KHASH_IMPL(name, SCOPE, khkey_t, __hash_func, __hash_equal) \ SCOPE kh_##name##_t *kh_init_##name(void) \ - REAL_FATTR_UNUSED; \ + 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; \ + REAL_FATTR_UNUSED; \ SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ { \ kfree(h->keys); \ kfree(h->flags); \ - kfree(h->vals); \ + kfree(h->vals_buf); \ } \ SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ + REAL_FATTR_UNUSED; \ SCOPE void kh_destroy_##name(kh_##name##_t *h) \ { \ if (h) { \ @@ -228,7 +233,7 @@ typedef khint_t khiter_t; } \ } \ SCOPE void kh_clear_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ + REAL_FATTR_UNUSED; \ SCOPE void kh_clear_##name(kh_##name##_t *h) \ { \ if (h && h->flags) { \ @@ -237,7 +242,7 @@ typedef khint_t khiter_t; } \ } \ SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - REAL_FATTR_UNUSED; \ + REAL_FATTR_UNUSED; \ SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ { \ if (h->n_buckets) { \ @@ -257,9 +262,9 @@ typedef khint_t khiter_t; 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) \ + SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size) \ { /* 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; \ @@ -280,23 +285,23 @@ typedef khint_t khiter_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; \ + if (val_size) { \ + char *new_vals = krealloc( h->vals_buf, new_n_buckets * val_size); \ + h->vals_buf = new_vals; \ } \ } /* otherwise shrink */ \ } \ } \ + char cval[KHASH_MAX_VAL_SIZE]; \ + char ctmp[KHASH_MAX_VAL_SIZE]; \ 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]; \ + if (val_size) { \ + kh_copyval(cval, kh_bval(h, j)); \ } \ __ac_set_isdel_true(h->flags, j); \ /* kick-out process; sort of like in Cuckoo hashing */ \ @@ -315,17 +320,17 @@ typedef khint_t khiter_t; h->keys[i] = key; \ key = tmp; \ } \ - if (kh_is_map) { \ - khval_t tmp = h->vals[i]; \ - h->vals[i] = val; \ - val = tmp; \ + if (val_size) { \ + kh_copyval(ctmp, kh_bval(h, i)); \ + kh_copyval(kh_bval(h, i), cval); \ + kh_copyval(cval, ctmp); \ } \ /* 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; \ + if (val_size) { \ + kh_copyval(kh_bval(h, i), cval); \ } \ break; \ } \ @@ -335,9 +340,8 @@ typedef khint_t khiter_t; 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)); \ + if (val_size) { \ + h->vals_buf = krealloc((void *)h->vals_buf, new_n_buckets * val_size); \ } \ } \ kfree(h->flags); /* free the working space */ \ @@ -347,16 +351,16 @@ typedef khint_t khiter_t; 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) \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size) \ + REAL_FATTR_UNUSED; \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size) \ { \ 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 */ \ + kh_resize_##name(h, h->n_buckets - 1, val_size); /* clear "deleted" elements */ \ } else { \ - kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \ + kh_resize_##name(h, h->n_buckets + 1, val_size); /* expand the hash table */ \ } \ } /* TODO: implement automatically shrinking; */ \ /* resize() already support shrinking */ \ @@ -407,7 +411,7 @@ typedef khint_t khiter_t; return x; \ } \ SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - REAL_FATTR_UNUSED; \ + 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)) { \ @@ -416,16 +420,16 @@ typedef khint_t khiter_t; } \ } -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_PROTOTYPES(name, khkey_t, khval_t) +#define KHASH_DECLARE(khkey_t) \ + __KHASH_TYPE(khkey_t, khkey_t) \ + __KHASH_PROTOTYPES(khkey_t, khkey_t) -#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ +#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, __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) + __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, __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) +#define KHASH_INIT(name, khkey_t, khval_t, __hash_func, __hash_equal) \ + KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, __hash_func, __hash_equal) // --- BEGIN OF HASH FUNCTIONS --- @@ -542,7 +546,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) 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) +#define kh_put(name, h, k, r, vs) kh_put_##name(h, k, r, vs) /*! @function @abstract Retrieve a key from the hash table. @@ -584,12 +588,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @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]) +#define kh_val(type, h, x) (*(type *)(&(h)->vals_buf[(x)*(sizeof (type))])) /*! @function @abstract Get the start iterator @@ -626,13 +625,15 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @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; \ - } } +#define kh_foreach(type, 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(type, h,__i); \ + code; \ + } \ +} /*! @function @abstract Iterate over the values in the hash table @@ -640,12 +641,14 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key) @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; \ - } } +#define kh_foreach_value(type, 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(type, h,__i); \ + code; \ + } \ +} /*! @function @abstract Iterate over the keys in the hash table @@ -725,6 +728,6 @@ typedef const char *kh_cstr_t; .upper_bound = 0, \ .flags = NULL, \ .keys = NULL, \ - .vals = NULL, \ + .vals_buf = NULL, \ }) #endif // NVIM_LIB_KHASH_H diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 87232a8a93..d6f0288f94 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -33,12 +33,10 @@ void api_extmark_free_all_mem(void) { String name; - handle_T id; - map_foreach(&namespace_ids, name, id, { - (void)id; + map_foreach_key(&namespace_ids, name, { xfree(name.data); }) - map_destroy(String, handle_T)(&namespace_ids); + map_destroy(String, &namespace_ids); } /// Creates a new namespace or gets an existing one. \*namespace\* @@ -77,7 +75,7 @@ Dictionary nvim_get_namespaces(void) String name; handle_T id; - map_foreach(&namespace_ids, name, id, { + map_foreach(handle_T, &namespace_ids, name, id, { PUT(retval, name.data, INTEGER_OBJ(id)); }) @@ -88,7 +86,7 @@ const char *describe_ns(NS ns_id) { String name; handle_T id; - map_foreach(&namespace_ids, name, id, { + map_foreach(handle_T, &namespace_ids, name, id, { if ((NS)id == ns_id && name.size) { return name.data; } diff --git a/src/nvim/api/extmark.h b/src/nvim/api/extmark.h index a6586e3031..3c979fa4f6 100644 --- a/src/nvim/api/extmark.h +++ b/src/nvim/api/extmark.h @@ -6,7 +6,6 @@ #include "nvim/decoration.h" #include "nvim/macros.h" #include "nvim/map.h" -#include "nvim/map_defs.h" #include "nvim/types.h" EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT); diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 2623c97c9d..bac501ed62 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -122,13 +122,13 @@ #define api_free_window(value) #define api_free_tabpage(value) -EXTERN PMap(handle_T) buffer_handles INIT(= MAP_INIT); -EXTERN PMap(handle_T) window_handles INIT(= MAP_INIT); -EXTERN PMap(handle_T) tabpage_handles INIT(= MAP_INIT); +EXTERN PMap(int) buffer_handles INIT(= MAP_INIT); +EXTERN PMap(int) window_handles INIT(= MAP_INIT); +EXTERN PMap(int) tabpage_handles INIT(= MAP_INIT); -#define handle_get_buffer(h) pmap_get(handle_T)(&buffer_handles, (h)) -#define handle_get_window(h) pmap_get(handle_T)(&window_handles, (h)) -#define handle_get_tabpage(h) pmap_get(handle_T)(&tabpage_handles, (h)) +#define handle_get_buffer(h) pmap_get(int)(&buffer_handles, (h)) +#define handle_get_window(h) pmap_get(int)(&window_handles, (h)) +#define handle_get_tabpage(h) pmap_get(int)(&tabpage_handles, (h)) /// Structure used for saving state for :try /// diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index bd3482c85f..532c3054ab 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -111,7 +111,7 @@ void remote_ui_disconnect(uint64_t channel_id) } UIData *data = ui->data; kv_destroy(data->call_buf); - pmap_del(uint64_t)(&connected_uis, channel_id); + pmap_del(uint64_t)(&connected_uis, channel_id, NULL); ui_detach_impl(ui, channel_id); // Destroy `ui`. diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 2d5d8e262b..17a3fd33f1 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -108,14 +108,13 @@ static Map(int, String) map_augroup_id_to_name = MAP_INIT; static void augroup_map_del(int id, const char *name) { if (name != NULL) { - String key = map_key(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name)); - map_del(String, int)(&map_augroup_name_to_id, key); + String key; + map_del(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name), &key); api_free_string(key); } if (id > 0) { - String mapped = map_get(int, String)(&map_augroup_id_to_name, id); + String mapped = map_del(int, String)(&map_augroup_id_to_name, id, NULL); api_free_string(mapped); - map_del(int, String)(&map_augroup_id_to_name, id); } } @@ -543,7 +542,7 @@ void do_augroup(char *arg, int del_group) String name; int value; - map_foreach(&map_augroup_name_to_id, name, value, { + map_foreach(int, &map_augroup_name_to_id, name, value, { if (value > 0) { msg_puts(name.data); } else { @@ -572,18 +571,15 @@ void free_all_autocmds(void) // Delete the augroup_map, including free the data String name; - int id; - map_foreach(&map_augroup_name_to_id, name, id, { - (void)id; + map_foreach_key(&map_augroup_name_to_id, name, { api_free_string(name); }) - map_destroy(String, int)(&map_augroup_name_to_id); + map_destroy(String, &map_augroup_name_to_id); - map_foreach(&map_augroup_id_to_name, id, name, { - (void)id; + map_foreach_value(String, &map_augroup_id_to_name, name, { api_free_string(name); }) - map_destroy(int, String)(&map_augroup_id_to_name); + map_destroy(int, &map_augroup_id_to_name); // aucmd_win[] is freed in win_free_all() } @@ -1311,7 +1307,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf) block_autocmds(); // We don't want BufEnter/WinEnter autocommands. if (need_append) { win_append(lastwin, auc_win); - pmap_put(handle_T)(&window_handles, auc_win->handle, auc_win); + pmap_put(int)(&window_handles, auc_win->handle, auc_win); win_config_float(auc_win, auc_win->w_float_config); } // Prevent chdir() call in win_enter_ext(), through do_autochdir() @@ -1367,7 +1363,7 @@ win_found: } // Remove the window. win_remove(curwin, NULL); - pmap_del(handle_T)(&window_handles, curwin->handle); + pmap_del(int)(&window_handles, curwin->handle, NULL); if (curwin->w_grid_alloc.chars != NULL) { ui_comp_remove_grid(&curwin->w_grid_alloc); ui_call_win_hide(curwin->w_grid_alloc.handle); diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b2edbf4053..e734a340d9 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -833,7 +833,7 @@ void buf_freeall(buf_T *buf, int flags) /// itself (not the file, that must have been done already). static void free_buffer(buf_T *buf) { - pmap_del(handle_T)(&buffer_handles, buf->b_fnum); + pmap_del(int)(&buffer_handles, buf->b_fnum, NULL); buf_free_count++; // b:changedtick uses an item in buf_T. free_buffer_stuff(buf, kBffClearWinInfo); @@ -1865,7 +1865,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) lastbuf = buf; buf->b_fnum = top_file_num++; - pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf); + pmap_put(int)(&buffer_handles, buf->b_fnum, buf); if (top_file_num < 0) { // wrap around (may cause duplicates) emsg(_("W14: Warning: List of file names overflow")); if (emsg_silent == 0 && !in_assert_fails) { diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 820ce534e1..154b8206b8 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -57,7 +57,7 @@ void channel_teardown(void) { Channel *channel; - map_foreach_value(&channels, channel, { + pmap_foreach_value(&channels, channel, { channel_close(channel->id, kChannelPartAll, NULL); }); } @@ -279,7 +279,7 @@ static void free_channel_event(void **argv) callback_reader_free(&chan->on_stderr); callback_free(&chan->on_exit); - pmap_del(uint64_t)(&channels, chan->id); + pmap_del(uint64_t)(&channels, chan->id, NULL); multiqueue_free(chan->events); xfree(chan); } @@ -289,7 +289,7 @@ static void channel_destroy_early(Channel *chan) if ((chan->id != --next_chan_id)) { abort(); } - pmap_del(uint64_t)(&channels, chan->id); + pmap_del(uint64_t)(&channels, chan->id, NULL); chan->id = 0; if ((--chan->refcount != 0)) { @@ -938,7 +938,7 @@ Array channel_all_info(void) { Channel *channel; Array ret = ARRAY_DICT_INIT; - map_foreach_value(&channels, channel, { + pmap_foreach_value(&channels, channel, { ADD(ret, DICTIONARY_OBJ(channel_info(channel->id))); }); return ret; diff --git a/src/nvim/channel.h b/src/nvim/channel.h index 7400465af0..deb693373c 100644 --- a/src/nvim/channel.h +++ b/src/nvim/channel.h @@ -15,7 +15,6 @@ #include "nvim/macros.h" #include "nvim/main.h" #include "nvim/map.h" -#include "nvim/map_defs.h" #include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/os/pty_process.h" #include "nvim/terminal.h" diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5c05b8faf7..1b21f107a8 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4520,7 +4520,7 @@ bool garbage_collect(bool testing) // Channels { Channel *data; - map_foreach_value(&channels, data, { + pmap_foreach_value(&channels, data, { set_ref_in_callback_reader(&data->on_data, copyID, NULL, NULL); set_ref_in_callback_reader(&data->on_stderr, copyID, NULL, NULL); set_ref_in_callback(&data->on_exit, copyID, NULL, NULL); @@ -4530,7 +4530,7 @@ bool garbage_collect(bool testing) // Timers { timer_T *timer; - map_foreach_value(&timers, timer, { + pmap_foreach_value(&timers, timer, { set_ref_in_callback(&timer->callback, copyID, NULL, NULL); }) } @@ -5986,7 +5986,7 @@ void add_timer_info_all(typval_T *rettv) { tv_list_alloc_ret(rettv, map_size(&timers)); timer_T *timer; - map_foreach_value(&timers, timer, { + pmap_foreach_value(&timers, timer, { if (!timer->stopped || timer->refcount > 1) { add_timer_info(rettv, timer); } @@ -6084,7 +6084,7 @@ static void timer_close_cb(TimeWatcher *tw, void *data) timer_T *timer = (timer_T *)data; multiqueue_free(timer->tw.events); callback_free(&timer->callback); - pmap_del(uint64_t)(&timers, (uint64_t)timer->timer_id); + pmap_del(uint64_t)(&timers, (uint64_t)timer->timer_id, NULL); timer_decref(timer); } @@ -6098,7 +6098,7 @@ static void timer_decref(timer_T *timer) void timer_stop_all(void) { timer_T *timer; - map_foreach_value(&timers, timer, { + pmap_foreach_value(&timers, timer, { timer_stop(timer); }) } diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 727be1562c..acdc36f9c7 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -50,11 +50,6 @@ # include "extmark.c.generated.h" #endif -static uint32_t *buf_ns_ref(buf_T *buf, uint32_t ns_id, bool put) -{ - return map_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, put); -} - /// Create or update an extmark /// /// must not be used during iteration! @@ -62,7 +57,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col colnr_T end_col, Decoration *decor, bool right_gravity, bool end_right_gravity, ExtmarkOp op, Error *err) { - uint32_t *ns = buf_ns_ref(buf, ns_id, true); + uint32_t *ns = map_put_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL, NULL); uint32_t id = idp ? *idp : 0; bool decor_full = false; @@ -237,7 +232,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r bool all_ns = (ns_id == 0); uint32_t *ns = NULL; if (!all_ns) { - ns = buf_ns_ref(buf, ns_id, false); + ns = map_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL); if (!ns) { // nothing to do return false; @@ -258,15 +253,14 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r || (mark.pos.row == u_row && mark.pos.col > u_col)) { break; } - ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), - false); + ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL); if (del_status) { marktree_del_itr(buf->b_marktree, itr, false); if (*del_status >= 0) { // we had a decor_id DecorItem it = kv_A(decors, *del_status); decor_remove(buf, it.row1, mark.pos.row, mark.decor_full); } - map_del(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark)); + map_del(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL); continue; } @@ -294,7 +288,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r } uint64_t id; ssize_t decor_id; - map_foreach(&delete_set, id, decor_id, { + map_foreach(ssize_t, &delete_set, id, decor_id, { mtkey_t mark = marktree_lookup(buf->b_marktree, id, itr); assert(marktree_itr_valid(itr)); marktree_del_itr(buf->b_marktree, itr, false); @@ -303,7 +297,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r decor_remove(buf, it.row1, mark.pos.row, mark.decor_full); } }); - map_clear(uint64_t, ssize_t)(&delete_set); + map_clear(uint64_t, &delete_set); kv_size(decors) = 0; return marks_cleared; } @@ -424,8 +418,8 @@ void extmark_free_all(buf_T *buf) marktree_clear(buf->b_marktree); - map_destroy(uint32_t, uint32_t)(buf->b_extmark_ns); - map_init(uint32_t, uint32_t, buf->b_extmark_ns); + map_destroy(uint32_t, buf->b_extmark_ns); + *buf->b_extmark_ns = (Map(uint32_t, uint32_t)) MAP_INIT; } /// Save info for undo/redo of set marks diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index cc332c530d..a53da95fba 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -50,7 +50,7 @@ static Map(int, int) blendthrough_attr_entries = MAP_INIT; /// highlight entries private to a namespace static Map(ColorKey, ColorItem) ns_hls; typedef int NSHlAttr[HLF_COUNT + 1]; -static PMap(handle_T) ns_hl_attr; +static PMap(int) ns_hl_attr; void highlight_init(void) { @@ -277,7 +277,7 @@ bool hl_check_ns(void) hl_attr_active = highlight_attr; if (ns > 0) { update_ns_hl(ns); - NSHlAttr *hl_def = (NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns); + NSHlAttr *hl_def = (NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns); if (hl_def) { hl_attr_active = *hl_def; } @@ -335,7 +335,7 @@ void update_window_hl(win_T *wp, bool invalid) if (ns_id != wp->w_ns_hl_active || wp->w_ns_hl_attr == NULL) { wp->w_ns_hl_active = ns_id; - wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns_id); + wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns_id); if (!wp->w_ns_hl_attr) { // No specific highlights, use the defaults. wp->w_ns_hl_attr = highlight_attr; @@ -419,7 +419,7 @@ void update_ns_hl(int ns_id) return; } - NSHlAttr **alloc = (NSHlAttr **)pmap_ref(handle_T)(&ns_hl_attr, ns_id, true); + NSHlAttr **alloc = (NSHlAttr **)pmap_put_ref(int)(&ns_hl_attr, ns_id, NULL, NULL); if (*alloc == NULL) { *alloc = xmalloc(sizeof(**alloc)); } @@ -491,28 +491,28 @@ void clear_hl_tables(bool reinit) { if (reinit) { kv_size(attr_entries) = 1; - map_clear(HlEntry, int)(&attr_entry_ids); - map_clear(int, int)(&combine_attr_entries); - map_clear(int, int)(&blend_attr_entries); - map_clear(int, int)(&blendthrough_attr_entries); + map_clear(HlEntry, &attr_entry_ids); + map_clear(int, &combine_attr_entries); + map_clear(int, &blend_attr_entries); + map_clear(int, &blendthrough_attr_entries); memset(highlight_attr_last, -1, sizeof(highlight_attr_last)); highlight_attr_set_all(); highlight_changed(); screen_invalidate_highlights(); } else { kv_destroy(attr_entries); - map_destroy(HlEntry, int)(&attr_entry_ids); - map_destroy(int, int)(&combine_attr_entries); - map_destroy(int, int)(&blend_attr_entries); - map_destroy(int, int)(&blendthrough_attr_entries); - map_destroy(ColorKey, ColorItem)(&ns_hls); + map_destroy(HlEntry, &attr_entry_ids); + map_destroy(int, &combine_attr_entries); + map_destroy(int, &blend_attr_entries); + map_destroy(int, &blendthrough_attr_entries); + map_destroy(ColorKey, &ns_hls); } } void hl_invalidate_blends(void) { - map_clear(int, int)(&blend_attr_entries); - map_clear(int, int)(&blendthrough_attr_entries); + map_clear(int, &blend_attr_entries); + map_clear(int, &blendthrough_attr_entries); highlight_changed(); update_window_hl(curwin, true); } diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index a0f0a947b8..41e7bdb7ac 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1420,7 +1420,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) void free_highlight(void) { ga_clear(&highlight_ga); - map_destroy(cstr_t, int)(&highlight_unames); + map_destroy(cstr_t, &highlight_unames); arena_mem_free(arena_finish(&highlight_arena)); } diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 9586b56f3c..1d11379956 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -910,7 +910,7 @@ static void nlua_common_free_all_mem(lua_State *lstate) if (nlua_track_refs) { // in case there are leaked luarefs, leak the associated memory // to get LeakSanitizer stacktraces on exit - pmap_destroy(handle_T)(&ref_state->ref_markers); + map_destroy(int, &ref_state->ref_markers); } #endif @@ -1285,7 +1285,7 @@ LuaRef nlua_ref(lua_State *lstate, nlua_ref_state_t *ref_state, int index) #ifdef NLUA_TRACK_REFS if (nlua_track_refs) { // dummy allocation to make LeakSanitizer track our luarefs - pmap_put(handle_T)(&ref_state->ref_markers, ref, xmalloc(3)); + pmap_put(int)(&ref_state->ref_markers, ref, xmalloc(3)); } #endif } @@ -1305,7 +1305,7 @@ void nlua_unref(lua_State *lstate, nlua_ref_state_t *ref_state, LuaRef ref) #ifdef NLUA_TRACK_REFS // NB: don't remove entry from map to track double-unref if (nlua_track_refs) { - xfree(pmap_get(handle_T)(&ref_state->ref_markers, ref)); + xfree(pmap_get(int)(&ref_state->ref_markers, ref)); } #endif luaL_unref(lstate, LUA_REGISTRYINDEX, ref); diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h index 7e16c0f45c..f340d9d0d8 100644 --- a/src/nvim/lua/executor.h +++ b/src/nvim/lua/executor.h @@ -24,7 +24,7 @@ typedef struct { LuaRef empty_dict_ref; int ref_count; #if __has_feature(address_sanitizer) - PMap(handle_T) ref_markers; + PMap(int) ref_markers; #endif } nlua_ref_state_t; diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 0c16d09b63..dae1365272 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -231,9 +231,9 @@ int tslua_remove_lang(lua_State *L) const char *lang_name = luaL_checkstring(L, 1); bool present = pmap_has(cstr_t)(&langs, lang_name); if (present) { - char *key = (char *)pmap_key(cstr_t)(&langs, lang_name); - pmap_del(cstr_t)(&langs, lang_name); - xfree(key); + cstr_t key; + pmap_del(cstr_t)(&langs, lang_name, &key); + xfree((void *)key); } lua_pushboolean(L, present); return 1; diff --git a/src/nvim/map.c b/src/nvim/map.c index 191a459863..4c8506f468 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -16,7 +16,6 @@ #include "klib/khash.h" #include "nvim/gettext.h" #include "nvim/map.h" -#include "nvim/map_defs.h" #include "nvim/memory.h" #define cstr_t_hash kh_str_hash_func @@ -29,8 +28,6 @@ #define int_eq kh_int_hash_equal #define handle_T_hash kh_int_hash_func #define handle_T_eq kh_int_hash_equal -#define KittyKey_hash kh_int_hash_func -#define KittyKey_eq kh_int_hash_equal #if defined(ARCH_64) # define ptr_t_hash(key) uint64_t_hash((uint64_t)(key)) @@ -45,74 +42,69 @@ #define DEFAULT_INITIALIZER { 0 } #define SSIZE_INITIALIZER { -1 } +#define KEY_IMPL(T) \ + __KHASH_IMPL(T, , T, T##_hash, T##_eq) \ + #define MAP_IMPL(T, U, ...) \ INITIALIZER_DECLARE(T, U, __VA_ARGS__); \ - __KHASH_IMPL(T##_##U##_map, , T, U, 1, T##_hash, T##_eq) \ - void map_##T##_##U##_destroy(Map(T, U) *map) \ - { \ - kh_dealloc(T##_##U##_map, &map->table); \ - } \ U map_##T##_##U##_get(Map(T, U) *map, T key) \ { \ khiter_t k; \ - if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \ + if ((k = kh_get(T, &map->table, key)) == kh_end(&map->table)) { \ return INITIALIZER(T, U); \ } \ - return kh_val(&map->table, k); \ - } \ - bool map_##T##_##U##_has(Map(T, U) *map, T key) \ - { \ - return kh_get(T##_##U##_map, &map->table, key) != kh_end(&map->table); \ - } \ - T map_##T##_##U##_key(Map(T, U) *map, T key) \ - { \ - khiter_t k; \ - if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \ - abort(); /* Caller must check map_has(). */ \ - } \ - return kh_key(&map->table, k); \ + return kh_val(U, &map->table, k); \ } \ U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \ { \ + STATIC_ASSERT(sizeof(U) <= KHASH_MAX_VAL_SIZE, "increase KHASH_MAX_VAL_SIZE"); \ int ret; \ U rv = INITIALIZER(T, U); \ - khiter_t k = kh_put(T##_##U##_map, &map->table, key, &ret); \ + khiter_t k = kh_put(T, &map->table, key, &ret, sizeof(U)); \ if (!ret) { \ - rv = kh_val(&map->table, k); \ + rv = kh_val(U, &map->table, k); \ } \ - kh_val(&map->table, k) = value; \ + kh_val(U, &map->table, k) = value; \ return rv; \ } \ - U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put) \ + U *map_##T##_##U##_ref(Map(T, U) *map, T key, T **key_alloc) \ + { \ + khiter_t k = kh_get(T, &map->table, key); \ + if (k == kh_end(&map->table)) { \ + return NULL; \ + } \ + if (key_alloc) { \ + *key_alloc = &kh_key(&map->table, k); \ + } \ + return &kh_val(U, &map->table, k); \ + } \ + U *map_##T##_##U##_put_ref(Map(T, U) *map, T key, T **key_alloc, bool *new_item) \ { \ int ret; \ - khiter_t k; \ - if (put) { \ - k = kh_put(T##_##U##_map, &map->table, key, &ret); \ - if (ret) { \ - kh_val(&map->table, k) = INITIALIZER(T, U); \ - } \ - } else { \ - k = kh_get(T##_##U##_map, &map->table, key); \ - if (k == kh_end(&map->table)) { \ - return NULL; \ - } \ + khiter_t k = kh_put(T, &map->table, key, &ret, sizeof(U)); \ + if (ret) { \ + kh_val(U, &map->table, k) = INITIALIZER(T, U); \ } \ - return &kh_val(&map->table, k); \ + if (new_item) { \ + *new_item = (bool)ret; \ + } \ + if (key_alloc) { \ + *key_alloc = &kh_key(&map->table, k); \ + } \ + return &kh_val(U, &map->table, k); \ } \ - U map_##T##_##U##_del(Map(T, U) *map, T key) \ + U map_##T##_##U##_del(Map(T, U) *map, T key, T *key_alloc) \ { \ U rv = INITIALIZER(T, U); \ khiter_t k; \ - if ((k = kh_get(T##_##U##_map, &map->table, key)) != kh_end(&map->table)) { \ - rv = kh_val(&map->table, k); \ - kh_del(T##_##U##_map, &map->table, k); \ + if ((k = kh_get(T, &map->table, key)) != kh_end(&map->table)) { \ + rv = kh_val(U, &map->table, k); \ + if (key_alloc) { \ + *key_alloc = kh_key(&map->table, k); \ + } \ + kh_del(T, &map->table, k); \ } \ return rv; \ - } \ - void map_##T##_##U##_clear(Map(T, U) *map) \ - { \ - kh_clear(T##_##U##_map, &map->table); \ } static inline khint_t String_hash(String s) @@ -162,7 +154,17 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2) return memcmp(&ae1, &ae2, sizeof(ae1)) == 0; } +KEY_IMPL(int) +KEY_IMPL(cstr_t) +KEY_IMPL(ptr_t) +KEY_IMPL(uint64_t) +KEY_IMPL(uint32_t) +KEY_IMPL(String) +KEY_IMPL(HlEntry) +KEY_IMPL(ColorKey) + MAP_IMPL(int, int, DEFAULT_INITIALIZER) +MAP_IMPL(int, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(int, cstr_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, int, DEFAULT_INITIALIZER) @@ -172,26 +174,19 @@ MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(uint64_t, ssize_t, SSIZE_INITIALIZER) MAP_IMPL(uint64_t, uint64_t, DEFAULT_INITIALIZER) MAP_IMPL(uint32_t, uint32_t, DEFAULT_INITIALIZER) -MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER) MAP_IMPL(String, handle_T, 0) MAP_IMPL(String, int, DEFAULT_INITIALIZER) MAP_IMPL(int, String, DEFAULT_INITIALIZER) - MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER) -MAP_IMPL(KittyKey, cstr_t, DEFAULT_INITIALIZER) - /// Deletes a key:value pair from a string:pointer map, and frees the /// storage of both key and value. /// void pmap_del2(PMap(cstr_t) *map, const char *key) { - if (pmap_has(cstr_t)(map, key)) { - void *k = (void *)pmap_key(cstr_t)(map, key); - void *v = pmap_get(cstr_t)(map, key); - pmap_del(cstr_t)(map, key); - xfree(k); - xfree(v); - } + cstr_t key_alloc = NULL; + ptr_t val = pmap_del(cstr_t)(map, key, &key_alloc); + xfree((void *)key_alloc); + xfree(val); } diff --git a/src/nvim/map.h b/src/nvim/map.h index 92f0b32255..cc32a20740 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -7,39 +7,71 @@ #include "klib/khash.h" #include "nvim/api/private/defs.h" -#include "nvim/extmark_defs.h" -#include "nvim/gettext.h" +#include "nvim/assert.h" #include "nvim/highlight_defs.h" -#include "nvim/map_defs.h" -#include "nvim/tui/input_defs.h" #include "nvim/types.h" -#include "nvim/ui_client.h" #if defined(__NetBSD__) # undef uint64_t # define uint64_t uint64_t #endif -#define MAP_DECLS(T, U) \ - KHASH_DECLARE(T##_##U##_map, T, U) \ - typedef struct { \ - khash_t(T##_##U##_map) table; \ - } Map(T, U); \ - Map(T, U) *map_##T##_##U##_new(void); \ - void map_##T##_##U##_free(Map(T, U) *map); \ - void map_##T##_##U##_destroy(Map(T, U) *map); \ - U map_##T##_##U##_get(Map(T, U) *map, T key); \ - bool map_##T##_##U##_has(Map(T, U) *map, T key); \ - T map_##T##_##U##_key(Map(T, U) *map, T key); \ - U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \ - U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put); \ - U map_##T##_##U##_del(Map(T, U) *map, T key); \ - void map_##T##_##U##_clear(Map(T, U) *map); +typedef const char *cstr_t; +typedef void *ptr_t; + +#define Map(T, U) Map_##T##_##U +#define PMap(T) Map(T, ptr_t) + +#define KEY_DECLS(T) \ + KHASH_DECLARE(T) \ + static inline bool set_put_##T(Set(T) *set, T key, T **key_alloc) { \ + int kh_ret; \ + khiter_t k = kh_put(T, set, key, &kh_ret, 0); \ + if (key_alloc) { \ + *key_alloc = &kh_key(set, k); \ + } \ + return kh_ret; \ + } \ + static inline void set_del_##T(Set(T) *set, T key) \ + { \ + khiter_t k; \ + if ((k = kh_get(T, set, key)) != kh_end(set)) { \ + kh_del(T, set, k); \ + } \ + } \ + static inline bool set_has_##T(Set(T) *set, T key) { \ + return (kh_get(T, set, key) != kh_end(set)); \ + } \ + +#define MAP_DECLS(T, U) \ + typedef struct { \ + khash_t(T) table; \ + } Map(T, U); \ + U map_##T##_##U##_get(Map(T, U) *map, T key); \ + static inline bool map_##T##_##U##_has(Map(T, U) *map, T key) \ + { \ + return kh_get(T, &map->table, key) != kh_end(&map->table); \ + } \ + U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \ + U *map_##T##_##U##_ref(Map(T, U) *map, T key, T **key_alloc); \ + U *map_##T##_##U##_put_ref(Map(T, U) *map, T key, T **key_alloc, bool *new_item); \ + U map_##T##_##U##_del(Map(T, U) *map, T key, T *key_alloc); \ -// // NOTE: Keys AND values must be allocated! khash.h does not make a copy. -// + +#define Set(type) khash_t(type) + +KEY_DECLS(int) +KEY_DECLS(cstr_t) +KEY_DECLS(ptr_t) +KEY_DECLS(uint64_t) +KEY_DECLS(uint32_t) +KEY_DECLS(String) +KEY_DECLS(HlEntry) +KEY_DECLS(ColorKey) + MAP_DECLS(int, int) +MAP_DECLS(int, ptr_t) MAP_DECLS(int, cstr_t) MAP_DECLS(cstr_t, ptr_t) MAP_DECLS(cstr_t, int) @@ -49,48 +81,50 @@ MAP_DECLS(uint64_t, ptr_t) MAP_DECLS(uint64_t, ssize_t) MAP_DECLS(uint64_t, uint64_t) MAP_DECLS(uint32_t, uint32_t) - -MAP_DECLS(handle_T, ptr_t) MAP_DECLS(HlEntry, int) MAP_DECLS(String, handle_T) MAP_DECLS(String, int) MAP_DECLS(int, String) - MAP_DECLS(ColorKey, ColorItem) -MAP_DECLS(KittyKey, cstr_t) +#define SET_INIT { 0, 0, 0, 0, NULL, NULL, NULL } +#define MAP_INIT { SET_INIT } -#define MAP_INIT { { 0, 0, 0, 0, NULL, NULL, NULL } } -#define map_init(k, v, map) do { *(map) = (Map(k, v)) MAP_INIT; } while (false) - -#define map_destroy(T, U) map_##T##_##U##_destroy #define map_get(T, U) map_##T##_##U##_get #define map_has(T, U) map_##T##_##U##_has -#define map_key(T, U) map_##T##_##U##_key #define map_put(T, U) map_##T##_##U##_put #define map_ref(T, U) map_##T##_##U##_ref +#define map_put_ref(T, U) map_##T##_##U##_put_ref #define map_del(T, U) map_##T##_##U##_del -#define map_clear(T, U) map_##T##_##U##_clear +#define map_destroy(T, map) kh_dealloc(T, &(map)->table) +#define map_clear(T, map) kh_clear(T, &(map)->table) #define map_size(map) ((map)->table.size) -#define pmap_destroy(T) map_destroy(T, ptr_t) #define pmap_get(T) map_get(T, ptr_t) #define pmap_has(T) map_has(T, ptr_t) -#define pmap_key(T) map_key(T, ptr_t) #define pmap_put(T) map_put(T, ptr_t) #define pmap_ref(T) map_ref(T, ptr_t) +#define pmap_put_ref(T) map_put_ref(T, ptr_t) /// @see pmap_del2 #define pmap_del(T) map_del(T, ptr_t) -#define pmap_clear(T) map_clear(T, ptr_t) -#define pmap_init(k, map) map_init(k, ptr_t, map) -#define map_foreach(map, key, value, block) \ - kh_foreach(&(map)->table, key, value, block) +#define map_foreach(U, map, key, value, block) kh_foreach(U, &(map)->table, key, value, block) -#define map_foreach_value(map, value, block) \ - kh_foreach_value(&(map)->table, value, block) +#define map_foreach_value(U, map, value, block) kh_foreach_value(U, &(map)->table, value, block) +#define map_foreach_key(map, key, block) kh_foreach_key(&(map)->table, key, block) +#define set_foreach(set, key, block) kh_foreach_key(set, key, block) + +#define pmap_foreach_value(map, value, block) map_foreach_value(ptr_t, map, value, block) +#define pmap_foreach(map, key, value, block) map_foreach(ptr_t, map, key, value, block) void pmap_del2(PMap(cstr_t) *map, const char *key); +#define set_has(T, set, key) set_has_##T(set, key) +#define set_put(T, set, key) set_put_##T(set, key, NULL) +#define set_put_ref(T, set, key, key_alloc) set_put_##T(set, key, key_alloc) +#define set_del(T, set, key) set_del_##T(set, key) +#define set_destroy(T, set) kh_dealloc(T, set) +#define set_clear(T, set) kh_clear(T, set) + #endif // NVIM_MAP_H diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h deleted file mode 100644 index 61afedbe50..0000000000 --- a/src/nvim/map_defs.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef NVIM_MAP_DEFS_H -#define NVIM_MAP_DEFS_H - -#include "klib/khash.h" - -typedef const char *cstr_t; -typedef void *ptr_t; - -#define Map(T, U) Map_##T##_##U -#define PMap(T) Map(T, ptr_t) - -#endif // NVIM_MAP_DEFS_H diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 757906d42f..840b6b646e 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -359,7 +359,7 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev) } b->n_keys--; - pmap_del(uint64_t)(b->id2node, id); + pmap_del(uint64_t)(b->id2node, id, NULL); // 5. bool itr_dirty = false; @@ -549,8 +549,8 @@ void marktree_clear(MarkTree *b) b->root = NULL; } if (b->id2node->table.keys) { - pmap_destroy(uint64_t)(b->id2node); - pmap_init(uint64_t, b->id2node); + map_destroy(uint64_t, b->id2node); + *b->id2node = (PMap(uint64_t)) MAP_INIT; } b->n_keys = 0; b->n_nodes = 0; diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h index 29d2abcd46..cd56115b58 100644 --- a/src/nvim/marktree.h +++ b/src/nvim/marktree.h @@ -9,7 +9,6 @@ #include "nvim/assert.h" #include "nvim/garray.h" #include "nvim/map.h" -#include "nvim/map_defs.h" #include "nvim/pos.h" #include "nvim/types.h" diff --git a/src/nvim/memory.c b/src/nvim/memory.c index b9a26e1ac6..1f550ffb01 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -664,6 +664,7 @@ char *arena_memdupz(Arena *arena, const char *buf, size_t size) # include "nvim/getchar.h" # include "nvim/grid.h" # include "nvim/mark.h" +# include "nvim/msgpack_rpc/channel.h" # include "nvim/ops.h" # include "nvim/option.h" # include "nvim/os/os.h" @@ -823,6 +824,7 @@ void free_all_mem(void) ui_free_all_mem(); nlua_free_all_mem(); + rpc_free_all_mem(); // should be last, in case earlier free functions deallocates arenas arena_free_reuse_blks(); diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 96b4bf5c3a..cd5daee915 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -110,7 +110,7 @@ static void log_client_msg(uint64_t channel_id, bool is_request, const char *nam # define log_server_msg(...) #endif -static PMap(cstr_t) event_strings = MAP_INIT; +static Set(cstr_t) event_strings = SET_INIT; static msgpack_sbuffer out_buffer; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -254,14 +254,12 @@ void rpc_subscribe(uint64_t id, char *event) abort(); } - char *event_string = pmap_get(cstr_t)(&event_strings, event); - - if (!event_string) { - event_string = xstrdup(event); - pmap_put(cstr_t)(&event_strings, event_string, event_string); + const char **key_alloc = NULL; + if (set_put_ref(cstr_t, &event_strings, event, &key_alloc)) { + *key_alloc = xstrdup(event); } - pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string); + set_put(cstr_t, channel->rpc.subscribed_events, *key_alloc); } /// Unsubscribes to event broadcasts @@ -553,9 +551,9 @@ static void broadcast_event(const char *name, Array args) kvec_t(Channel *) subscribed = KV_INITIAL_VALUE; Channel *channel; - map_foreach_value(&channels, channel, { + pmap_foreach_value(&channels, channel, { if (channel->is_rpc - && pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) { + && set_has(cstr_t, channel->rpc.subscribed_events, name)) { kv_push(subscribed, channel); } }); @@ -583,24 +581,12 @@ end: static void unsubscribe(Channel *channel, char *event) { - char *event_string = pmap_get(cstr_t)(&event_strings, event); - if (!event_string) { + if (!set_has(cstr_t, &event_strings, event)) { WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'", channel->id, event); return; } - pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string); - - map_foreach_value(&channels, channel, { - if (channel->is_rpc - && pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) { - return; - } - }); - - // Since the string is no longer used by other channels, release it's memory - pmap_del(cstr_t)(&event_strings, event_string); - xfree(event_string); + set_del(cstr_t, channel->rpc.subscribed_events, event); } /// Mark rpc state as closed, and release its reference to the channel. @@ -630,13 +616,7 @@ void rpc_free(Channel *channel) unpacker_teardown(channel->rpc.unpacker); xfree(channel->rpc.unpacker); - // Unsubscribe from all events - char *event_string; - map_foreach_value(channel->rpc.subscribed_events, event_string, { - unsubscribe(channel, event_string); - }); - - pmap_destroy(cstr_t)(channel->rpc.subscribed_events); + set_destroy(cstr_t, channel->rpc.subscribed_events); kv_destroy(channel->rpc.call_stack); api_free_dictionary(channel->rpc.info); } @@ -734,3 +714,12 @@ const char *rpc_client_name(Channel *chan) return NULL; } + +void rpc_free_all_mem(void) +{ + cstr_t key; + set_foreach(&event_strings, key, { + xfree((void *)key); + }); + set_destroy(cstr_t, &event_strings); +} diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h index 404e68329a..1b5f0bb298 100644 --- a/src/nvim/msgpack_rpc/channel_defs.h +++ b/src/nvim/msgpack_rpc/channel_defs.h @@ -31,7 +31,7 @@ typedef struct { } RequestEvent; typedef struct { - PMap(cstr_t) subscribed_events[1]; + Set(cstr_t) subscribed_events[1]; bool closed; Unpacker *unpacker; uint32_t next_request_id; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 34e94d6021..f7b7723553 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -646,21 +646,20 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb return done; } -static void push_path(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, char *entry, +static void push_path(RuntimeSearchPath *search_path, Set(String) *rtp_used, char *entry, bool after) { - handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string(entry)); - if (h == 0) { - char *allocated = xstrdup(entry); - map_put(String, handle_T)(rtp_used, cstr_as_string(allocated), 1); - kv_push(*search_path, ((SearchPathItem){ allocated, after, kNone })); + String *key_alloc; + if (set_put_ref(String, rtp_used, cstr_as_string(entry), &key_alloc)) { + *key_alloc = cstr_to_string(entry); + kv_push(*search_path, ((SearchPathItem){ key_alloc->data, after, kNone })); } } -static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, - char *entry, bool after) +static void expand_rtp_entry(RuntimeSearchPath *search_path, Set(String) *rtp_used, char *entry, + bool after) { - if (map_get(String, handle_T)(rtp_used, cstr_as_string(entry))) { + if (set_has(String, rtp_used, cstr_as_string(entry))) { return; } @@ -679,7 +678,7 @@ static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_ } } -static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, +static void expand_pack_entry(RuntimeSearchPath *search_path, Set(String) *rtp_used, CharVec *after_path, char *pack_entry, size_t pack_entry_len) { static char buf[MAXPATHL]; @@ -712,10 +711,8 @@ static bool path_is_after(char *buf, size_t buflen) RuntimeSearchPath runtime_search_path_build(void) { kvec_t(String) pack_entries = KV_INITIAL_VALUE; - // TODO(bfredl): these should just be sets, when Set(String) is do merge to - // master. Map(String, handle_T) pack_used = MAP_INIT; - Map(String, handle_T) rtp_used = MAP_INIT; + Set(String) rtp_used = SET_INIT; RuntimeSearchPath search_path = KV_INITIAL_VALUE; CharVec after_path = KV_INITIAL_VALUE; @@ -744,7 +741,7 @@ RuntimeSearchPath runtime_search_path_build(void) // fact: &rtp entries can contain wild chars expand_rtp_entry(&search_path, &rtp_used, buf, false); - handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string(buf), false); + handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string(buf), NULL); if (h) { (*h)++; expand_pack_entry(&search_path, &rtp_used, &after_path, buf, buflen); @@ -774,8 +771,8 @@ RuntimeSearchPath runtime_search_path_build(void) // strings are not owned kv_destroy(pack_entries); kv_destroy(after_path); - map_destroy(String, handle_T)(&pack_used); - map_destroy(String, handle_T)(&rtp_used); + map_destroy(String, &pack_used); + set_destroy(String, &rtp_used); return search_path; } diff --git a/src/nvim/shada.c b/src/nvim/shada.c index c405b8ca5f..d3a0b12e5e 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -16,7 +16,6 @@ #include #include "auto/config.h" -#include "klib/khash.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" @@ -35,6 +34,7 @@ #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/macros.h" +#include "nvim/map.h" #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memory.h" @@ -62,19 +62,6 @@ # include ENDIAN_INCLUDE_FILE #endif -// Note: when using bufset hash pointers are intentionally casted to uintptr_t -// and not to khint32_t or khint64_t: this way compiler must give a warning -// (-Wconversion) when types change. -#ifdef ARCH_32 -KHASH_SET_INIT_INT(bufset) -#elif defined(ARCH_64) -KHASH_SET_INIT_INT64(bufset) -#else -# error Not a 64- or 32-bit architecture -#endif -KHASH_MAP_INIT_STR(fnamebufs, buf_T *) -KHASH_SET_INIT_STR(strset) - #define SEARCH_KEY_MAGIC "sm" #define SEARCH_KEY_SMARTCASE "sc" #define SEARCH_KEY_HAS_LINE_OFFSET "sl" @@ -305,8 +292,6 @@ typedef struct hm_llist_entry { struct hm_llist_entry *prev; ///< Pointer to previous entry or NULL. } HMLListEntry; -KHASH_MAP_INIT_STR(hmll_entries, HMLListEntry *) - /// Sized linked list structure for history merger typedef struct { HMLListEntry *entries; ///< Pointer to the start of the allocated array of @@ -318,9 +303,8 @@ typedef struct { HMLListEntry *last_free_entry; ///< Last unused element in entries array. size_t size; ///< Number of allocated entries. size_t num_entries; ///< Number of entries already used. - khash_t(hmll_entries) contained_entries; ///< Hash mapping all history entry - ///< strings to corresponding entry - ///< pointers. + PMap(cstr_t) contained_entries; ///< Map all history entry strings to + ///< corresponding entry pointers. } HMLList; typedef struct { @@ -348,8 +332,6 @@ typedef struct { Timestamp greatest_timestamp; ///< Greatest timestamp among marks. } FileMarks; -KHASH_MAP_INIT_STR(file_marks, FileMarks) - /// State structure used by shada_write /// /// Before actually writing most of the data is read to this structure. @@ -363,8 +345,8 @@ typedef struct { PossiblyFreedShadaEntry search_pattern; ///< Last search pattern. PossiblyFreedShadaEntry sub_search_pattern; ///< Last s/ search pattern. PossiblyFreedShadaEntry replacement; ///< Last s// replacement string. - khash_t(strset) dumped_variables; ///< Names of already dumped variables. - khash_t(file_marks) file_marks; ///< All file marks. + Set(cstr_t) dumped_variables; ///< Names of already dumped variables. + PMap(cstr_t) file_marks; ///< All file marks. } WriteMergerState; struct sd_read_def; @@ -504,7 +486,7 @@ static inline void hmll_init(HMLList *const hmll, const size_t size) .free_entry = NULL, .size = size, .num_entries = 0, - .contained_entries = KHASH_EMPTY_TABLE(hmll_entries), + .contained_entries = MAP_INIT, }; hmll->last_free_entry = hmll->entries; } @@ -535,10 +517,10 @@ static inline void hmll_remove(HMLList *const hmll, HMLListEntry *const hmll_ent assert(hmll->free_entry == NULL); hmll->free_entry = hmll_entry; } - const khiter_t k = kh_get(hmll_entries, &hmll->contained_entries, - hmll_entry->data.data.history_item.string); - assert(k != kh_end(&hmll->contained_entries)); - kh_del(hmll_entries, &hmll->contained_entries, k); + ptr_t val = pmap_del(cstr_t)(&hmll->contained_entries, + hmll_entry->data.data.history_item.string, NULL); + assert(val); + (void)val; if (hmll_entry->next == NULL) { hmll->last = hmll_entry->prev; } else { @@ -586,11 +568,11 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co } target_entry->data = data; target_entry->can_free_entry = can_free_entry; - int kh_ret; - const khiter_t k = kh_put(hmll_entries, &hmll->contained_entries, - data.data.history_item.string, &kh_ret); - if (kh_ret > 0) { - kh_val(&hmll->contained_entries, k) = target_entry; + bool new_item = false; + ptr_t *val = pmap_put_ref(cstr_t)(&hmll->contained_entries, data.data.history_item.string, + NULL, &new_item); + if (new_item) { + *val = target_entry; } hmll->num_entries++; target_entry->prev = hmll_entry; @@ -614,7 +596,7 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co static inline void hmll_dealloc(HMLList *const hmll) FUNC_ATTR_NONNULL_ALL { - kh_dealloc(hmll_entries, &hmll->contained_entries); + map_destroy(cstr_t, &hmll->contained_entries); xfree(hmll->entries); } @@ -771,30 +753,6 @@ static void close_file(void *cookie) } } -/// Check whether buffer is in the given set -/// -/// @param[in] set Set to check within. -/// @param[in] buf Buffer to find. -/// -/// @return true or false. -static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf) - FUNC_ATTR_PURE -{ - return kh_get(bufset, set, (uintptr_t)buf) != kh_end(set); -} - -/// Check whether string is in the given set -/// -/// @param[in] set Set to check within. -/// @param[in] buf Buffer to find. -/// -/// @return true or false. -static inline bool in_strset(const khash_t(strset) *const set, char *str) - FUNC_ATTR_PURE -{ - return kh_get(strset, set, str) != kh_end(set); -} - /// Msgpack callback for writing to ShaDaWriteDef* static int msgpack_sd_writer_write(void *data, const char *buf, size_t len) { @@ -930,10 +888,11 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, } } HMLList *const hmll = &hms_p->hmll; - const khiter_t k = kh_get(hmll_entries, &hms_p->hmll.contained_entries, - entry.data.history_item.string); - if (k != kh_end(&hmll->contained_entries)) { - HMLListEntry *const existing_entry = kh_val(&hmll->contained_entries, k); + cstr_t *key_alloc = NULL; + ptr_t *val = pmap_ref(cstr_t)(&hms_p->hmll.contained_entries, entry.data.history_item.string, + &key_alloc); + if (val) { + HMLListEntry *const existing_entry = *val; if (entry.timestamp > existing_entry->data.timestamp) { hmll_remove(hmll, existing_entry); } else if (!do_iter && entry.timestamp == existing_entry->data.timestamp) { @@ -944,7 +903,7 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, existing_entry->data = entry; existing_entry->can_free_entry = can_free_entry; // Previous key was freed above, as part of freeing the ShaDa entry. - kh_key(&hmll->contained_entries, k) = entry.data.history_item.string; + *key_alloc = entry.data.history_item.string; return; } else { return; @@ -1046,24 +1005,27 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) /// @param[in] fname File name to find. /// /// @return Pointer to the buffer or NULL. -static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *const fname) +static buf_T *find_buffer(PMap(cstr_t) *const fname_bufs, const char *const fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - int kh_ret; - khint_t k = kh_put(fnamebufs, fname_bufs, fname, &kh_ret); - if (!kh_ret) { - return kh_val(fname_bufs, k); + cstr_t *key_alloc = NULL; + bool new_item = false; + buf_T **ref = (buf_T **)pmap_put_ref(cstr_t)(fname_bufs, fname, &key_alloc, &new_item); + if (new_item) { + *key_alloc = xstrdup(fname); + } else { + return *ref; // item already existed (can be a NULL value) } - kh_key(fname_bufs, k) = xstrdup(fname); + FOR_ALL_BUFFERS(buf) { if (buf->b_ffname != NULL) { if (path_fnamecmp(fname, buf->b_ffname) == 0) { - kh_val(fname_bufs, k) = buf; + *ref = buf; return buf; } } } - kh_val(fname_bufs, k) = NULL; + *ref = NULL; return NULL; } @@ -1163,9 +1125,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) } } ShadaEntry cur_entry; - khash_t(bufset) cl_bufs = KHASH_EMPTY_TABLE(bufset); - khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs); - khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset); + Set(ptr_t) cl_bufs = SET_INIT; + PMap(cstr_t) fname_bufs = MAP_INIT; + Set(cstr_t) oldfiles_set = SET_INIT; if (get_old_files && (oldfiles_list == NULL || force)) { oldfiles_list = tv_list_alloc(kListLenUnknown); set_vim_var_list(VV_OLDFILES, oldfiles_list); @@ -1359,8 +1321,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) break; case kSDItemChange: case kSDItemLocalMark: { - if (get_old_files && !in_strset(&oldfiles_set, - cur_entry.data.filemark.fname)) { + if (get_old_files && !set_has(cstr_t, &oldfiles_set, cur_entry.data.filemark.fname)) { char *fname = cur_entry.data.filemark.fname; if (want_marks) { // Do not bother with allocating memory for the string if already @@ -1368,8 +1329,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) // want_marks is set because this way it may be used for a mark. fname = xstrdup(fname); } - int kh_ret; - (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); + set_put(cstr_t, &oldfiles_set, fname); tv_list_append_allocated_string(oldfiles_list, fname); if (!want_marks) { // Avoid free because this string was already used. @@ -1398,8 +1358,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) break; } } else { - int kh_ret; - (void)kh_put(bufset, &cl_bufs, (uintptr_t)buf, &kh_ret); + set_put(ptr_t, &cl_bufs, buf); #define SDE_TO_FMARK(entry) fm #define AFTERFREE(entry) (entry).data.filemark.fname = NULL #define DUMMY_IDX_ADJ(i) @@ -1440,18 +1399,18 @@ shada_read_main_cycle_end: if (cl_bufs.n_occupied) { FOR_ALL_TAB_WINDOWS(tp, wp) { (void)tp; - if (in_bufset(&cl_bufs, wp->w_buffer)) { + if (set_has(ptr_t, &cl_bufs, wp->w_buffer)) { wp->w_changelistidx = wp->w_buffer->b_changelistlen; } } } - kh_dealloc(bufset, &cl_bufs); + set_destroy(ptr_t, &cl_bufs); const char *key; - kh_foreach_key(&fname_bufs, key, { - xfree((void *)key); + map_foreach_key(&fname_bufs, key, { + xfree((char *)key); }) - kh_dealloc(fnamebufs, &fname_bufs); - kh_dealloc(strset, &oldfiles_set); + map_destroy(cstr_t, &fname_bufs); + set_destroy(cstr_t, &oldfiles_set); } /// Default shada file location: cached path @@ -2154,7 +2113,7 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re break; } case kSDItemVariable: - if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) { + if (!set_has(cstr_t, &wms->dumped_variables, entry.data.global_var.name)) { ret = shada_pack_entry(packer, entry, 0); } shada_free_shada_entry(&entry); @@ -2211,13 +2170,12 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re break; } const char *const fname = entry.data.filemark.fname; - khiter_t k; - int kh_ret; - k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); - FileMarks *const filemarks = &kh_val(&wms->file_marks, k); - if (kh_ret > 0) { - CLEAR_POINTER(filemarks); + cstr_t *key = NULL; + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, NULL); + if (*val == NULL) { + *val = xcalloc(1, sizeof(FileMarks)); } + FileMarks *const filemarks = *val; if (entry.timestamp > filemarks->greatest_timestamp) { filemarks->greatest_timestamp = entry.timestamp; } @@ -2237,9 +2195,8 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re break; } if (wms_entry->can_free_entry) { - if (kh_key(&wms->file_marks, k) - == wms_entry->data.data.filemark.fname) { - kh_key(&wms->file_marks, k) = entry.data.filemark.fname; + if (*key == wms_entry->data.data.filemark.fname) { + *key = entry.data.filemark.fname; } shada_free_shada_entry(&wms_entry->data); } @@ -2281,11 +2238,11 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re /// @param[in] removable_bufs Cache of buffers ignored due to their location. /// /// @return true or false. -static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const removable_bufs) +static inline bool ignore_buf(const buf_T *const buf, Set(ptr_t) *const removable_bufs) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { return (buf->b_ffname == NULL || !buf->b_p_bl || bt_quickfix(buf) \ - || bt_terminal(buf) || in_bufset(removable_bufs, buf)); + || bt_terminal(buf) || set_has(ptr_t, removable_bufs, (ptr_t)buf)); } /// Get list of buffers to write to the shada file @@ -2293,7 +2250,7 @@ static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const rem /// @param[in] removable_bufs Buffers which are ignored /// /// @return ShadaEntry List of buffers to save, kSDItemBufferList entry. -static inline ShadaEntry shada_get_buflist(khash_t(bufset) *const removable_bufs) +static inline ShadaEntry shada_get_buflist(Set(ptr_t) *const removable_bufs) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { int max_bufs = get_shada_parameter('%'); @@ -2461,12 +2418,11 @@ static inline void replace_numbered_mark(WriteMergerState *const wms, const size /// Find buffers ignored due to their location. /// /// @param[out] removable_bufs Cache of buffers ignored due to their location. -static inline void find_removable_bufs(khash_t(bufset) *removable_bufs) +static inline void find_removable_bufs(Set(ptr_t) *removable_bufs) { FOR_ALL_BUFFERS(buf) { if (buf->b_ffname != NULL && shada_removable(buf->b_ffname)) { - int kh_ret; - (void)kh_put(bufset, removable_bufs, (uintptr_t)buf, &kh_ret); + set_put(ptr_t, removable_bufs, (ptr_t)buf); } } } @@ -2518,7 +2474,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef max_reg_lines = get_shada_parameter('"'); } const bool dump_registers = (max_reg_lines != 0); - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; const size_t max_kbyte = (size_t)max_kbyte_i; const size_t num_marked_files = (size_t)get_shada_parameter('\''); const bool dump_global_marks = get_shada_parameter('f') != 0; @@ -2662,8 +2618,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef tv_clear(&vartv); tv_clear(&tgttv); if (spe_ret == kSDWriteSuccessful) { - int kh_ret; - (void)kh_put(strset, &wms->dumped_variables, name, &kh_ret); + set_put(cstr_t, &wms->dumped_variables, name); } } while (var_iter != NULL); } @@ -2723,7 +2678,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef } else { const buf_T *const buf = buflist_findnr(fm.fmark.fnum); if (buf == NULL || buf->b_ffname == NULL - || in_bufset(&removable_bufs, buf)) { + || set_has(ptr_t, &removable_bufs, (ptr_t)buf)) { continue; } fname = buf->b_ffname; @@ -2759,18 +2714,16 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef // Initialize buffers if (num_marked_files > 0) { FOR_ALL_BUFFERS(buf) { - if (buf->b_ffname == NULL || in_bufset(&removable_bufs, buf)) { + if (buf->b_ffname == NULL || set_has(ptr_t, &removable_bufs, buf)) { continue; } const void *local_marks_iter = NULL; const char *const fname = buf->b_ffname; - khiter_t k; - int kh_ret; - k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); - FileMarks *const filemarks = &kh_val(&wms->file_marks, k); - if (kh_ret > 0) { - CLEAR_POINTER(filemarks); + ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, NULL, NULL); + if (*val == NULL) { + *val = xcalloc(1, sizeof(FileMarks)); } + FileMarks *const filemarks = *val; do { fmark_T fm; char name = NUL; @@ -2887,16 +2840,14 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef PACK_WMS_ENTRY(wms->replacement); #undef PACK_WMS_ENTRY - const size_t file_markss_size = kh_size(&wms->file_marks); + const size_t file_markss_size = map_size(&wms->file_marks); FileMarks **const all_file_markss = xmalloc(file_markss_size * sizeof(*all_file_markss)); FileMarks **cur_file_marks = all_file_markss; - for (khint_t i = kh_begin(&wms->file_marks); i != kh_end(&wms->file_marks); - i++) { - if (kh_exist(&wms->file_marks, i)) { - *cur_file_marks++ = &kh_val(&wms->file_marks, i); - } - } + ptr_t val; + map_foreach_value(ptr_t, &wms->file_marks, val, { + *cur_file_marks++ = val; + }) qsort((void *)all_file_markss, file_markss_size, sizeof(*all_file_markss), &compare_file_marks); const size_t file_markss_to_dump = MIN(num_marked_files, file_markss_size); @@ -2949,10 +2900,13 @@ shada_write_exit: hms_dealloc(&wms->hms[i]); } } - kh_dealloc(file_marks, &wms->file_marks); - kh_dealloc(bufset, &removable_bufs); + map_foreach_value(ptr_t, &wms->file_marks, val, { + xfree(val); + }) + map_destroy(cstr_t, &wms->file_marks); + set_destroy(ptr_t, &removable_bufs); msgpack_packer_free(packer); - kh_dealloc(strset, &wms->dumped_variables); + set_destroy(cstr_t, &wms->dumped_variables); xfree(wms); return ret; } @@ -4035,7 +3989,7 @@ static bool shada_removable(const char *name) /// /// @return number of jumplist entries static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, - khash_t(bufset) *const removable_bufs) + Set(ptr_t) *const removable_bufs) { // Initialize jump list size_t jumps_size = 0; @@ -4056,7 +4010,7 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, ? NULL : buflist_findnr(fm.fmark.fnum)); if (buf != NULL - ? in_bufset(removable_bufs, buf) + ? set_has(ptr_t, removable_bufs, (ptr_t)buf) : fm.fmark.fnum != 0) { continue; } @@ -4111,7 +4065,7 @@ void shada_encode_regs(msgpack_sbuffer *const sbuf) void shada_encode_jumps(msgpack_sbuffer *const sbuf) FUNC_ATTR_NONNULL_ALL { - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; find_removable_bufs(&removable_bufs); PossiblyFreedShadaEntry jumps[JUMPLISTSIZE]; size_t jumps_size = shada_init_jumps(jumps, &removable_bufs); @@ -4130,7 +4084,7 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf) void shada_encode_buflist(msgpack_sbuffer *const sbuf) FUNC_ATTR_NONNULL_ALL { - khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); + Set(ptr_t) removable_bufs = SET_INIT; find_removable_bufs(&removable_bufs); ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs); msgpack_packer packer; diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 0b0e321d8c..62a2d1b6e6 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -169,7 +169,7 @@ static VTermScreenCallbacks vterm_screen_callbacks = { .sb_popline = term_sb_pop, }; -static PMap(ptr_t) invalidated_terminals = MAP_INIT; +static Set(ptr_t) invalidated_terminals = SET_INIT; void terminal_init(void) { @@ -183,10 +183,10 @@ void terminal_teardown(void) time_watcher_stop(&refresh_timer); multiqueue_free(refresh_timer.events); time_watcher_close(&refresh_timer, NULL); - pmap_destroy(ptr_t)(&invalidated_terminals); + set_destroy(ptr_t, &invalidated_terminals); // terminal_destroy might be called after terminal_teardown is invoked // make sure it is in an empty, valid state - pmap_init(ptr_t, &invalidated_terminals); + invalidated_terminals = (Set(ptr_t)) SET_INIT; } static void term_output_callback(const char *s, size_t len, void *user_data) @@ -652,12 +652,12 @@ void terminal_destroy(Terminal **termpp) } if (!term->refcount) { - if (pmap_has(ptr_t)(&invalidated_terminals, term)) { + if (set_has(ptr_t, &invalidated_terminals, term)) { // flush any pending changes to the buffer block_autocmds(); refresh_terminal(term); unblock_autocmds(); - pmap_del(ptr_t)(&invalidated_terminals, term); + set_del(ptr_t, &invalidated_terminals, term); } for (size_t i = 0; i < term->sb_current; i++) { xfree(term->sb_buffer[i]); @@ -1027,7 +1027,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data) } memcpy(sbrow->cells, cells, sizeof(cells[0]) * c); - pmap_put(ptr_t)(&invalidated_terminals, term, NULL); + set_put(ptr_t, &invalidated_terminals, term); return 1; } @@ -1068,7 +1068,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) } xfree(sbrow); - pmap_put(ptr_t)(&invalidated_terminals, term, NULL); + set_put(ptr_t, &invalidated_terminals, term); return 1; } @@ -1524,7 +1524,7 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row) term->invalid_end = MAX(term->invalid_end, end_row); } - pmap_put(ptr_t)(&invalidated_terminals, term, NULL); + set_put(ptr_t, &invalidated_terminals, term); if (!refresh_pending) { time_watcher_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0); refresh_pending = true; @@ -1567,10 +1567,10 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data) void *stub; (void)(stub); // don't process autocommands while updating terminal buffers block_autocmds(); - map_foreach(&invalidated_terminals, term, stub, { + set_foreach(&invalidated_terminals, term, { refresh_terminal(term); }); - pmap_clear(ptr_t)(&invalidated_terminals); + set_clear(ptr_t, &invalidated_terminals); unblock_autocmds(); } diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 73ed7b6096..81a68d5b07 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -33,7 +33,7 @@ #define KEY_BUFFER_SIZE 0xfff static const struct kitty_key_map_entry { - KittyKey key; + int key; const char *name; } kitty_key_map_entry[] = { { KITTY_KEY_ESCAPE, "Esc" }, @@ -115,7 +115,7 @@ static const struct kitty_key_map_entry { { KITTY_KEY_KP_BEGIN, "kOrigin" }, }; -static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT; +static Map(int, cstr_t) kitty_key_map = MAP_INIT; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/input.c.generated.h" @@ -135,8 +135,8 @@ void tinput_init(TermInput *input, Loop *loop) input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE); for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) { - map_put(KittyKey, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key, - kitty_key_map_entry[i].name); + map_put(int, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key, + kitty_key_map_entry[i].name); } input->in_fd = STDIN_FILENO; @@ -162,7 +162,7 @@ void tinput_init(TermInput *input, Loop *loop) void tinput_destroy(TermInput *input) { - map_destroy(KittyKey, cstr_t)(&kitty_key_map); + map_destroy(int, &kitty_key_map); rbuffer_free(input->key_buffer); time_watcher_close(&input->timer_handle, NULL); stream_close(&input->read_stream, NULL, NULL); @@ -231,7 +231,7 @@ static void tinput_enqueue(TermInput *input, char *buf, size_t size) static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key) { - const char *name = map_get(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint); + const char *name = map_get(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint); if (name) { char buf[64]; size_t len = 0; @@ -257,7 +257,7 @@ static void forward_simple_utf8(TermInput *input, TermKeyKey *key) char *ptr = key->utf8; if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF - && map_has(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint)) { + && map_has(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint)) { handle_kitty_key_protocol(input, key); return; } @@ -286,8 +286,7 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key) } else { assert(key->modifiers); if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF - && map_has(KittyKey, cstr_t)(&kitty_key_map, - (KittyKey)key->code.codepoint)) { + && map_has(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint)) { handle_kitty_key_protocol(input, key); return; } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 6d09b9f3a3..24f20af2f3 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -127,10 +127,10 @@ void ui_free_all_mem(void) kv_destroy(call_buf); UIEventCallback *event_cb; - map_foreach_value(&ui_event_cbs, event_cb, { + pmap_foreach_value(&ui_event_cbs, event_cb, { free_ui_event_callback(event_cb); }) - pmap_destroy(uint32_t)(&ui_event_cbs); + map_destroy(uint32_t, &ui_event_cbs); } #endif @@ -660,7 +660,7 @@ void ui_call_event(char *name, Array args) { UIEventCallback *event_cb; bool handled = false; - map_foreach_value(&ui_event_cbs, event_cb, { + pmap_foreach_value(&ui_event_cbs, event_cb, { Error err = ERROR_INIT; Object res = nlua_call_ref(event_cb->cb, name, args, false, &err); if (res.type == kObjectTypeBoolean && res.data.boolean == true) { @@ -686,7 +686,7 @@ void ui_cb_update_ext(void) for (size_t i = 0; i < kUIGlobalCount; i++) { UIEventCallback *event_cb; - map_foreach_value(&ui_event_cbs, event_cb, { + pmap_foreach_value(&ui_event_cbs, event_cb, { if (event_cb->ext_widgets[i]) { ui_cb_ext[i] = true; break; @@ -710,9 +710,9 @@ void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets) event_cb->ext_widgets[kUICmdline] = true; } - UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true); + ptr_t *item = pmap_put_ref(uint32_t)(&ui_event_cbs, ns_id, NULL, NULL); if (*item) { - free_ui_event_callback(*item); + free_ui_event_callback((UIEventCallback *)(*item)); } *item = event_cb; @@ -723,8 +723,8 @@ void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets) void ui_remove_cb(uint32_t ns_id) { if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) { - free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id)); - pmap_del(uint32_t)(&ui_event_cbs, ns_id); + UIEventCallback *item = pmap_del(uint32_t)(&ui_event_cbs, ns_id, NULL); + free_ui_event_callback(item); } ui_cb_update_ext(); ui_refresh(); diff --git a/src/nvim/window.c b/src/nvim/window.c index 4f6b5f81a4..90c8ba92f9 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4077,7 +4077,7 @@ static tabpage_T *alloc_tabpage(void) static int last_tp_handle = 0; tabpage_T *tp = xcalloc(1, sizeof(tabpage_T)); tp->handle = ++last_tp_handle; - pmap_put(handle_T)(&tabpage_handles, tp->handle, tp); + pmap_put(int)(&tabpage_handles, tp->handle, tp); // Init t: variables. tp->tp_vars = tv_dict_alloc(); @@ -4090,7 +4090,7 @@ static tabpage_T *alloc_tabpage(void) void free_tabpage(tabpage_T *tp) { - pmap_del(handle_T)(&tabpage_handles, tp->handle); + pmap_del(int)(&tabpage_handles, tp->handle, NULL); diff_clear(tp); for (int idx = 0; idx < SNAP_COUNT; idx++) { clear_snapshot(tp, idx); @@ -5062,7 +5062,7 @@ static win_T *win_alloc(win_T *after, bool hidden) win_T *new_wp = xcalloc(1, sizeof(win_T)); new_wp->handle = ++last_win_id; - pmap_put(handle_T)(&window_handles, new_wp->handle, new_wp); + pmap_put(int)(&window_handles, new_wp->handle, new_wp); grid_assign_handle(&new_wp->w_grid_alloc); @@ -5124,7 +5124,7 @@ void free_wininfo(wininfo_T *wip, buf_T *bp) /// @param tp tab page "win" is in, NULL for current static void win_free(win_T *wp, tabpage_T *tp) { - pmap_del(handle_T)(&window_handles, wp->handle); + pmap_del(int)(&window_handles, wp->handle, NULL); clearFolding(wp); // reduce the reference count to the argument list.