mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Improve map module: Refactor into a macro library
The map_* declarations and definitions are now created by a macro invocation with a key type parameter. Also refactored server module to use the updated version.
This commit is contained in:
parent
974eade1a6
commit
37dfe2d48f
126
src/nvim/map.c
126
src/nvim/map.c
@ -8,65 +8,73 @@
|
||||
|
||||
#include "nvim/lib/khash.h"
|
||||
|
||||
__KHASH_IMPL(Map,, kh_cstr_t, void *, 1, kh_str_hash_func, kh_str_hash_equal)
|
||||
#define cstr_t_hash kh_str_hash_func
|
||||
#define cstr_t_eq kh_str_hash_equal
|
||||
#define uint64_t_hash kh_int64_hash_func
|
||||
#define uint64_t_eq kh_int64_hash_equal
|
||||
#define uint32_t_hash kh_int_hash_func
|
||||
#define uint32_t_eq kh_int_hash_equal
|
||||
|
||||
Map *map_new()
|
||||
{
|
||||
Map *rv = xmalloc(sizeof(Map));
|
||||
rv->table = kh_init(Map);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void map_free(Map *map)
|
||||
{
|
||||
kh_clear(Map, map->table);
|
||||
kh_destroy(Map, map->table);
|
||||
free(map);
|
||||
}
|
||||
|
||||
void *map_get(Map *map, const char *key)
|
||||
{
|
||||
khiter_t k;
|
||||
|
||||
if ((k = kh_get(Map, map->table, key)) == kh_end(map->table)) {
|
||||
return NULL;
|
||||
#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_clear(T##_map, map->table); \
|
||||
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_del(T##_map, 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; \
|
||||
}
|
||||
|
||||
return kh_val(map->table, k);
|
||||
}
|
||||
|
||||
bool map_has(Map *map, const char *key)
|
||||
{
|
||||
return kh_get(Map, map->table, key) != kh_end(map->table);
|
||||
}
|
||||
|
||||
void *map_put(Map *map, const char *key, void *value)
|
||||
{
|
||||
int ret;
|
||||
void *rv = NULL;
|
||||
khiter_t k = kh_put(Map, map->table, key, &ret);
|
||||
|
||||
if (!ret) {
|
||||
// key present, return the current value
|
||||
rv = kh_val(map->table, k);
|
||||
kh_del(Map, map->table, k);
|
||||
}
|
||||
|
||||
kh_val(map->table, k) = value;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void *map_del(Map *map, const char *key)
|
||||
{
|
||||
void *rv = NULL;
|
||||
khiter_t k;
|
||||
|
||||
if ((k = kh_get(Map, map->table, key)) != kh_end(map->table)) {
|
||||
rv = kh_val(map->table, k);
|
||||
kh_del(Map, map->table, k);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
MAP_IMPL(cstr_t)
|
||||
|
@ -1,4 +1,3 @@
|
||||
// General-purpose string->pointer associative array with a simple API
|
||||
#ifndef NVIM_MAP_H
|
||||
#define NVIM_MAP_H
|
||||
|
||||
@ -6,46 +5,28 @@
|
||||
|
||||
#include "nvim/map_defs.h"
|
||||
|
||||
/// Creates a new `Map` instance
|
||||
///
|
||||
/// @return a pointer to the new instance
|
||||
Map *map_new(void);
|
||||
#define MAP_DECLS(T) \
|
||||
KHASH_DECLARE(T##_map, T, void *) \
|
||||
\
|
||||
typedef struct { \
|
||||
khash_t(T##_map) *table; \
|
||||
} Map(T); \
|
||||
\
|
||||
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);
|
||||
|
||||
/// Frees memory for a `Map` instance
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
void map_free(Map *map);
|
||||
MAP_DECLS(cstr_t)
|
||||
|
||||
/// Gets the value corresponding to a key in a `Map` instance
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return The value if the key exists in the map, or NULL if it doesn't
|
||||
void *map_get(Map *map, const char *key);
|
||||
|
||||
/// Checks if a key exists in the map
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return true if the key exists, false otherwise
|
||||
bool map_has(Map *map, const char *key);
|
||||
|
||||
/// Set the value corresponding to a key in a `Map` instance and returns
|
||||
/// the old value.
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @param value A value
|
||||
/// @return The current value if exists or NULL otherwise
|
||||
void *map_put(Map *map, const char *key, void *value);
|
||||
|
||||
/// Deletes the value corresponding to a key in a `Map` instance and returns
|
||||
/// the old value.
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @return The current value if exists or NULL otherwise
|
||||
void *map_del(Map *map, const char *key);
|
||||
#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_foreach(map, key, value, block) \
|
||||
kh_foreach(map->table, key, value, block)
|
||||
|
@ -1,21 +1,13 @@
|
||||
#ifndef NVIM_MAP_DEFS_H
|
||||
#define NVIM_MAP_DEFS_H
|
||||
|
||||
|
||||
#include "nvim/lib/khash.h"
|
||||
|
||||
KHASH_DECLARE(Map, kh_cstr_t, void *)
|
||||
typedef const char * cstr_t;
|
||||
|
||||
typedef struct {
|
||||
khash_t(Map) *table;
|
||||
} Map;
|
||||
#define Map(T) Map_##T
|
||||
|
||||
|
||||
/// Callback for iterating through each key/value pair in a map
|
||||
///
|
||||
/// @param map The `Map` instance
|
||||
/// @param key A key string
|
||||
/// @param value A value
|
||||
typedef void (*key_value_cb)(Map *map, const char *key, void *value);
|
||||
|
||||
#endif // NVIM_MAP_DEFS_H
|
||||
|
||||
|
@ -43,7 +43,7 @@ typedef struct {
|
||||
} socket;
|
||||
} Server;
|
||||
|
||||
static Map *servers = NULL;
|
||||
static Map(cstr_t) *servers = NULL;
|
||||
|
||||
static void connection_cb(uv_stream_t *server, int status);
|
||||
static void free_client(uv_handle_t *handle);
|
||||
@ -51,7 +51,7 @@ static void free_server(uv_handle_t *handle);
|
||||
|
||||
void server_init()
|
||||
{
|
||||
servers = map_new();
|
||||
servers = map_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, ChannelProtocol prot)
|
||||
strncpy(addr, endpoint, sizeof(addr));
|
||||
|
||||
// Check if the server already exists
|
||||
if (map_has(servers, addr)) {
|
||||
if (map_has(cstr_t)(servers, addr)) {
|
||||
EMSG2("Already listening on %s", addr);
|
||||
return;
|
||||
}
|
||||
@ -174,7 +174,7 @@ void server_start(char *endpoint, ChannelProtocol prot)
|
||||
server->type = server_type;
|
||||
|
||||
// Add the server to the hash table
|
||||
map_put(servers, addr, server);
|
||||
map_put(cstr_t)(servers, addr, server);
|
||||
}
|
||||
|
||||
void server_stop(char *endpoint)
|
||||
@ -185,7 +185,7 @@ void server_stop(char *endpoint)
|
||||
// Trim to `ADDRESS_MAX_SIZE`
|
||||
strncpy(addr, endpoint, sizeof(addr));
|
||||
|
||||
if ((server = map_get(servers, addr)) == NULL) {
|
||||
if ((server = map_get(cstr_t)(servers, addr)) == NULL) {
|
||||
EMSG2("Not listening on %s", addr);
|
||||
return;
|
||||
}
|
||||
@ -196,7 +196,7 @@ void server_stop(char *endpoint)
|
||||
uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server);
|
||||
}
|
||||
|
||||
map_del(servers, addr);
|
||||
map_del(cstr_t)(servers, addr);
|
||||
}
|
||||
|
||||
static void connection_cb(uv_stream_t *server, int status)
|
||||
|
Loading…
Reference in New Issue
Block a user