mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
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:
parent
33687f5e87
commit
e2fdd53d8c
@ -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 ] },
|
||||
|
@ -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)'
|
||||
|
135
src/klib/khash.h
135
src/klib/khash.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
///
|
||||
|
@ -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`.
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
109
src/nvim/map.c
109
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);
|
||||
}
|
||||
|
114
src/nvim/map.h
114
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
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
208
src/nvim/shada.c
208
src/nvim/shada.c
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user