mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 05:58:33 +00:00
Refactor: Redefine Map(T)
as a more generic Map(T, U)
macro
To replace `Map(T)`, a new macro `PMap(T)` was defined as `Map(T, ptr_t)` for writing maps that store pointers with less boilerplate
This commit is contained in:
@@ -4,26 +4,26 @@
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/api/private/handle.h"
|
||||
|
||||
#define HANDLE_INIT(name) name##_handles = map_new(uint64_t)()
|
||||
#define HANDLE_INIT(name) name##_handles = pmap_new(uint64_t)()
|
||||
|
||||
#define HANDLE_IMPL(type, name) \
|
||||
static Map(uint64_t) *name##_handles = NULL; \
|
||||
static PMap(uint64_t) *name##_handles = NULL; \
|
||||
\
|
||||
type *handle_get_##name(uint64_t handle) \
|
||||
{ \
|
||||
return map_get(uint64_t)(name##_handles, handle); \
|
||||
return pmap_get(uint64_t)(name##_handles, handle); \
|
||||
} \
|
||||
\
|
||||
void handle_register_##name(type *name) \
|
||||
{ \
|
||||
assert(!name->handle); \
|
||||
name->handle = next_handle++; \
|
||||
map_put(uint64_t)(name##_handles, name->handle, name); \
|
||||
pmap_put(uint64_t)(name##_handles, name->handle, name); \
|
||||
} \
|
||||
\
|
||||
void handle_unregister_##name(type *name) \
|
||||
{ \
|
||||
map_del(uint64_t)(name##_handles, name->handle); \
|
||||
pmap_del(uint64_t)(name##_handles, name->handle); \
|
||||
}
|
||||
|
||||
static uint64_t next_handle = 1;
|
||||
|
@@ -21,7 +21,7 @@
|
||||
/// @param obj The source object
|
||||
/// @param lookup Lookup table containing pointers to all processed objects
|
||||
/// @return The converted value
|
||||
static Object vim_to_object_rec(typval_T *obj, Map(ptr_t) *lookup);
|
||||
static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup);
|
||||
|
||||
static bool object_to_vim(Object obj, typval_T *tv, Error *err);
|
||||
|
||||
@@ -278,10 +278,10 @@ Object vim_to_object(typval_T *obj)
|
||||
{
|
||||
Object rv;
|
||||
// We use a lookup table to break out of cyclic references
|
||||
Map(ptr_t) *lookup = map_new(ptr_t)();
|
||||
PMap(ptr_t) *lookup = pmap_new(ptr_t)();
|
||||
rv = vim_to_object_rec(obj, lookup);
|
||||
// Free the table
|
||||
map_free(ptr_t)(lookup);
|
||||
pmap_free(ptr_t)(lookup);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -422,18 +422,18 @@ static bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
return true;
|
||||
}
|
||||
|
||||
static Object vim_to_object_rec(typval_T *obj, Map(ptr_t) *lookup)
|
||||
static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup)
|
||||
{
|
||||
Object rv = {.type = kObjectTypeNil};
|
||||
|
||||
if (obj->v_type == VAR_LIST || obj->v_type == VAR_DICT) {
|
||||
// Container object, add it to the lookup table
|
||||
if (map_has(ptr_t)(lookup, obj)) {
|
||||
if (pmap_has(ptr_t)(lookup, obj)) {
|
||||
// It's already present, meaning we alredy processed it so just return
|
||||
// nil instead.
|
||||
return rv;
|
||||
}
|
||||
map_put(ptr_t)(lookup, obj, NULL);
|
||||
pmap_put(ptr_t)(lookup, obj, NULL);
|
||||
}
|
||||
|
||||
switch (obj->v_type) {
|
||||
|
124
src/nvim/map.c
124
src/nvim/map.c
@@ -23,66 +23,70 @@
|
||||
#define ptr_t_eq(a, b) uint32_t_eq((uint32_t)a, (uint32_t)b)
|
||||
#endif
|
||||
|
||||
#define INITIALIZER(T, U) T##_##U##_initializer
|
||||
#define INITIALIZER_DECLARE(T, U, ...) const U INITIALIZER(T, U) = __VA_ARGS__
|
||||
#define DEFAULT_INITIALIZER {0}
|
||||
|
||||
#define MAP_IMPL(T) \
|
||||
__KHASH_IMPL(T##_map,, T, void *, 1, T##_hash, T##_eq) \
|
||||
\
|
||||
Map(T) *map_##T##_new() \
|
||||
{ \
|
||||
Map(T) *rv = xmalloc(sizeof(Map(T))); \
|
||||
rv->table = kh_init(T##_map); \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
void map_##T##_free(Map(T) *map) \
|
||||
{ \
|
||||
kh_destroy(T##_map, map->table); \
|
||||
free(map); \
|
||||
} \
|
||||
\
|
||||
void *map_##T##_get(Map(T) *map, T key) \
|
||||
{ \
|
||||
khiter_t k; \
|
||||
\
|
||||
if ((k = kh_get(T##_map, map->table, key)) == kh_end(map->table)) { \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
return kh_val(map->table, k); \
|
||||
} \
|
||||
\
|
||||
bool map_##T##_has(Map(T) *map, T key) \
|
||||
{ \
|
||||
return kh_get(T##_map, map->table, key) != kh_end(map->table); \
|
||||
} \
|
||||
\
|
||||
void *map_##T##_put(Map(T) *map, T key, void *value) \
|
||||
{ \
|
||||
int ret; \
|
||||
void *rv = NULL; \
|
||||
khiter_t k = kh_put(T##_map, map->table, key, &ret); \
|
||||
\
|
||||
if (!ret) { \
|
||||
rv = kh_val(map->table, k); \
|
||||
} \
|
||||
\
|
||||
kh_val(map->table, k) = value; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
void *map_##T##_del(Map(T) *map, T key) \
|
||||
{ \
|
||||
void *rv = NULL; \
|
||||
khiter_t k; \
|
||||
\
|
||||
if ((k = kh_get(T##_map, map->table, key)) != kh_end(map->table)) { \
|
||||
rv = kh_val(map->table, k); \
|
||||
kh_del(T##_map, map->table, k); \
|
||||
} \
|
||||
\
|
||||
return rv; \
|
||||
#define MAP_IMPL(T, U, ...) \
|
||||
INITIALIZER_DECLARE(T, U, __VA_ARGS__); \
|
||||
__KHASH_IMPL(T##_##U##_map,, T, U, 1, T##_hash, T##_eq) \
|
||||
\
|
||||
Map(T, U) *map_##T##_##U##_new() \
|
||||
{ \
|
||||
Map(T, U) *rv = xmalloc(sizeof(Map(T, U))); \
|
||||
rv->table = kh_init(T##_##U##_map); \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
void map_##T##_##U##_free(Map(T, U) *map) \
|
||||
{ \
|
||||
kh_destroy(T##_##U##_map, map->table); \
|
||||
free(map); \
|
||||
} \
|
||||
\
|
||||
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)) { \
|
||||
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); \
|
||||
} \
|
||||
\
|
||||
U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \
|
||||
{ \
|
||||
int ret; \
|
||||
U rv = INITIALIZER(T, U); \
|
||||
khiter_t k = kh_put(T##_##U##_map, map->table, key, &ret); \
|
||||
\
|
||||
if (!ret) { \
|
||||
rv = kh_val(map->table, k); \
|
||||
} \
|
||||
\
|
||||
kh_val(map->table, k) = value; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
U map_##T##_##U##_del(Map(T, U) *map, T key) \
|
||||
{ \
|
||||
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); \
|
||||
} \
|
||||
\
|
||||
return rv; \
|
||||
}
|
||||
|
||||
MAP_IMPL(cstr_t)
|
||||
MAP_IMPL(ptr_t)
|
||||
MAP_IMPL(uint64_t)
|
||||
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
|
||||
MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
|
||||
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
|
||||
|
@@ -5,30 +5,37 @@
|
||||
|
||||
#include "nvim/map_defs.h"
|
||||
|
||||
#define MAP_DECLS(T) \
|
||||
KHASH_DECLARE(T##_map, T, void *) \
|
||||
#define MAP_DECLS(T, U) \
|
||||
KHASH_DECLARE(T##_##U##_map, T, U) \
|
||||
\
|
||||
typedef struct { \
|
||||
khash_t(T##_map) *table; \
|
||||
} Map(T); \
|
||||
khash_t(T##_##U##_map) *table; \
|
||||
} Map(T, U); \
|
||||
\
|
||||
Map(T) *map_##T##_new(void); \
|
||||
void map_##T##_free(Map(T) *map); \
|
||||
void *map_##T##_get(Map(T) *map, T key); \
|
||||
bool map_##T##_has(Map(T) *map, T key); \
|
||||
void* map_##T##_put(Map(T) *map, T key, void *value); \
|
||||
void* map_##T##_del(Map(T) *map, T key);
|
||||
Map(T, U) *map_##T##_##U##_new(void); \
|
||||
void map_##T##_##U##_free(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); \
|
||||
U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \
|
||||
U map_##T##_##U##_del(Map(T, U) *map, T key);
|
||||
|
||||
MAP_DECLS(cstr_t)
|
||||
MAP_DECLS(ptr_t)
|
||||
MAP_DECLS(uint64_t)
|
||||
MAP_DECLS(cstr_t, ptr_t)
|
||||
MAP_DECLS(ptr_t, ptr_t)
|
||||
MAP_DECLS(uint64_t, ptr_t)
|
||||
|
||||
#define map_new(T) map_##T##_new
|
||||
#define map_free(T) map_##T##_free
|
||||
#define map_get(T) map_##T##_get
|
||||
#define map_has(T) map_##T##_has
|
||||
#define map_put(T) map_##T##_put
|
||||
#define map_del(T) map_##T##_del
|
||||
#define map_new(T, U) map_##T##_##U##_new
|
||||
#define map_free(T, U) map_##T##_##U##_free
|
||||
#define map_get(T, U) map_##T##_##U##_get
|
||||
#define map_has(T, U) map_##T##_##U##_has
|
||||
#define map_put(T, U) map_##T##_##U##_put
|
||||
#define map_del(T, U) map_##T##_##U##_del
|
||||
|
||||
#define pmap_new(T) map_new(T, ptr_t)
|
||||
#define pmap_free(T) map_free(T, ptr_t)
|
||||
#define pmap_get(T) map_get(T, ptr_t)
|
||||
#define pmap_has(T) map_has(T, ptr_t)
|
||||
#define pmap_put(T) map_put(T, ptr_t)
|
||||
#define pmap_del(T) map_del(T, ptr_t)
|
||||
|
||||
#define map_foreach(map, key, value, block) \
|
||||
kh_foreach(map->table, key, value, block)
|
||||
|
@@ -7,8 +7,8 @@
|
||||
typedef const char * cstr_t;
|
||||
typedef void * ptr_t;
|
||||
|
||||
#define Map(T) Map_##T
|
||||
|
||||
#define Map(T, U) Map_##T##_##U
|
||||
#define PMap(T) Map(T, ptr_t)
|
||||
|
||||
#endif // NVIM_MAP_DEFS_H
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
typedef struct {
|
||||
uint64_t id;
|
||||
Map(cstr_t) *subscribed_events;
|
||||
PMap(cstr_t) *subscribed_events;
|
||||
bool is_job;
|
||||
msgpack_unpacker *unpacker;
|
||||
msgpack_sbuffer *sbuffer;
|
||||
@@ -34,8 +34,8 @@ typedef struct {
|
||||
} Channel;
|
||||
|
||||
static uint64_t next_id = 1;
|
||||
static Map(uint64_t) *channels = NULL;
|
||||
static Map(cstr_t) *event_strings = NULL;
|
||||
static PMap(uint64_t) *channels = NULL;
|
||||
static PMap(cstr_t) *event_strings = NULL;
|
||||
static msgpack_sbuffer msgpack_event_buffer;
|
||||
|
||||
static void job_out(RStream *rstream, void *data, bool eof);
|
||||
@@ -51,8 +51,8 @@ static Channel *register_channel(void);
|
||||
|
||||
void channel_init()
|
||||
{
|
||||
channels = map_new(uint64_t)();
|
||||
event_strings = map_new(cstr_t)();
|
||||
channels = pmap_new(uint64_t)();
|
||||
event_strings = pmap_new(cstr_t)();
|
||||
msgpack_sbuffer_init(&msgpack_event_buffer);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ bool channel_send_event(uint64_t id, char *type, typval_T *data)
|
||||
Channel *channel = NULL;
|
||||
|
||||
if (id > 0) {
|
||||
if (!(channel = map_get(uint64_t)(channels, id))) {
|
||||
if (!(channel = pmap_get(uint64_t)(channels, id))) {
|
||||
return false;
|
||||
}
|
||||
send_event(channel, type, data);
|
||||
@@ -111,25 +111,25 @@ void channel_subscribe(uint64_t id, char *event)
|
||||
{
|
||||
Channel *channel;
|
||||
|
||||
if (!(channel = map_get(uint64_t)(channels, id))) {
|
||||
if (!(channel = pmap_get(uint64_t)(channels, id))) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *event_string = map_get(cstr_t)(event_strings, event);
|
||||
char *event_string = pmap_get(cstr_t)(event_strings, event);
|
||||
|
||||
if (!event_string) {
|
||||
event_string = xstrdup(event);
|
||||
map_put(cstr_t)(event_strings, event_string, event_string);
|
||||
pmap_put(cstr_t)(event_strings, event_string, event_string);
|
||||
}
|
||||
|
||||
map_put(cstr_t)(channel->subscribed_events, event_string, event_string);
|
||||
pmap_put(cstr_t)(channel->subscribed_events, event_string, event_string);
|
||||
}
|
||||
|
||||
void channel_unsubscribe(uint64_t id, char *event)
|
||||
{
|
||||
Channel *channel;
|
||||
|
||||
if (!(channel = map_get(uint64_t)(channels, id))) {
|
||||
if (!(channel = pmap_get(uint64_t)(channels, id))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ static void broadcast_event(char *type, typval_T *data)
|
||||
Channel *channel;
|
||||
|
||||
map_foreach_value(channels, channel, {
|
||||
if (map_has(cstr_t)(channel->subscribed_events, type)) {
|
||||
if (pmap_has(cstr_t)(channel->subscribed_events, type)) {
|
||||
kv_push(Channel *, subscribed, channel);
|
||||
}
|
||||
});
|
||||
@@ -216,23 +216,23 @@ end:
|
||||
|
||||
static void unsubscribe(Channel *channel, char *event)
|
||||
{
|
||||
char *event_string = map_get(cstr_t)(event_strings, event);
|
||||
map_del(cstr_t)(channel->subscribed_events, event_string);
|
||||
char *event_string = pmap_get(cstr_t)(event_strings, event);
|
||||
pmap_del(cstr_t)(channel->subscribed_events, event_string);
|
||||
|
||||
map_foreach_value(channels, channel, {
|
||||
if (map_has(cstr_t)(channel->subscribed_events, event_string)) {
|
||||
if (pmap_has(cstr_t)(channel->subscribed_events, event_string)) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Since the string is no longer used by other channels, release it's memory
|
||||
map_del(cstr_t)(event_strings, event_string);
|
||||
pmap_del(cstr_t)(event_strings, event_string);
|
||||
free(event_string);
|
||||
}
|
||||
|
||||
static void close_channel(Channel *channel)
|
||||
{
|
||||
map_del(uint64_t)(channels, channel->id);
|
||||
pmap_del(uint64_t)(channels, channel->id);
|
||||
msgpack_sbuffer_free(channel->sbuffer);
|
||||
msgpack_unpacker_free(channel->unpacker);
|
||||
|
||||
@@ -250,7 +250,7 @@ static void close_channel(Channel *channel)
|
||||
unsubscribe(channel, event_string);
|
||||
});
|
||||
|
||||
map_free(cstr_t)(channel->subscribed_events);
|
||||
pmap_free(cstr_t)(channel->subscribed_events);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ static Channel *register_channel()
|
||||
rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
|
||||
rv->sbuffer = msgpack_sbuffer_new();
|
||||
rv->id = next_id++;
|
||||
rv->subscribed_events = map_new(cstr_t)();
|
||||
map_put(uint64_t)(channels, rv->id, rv);
|
||||
rv->subscribed_events = pmap_new(cstr_t)();
|
||||
pmap_put(uint64_t)(channels, rv->id, rv);
|
||||
return rv;
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ typedef struct {
|
||||
} socket;
|
||||
} Server;
|
||||
|
||||
static Map(cstr_t) *servers = NULL;
|
||||
static PMap(cstr_t) *servers = NULL;
|
||||
|
||||
static void connection_cb(uv_stream_t *server, int status);
|
||||
static void free_client(uv_handle_t *handle);
|
||||
@@ -48,7 +48,7 @@ static void free_server(uv_handle_t *handle);
|
||||
|
||||
void server_init()
|
||||
{
|
||||
servers = map_new(cstr_t)();
|
||||
servers = pmap_new(cstr_t)();
|
||||
|
||||
if (!os_getenv("NEOVIM_LISTEN_ADDRESS")) {
|
||||
char *listen_address = (char *)vim_tempname('s');
|
||||
@@ -88,7 +88,7 @@ void server_start(char *endpoint)
|
||||
}
|
||||
|
||||
// Check if the server already exists
|
||||
if (map_has(cstr_t)(servers, addr)) {
|
||||
if (pmap_has(cstr_t)(servers, addr)) {
|
||||
EMSG2("Already listening on %s", addr);
|
||||
return;
|
||||
}
|
||||
@@ -172,7 +172,7 @@ void server_start(char *endpoint)
|
||||
server->type = server_type;
|
||||
|
||||
// Add the server to the hash table
|
||||
map_put(cstr_t)(servers, addr, server);
|
||||
pmap_put(cstr_t)(servers, addr, server);
|
||||
}
|
||||
|
||||
void server_stop(char *endpoint)
|
||||
@@ -183,7 +183,7 @@ void server_stop(char *endpoint)
|
||||
// Trim to `ADDRESS_MAX_SIZE`
|
||||
xstrlcpy(addr, endpoint, sizeof(addr));
|
||||
|
||||
if ((server = map_get(cstr_t)(servers, addr)) == NULL) {
|
||||
if ((server = pmap_get(cstr_t)(servers, addr)) == NULL) {
|
||||
EMSG2("Not listening on %s", addr);
|
||||
return;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ void server_stop(char *endpoint)
|
||||
uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server);
|
||||
}
|
||||
|
||||
map_del(cstr_t)(servers, addr);
|
||||
pmap_del(cstr_t)(servers, addr);
|
||||
}
|
||||
|
||||
static void connection_cb(uv_stream_t *server, int status)
|
||||
|
Reference in New Issue
Block a user