refactor(map): avoid duplicated khash_t types for values

This reduces the total number of khash_t instantiations from 22 to 8.

Make the khash internal functions take the size of values as a runtime
parameter. This is abstracted with typesafe Map containers which
are still specialized for both key, value type.

Introduce `Set(key)` type for when there is no value.

Refactor shada.c to use Map/Set instead of khash directly.
This requires `map_ref` operation to be more flexible.
Return pointers to both key and value, plus an indicator for new_item.
As a bonus, `map_key` is now redundant.

Instead of Map(cstr_t, FileMarks), use a pointer map as the FileMarks struct is
humongous.

Make `event_strings` actually work like an intern pool instead of wtf it
was doing before.
This commit is contained in:
bfredl 2023-05-14 18:45:56 +02:00
parent 33687f5e87
commit e2fdd53d8c
32 changed files with 408 additions and 462 deletions

View File

@ -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 ] },

View File

@ -2244,6 +2244,7 @@ def CheckSpacing(filename, clean_lines, linenum, error):
r'(?<!\bkbtree_t)'
r'(?<!\bkbitr_t)'
r'(?<!\bPMap)'
r'(?<!\bSet)'
r'(?<!\bArrayOf)'
r'(?<!\bDictionaryOf)'
r'(?<!\bDict)'

View File

@ -185,41 +185,46 @@ typedef khint_t khiter_t;
#define __ac_HASH_UPPER 0.77
#define __KHASH_TYPE(name, khkey_t, khval_t) \
// This is only used for stack temporaries. Heap allocation is done with precise sizes.
#define KHASH_MAX_VAL_SIZE 32
#define __KHASH_TYPE(name, khkey_t) \
typedef struct { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
char *vals_buf; \
} kh_##name##_t;
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
#define __KHASH_PROTOTYPES(name, khkey_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_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size); \
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size); \
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) \
#define kh_bval(h, x) (&(h)->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

View File

@ -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;
}

View File

@ -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);

View File

@ -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
///

View File

@ -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`.

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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"

View File

@ -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);
})
}

View File

@ -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

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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();

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -16,7 +16,6 @@
#include <uv.h>
#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;

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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.