From b87b1a3325cc134bacd7dbec4d873053aa1c4d93 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 19 May 2014 10:51:47 -0300 Subject: Improve map module: Add to clint and CONV_SRCS --- src/nvim/CMakeLists.txt | 1 + src/nvim/map.h | 2 +- src/nvim/map_defs.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 221019ebe4..d9ec65af86 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -48,6 +48,7 @@ set(CONV_SRCS arabic.c garray.c memory.c + map.c os/env.c os/event.c os/job.c diff --git a/src/nvim/map.h b/src/nvim/map.h index 7b4c03ffa0..39536a0c10 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -53,5 +53,5 @@ void *map_del(Map *map, const char *key); /// @param cb A function that will be called for each key/value void map_foreach(Map *map, key_value_cb cb); -#endif /* NVIM_MAP_H */ +#endif // NVIM_MAP_H diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h index e56a1461d4..d8203aeba6 100644 --- a/src/nvim/map_defs.h +++ b/src/nvim/map_defs.h @@ -10,5 +10,5 @@ typedef struct map Map; /// @param value A value typedef void (*key_value_cb)(Map *map, const char *key, void *value); -#endif /* NVIM_MAP_DEFS_H */ +#endif // NVIM_MAP_DEFS_H -- cgit From eb7513bbd2bd9189502159c4146bb6999b8da32b Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 19 May 2014 10:51:56 -0300 Subject: Improve map module: Fix implementation of map_has --- src/nvim/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/map.c b/src/nvim/map.c index 40868e5b92..332de6d3d3 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -45,7 +45,7 @@ void *map_get(Map *map, const char *key) bool map_has(Map *map, const char *key) { - return map_get(map, key) != NULL; + return kh_get(Map, map->table, key) != kh_end(map->table); } void *map_put(Map *map, const char *key, void *value) -- cgit From 974eade1a6445222812fc03f60896def74b7dd06 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 19 May 2014 10:52:04 -0300 Subject: Improve map module: Change scopes - Move `Map` structure definition to `map_defs.h` - Use `KHASH_DECLARE` on map_defs.h to declare khash function prototypes. - Redefine `map_foreach` into a macro - Refactor server.c module to use the new `map_foreach` macro. --- src/nvim/map.c | 29 +++++------------------------ src/nvim/map.h | 10 +++++----- src/nvim/map_defs.h | 9 ++++++++- src/nvim/os/server.c | 22 +++++++++------------- 4 files changed, 27 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/nvim/map.c b/src/nvim/map.c index 332de6d3d3..91a90b4493 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -8,15 +8,7 @@ #include "nvim/lib/khash.h" -typedef struct { - void *ptr; -} Value; - -KHASH_MAP_INIT_STR(Map, Value) - -struct map { - khash_t(Map) *table; -}; +__KHASH_IMPL(Map,, kh_cstr_t, void *, 1, kh_str_hash_func, kh_str_hash_equal) Map *map_new() { @@ -40,7 +32,7 @@ void *map_get(Map *map, const char *key) return NULL; } - return kh_val(map->table, k).ptr; + return kh_val(map->table, k); } bool map_has(Map *map, const char *key) @@ -53,15 +45,14 @@ 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); - Value val = {.ptr = value}; if (!ret) { // key present, return the current value - rv = kh_val(map->table, k).ptr; + rv = kh_val(map->table, k); kh_del(Map, map->table, k); } - kh_val(map->table, k) = val; + kh_val(map->table, k) = value; return rv; } @@ -72,20 +63,10 @@ void *map_del(Map *map, const char *key) khiter_t k; if ((k = kh_get(Map, map->table, key)) != kh_end(map->table)) { - rv = kh_val(map->table, k).ptr; + rv = kh_val(map->table, k); kh_del(Map, map->table, k); } return rv; } -void map_foreach(Map *map, key_value_cb cb) -{ - const char *key; - Value value; - - kh_foreach(map->table, key, value, { - cb(map, (const char *)key, value.ptr); - }); -} - diff --git a/src/nvim/map.h b/src/nvim/map.h index 39536a0c10..3e9ab389bd 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -47,11 +47,11 @@ void *map_put(Map *map, const char *key, void *value); /// @return The current value if exists or NULL otherwise void *map_del(Map *map, const char *key); -/// Iterates through each key/value pair in the map -/// -/// @param map The `Map` instance -/// @param cb A function that will be called for each key/value -void map_foreach(Map *map, key_value_cb cb); +#define map_foreach(map, key, value, block) \ + kh_foreach(map->table, key, value, block) + +#define map_foreach_value(map, value, block) \ + kh_foreach_value(map->table, value, block) #endif // NVIM_MAP_H diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h index d8203aeba6..e1355624dc 100644 --- a/src/nvim/map_defs.h +++ b/src/nvim/map_defs.h @@ -1,7 +1,14 @@ #ifndef NVIM_MAP_DEFS_H #define NVIM_MAP_DEFS_H -typedef struct map Map; +#include "nvim/lib/khash.h" + +KHASH_DECLARE(Map, kh_cstr_t, void *) + +typedef struct { + khash_t(Map) *table; +} Map; + /// Callback for iterating through each key/value pair in a map /// diff --git a/src/nvim/os/server.c b/src/nvim/os/server.c index e9a11809ae..9cf0f53c70 100644 --- a/src/nvim/os/server.c +++ b/src/nvim/os/server.c @@ -45,7 +45,6 @@ typedef struct { static Map *servers = NULL; -static void close_server(Map *map, const char *endpoint, void *server); static void connection_cb(uv_stream_t *server, int status); static void free_client(uv_handle_t *handle); static void free_server(uv_handle_t *handle); @@ -70,7 +69,15 @@ void server_teardown() return; } - map_foreach(servers, close_server); + Server *server; + + map_foreach_value(servers, server, { + if (server->type == kServerTypeTcp) { + uv_close((uv_handle_t *)&server->socket.tcp.handle, free_server); + } else { + uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server); + } + }); } void server_start(char *endpoint, ChannelProtocol prot) @@ -221,17 +228,6 @@ static void connection_cb(uv_stream_t *server, int status) channel_from_stream(client, srv->protocol); } -static void close_server(Map *map, const char *endpoint, void *srv) -{ - Server *server = srv; - - if (server->type == kServerTypeTcp) { - uv_close((uv_handle_t *)&server->socket.tcp.handle, free_server); - } else { - uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server); - } -} - static void free_client(uv_handle_t *handle) { free(handle); -- cgit From 37dfe2d48f16e4227dd713ebeb03257490f78e67 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 19 May 2014 10:52:10 -0300 Subject: 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. --- src/nvim/map.c | 128 +++++++++++++++++++++++++++------------------------ src/nvim/map.h | 63 +++++++++---------------- src/nvim/map_defs.h | 14 ++---- src/nvim/os/server.c | 12 ++--- 4 files changed, 99 insertions(+), 118 deletions(-) (limited to 'src') diff --git a/src/nvim/map.c b/src/nvim/map.c index 91a90b4493..d8260c9a7d 100644 --- a/src/nvim/map.c +++ b/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) - -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 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 + +#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) diff --git a/src/nvim/map.h b/src/nvim/map.h index 3e9ab389bd..e85b4d3a5e 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -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); - -/// Frees memory for a `Map` instance -/// -/// @param map The `Map` instance -void map_free(Map *map); - -/// 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_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); + +MAP_DECLS(cstr_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_foreach(map, key, value, block) \ kh_foreach(map->table, key, value, block) diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h index e1355624dc..e6bbe42fb8 100644 --- a/src/nvim/map_defs.h +++ b/src/nvim/map_defs.h @@ -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 *) +#include "nvim/lib/khash.h" -typedef struct { - khash_t(Map) *table; -} Map; +typedef const char * cstr_t; +#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 diff --git a/src/nvim/os/server.c b/src/nvim/os/server.c index 9cf0f53c70..9b5410c323 100644 --- a/src/nvim/os/server.c +++ b/src/nvim/os/server.c @@ -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) -- cgit From 25595d97d5c1038dd3789e85194a81ee7e4fdbd2 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 19 May 2014 10:52:15 -0300 Subject: Improve map module: Refactor vim_to_object_rec Now the map.c module is used to implement the 'lookup set' for that function --- src/nvim/api/helpers.c | 26 ++++++++------------------ src/nvim/map.c | 13 ++++++++++--- src/nvim/map.h | 5 +++-- src/nvim/map_defs.h | 1 + 4 files changed, 22 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nvim/api/helpers.c b/src/nvim/api/helpers.c index 3256abeeee..a193c8721e 100644 --- a/src/nvim/api/helpers.c +++ b/src/nvim/api/helpers.c @@ -9,27 +9,18 @@ #include "nvim/window.h" #include "nvim/memory.h" #include "nvim/eval.h" +#include "nvim/map_defs.h" +#include "nvim/map.h" #include "nvim/option.h" #include "nvim/option_defs.h" -#include "nvim/lib/khash.h" - - -#if defined(ARCH_64) -#define ptr_hash_func(key) kh_int64_hash_func(key) -#elif defined(ARCH_32) -#define ptr_hash_func(key) kh_int_hash_func(key) -#endif - -KHASH_INIT(Lookup, uintptr_t, char, 0, ptr_hash_func, kh_int_hash_equal) - /// Recursion helper for the `vim_to_object`. This uses a pointer table /// to avoid infinite recursion due to cyclic references /// /// @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, khash_t(Lookup) *lookup); +static Object vim_to_object_rec(typval_T *obj, Map(ptr_t) *lookup); static bool object_to_vim(Object obj, typval_T *tv, Error *err); @@ -285,10 +276,10 @@ Object vim_to_object(typval_T *obj) { Object rv; // We use a lookup table to break out of cyclic references - khash_t(Lookup) *lookup = kh_init(Lookup); + Map(ptr_t) *lookup = map_new(ptr_t)(); rv = vim_to_object_rec(obj, lookup); // Free the table - kh_destroy(Lookup, lookup); + map_free(ptr_t)(lookup); return rv; } @@ -443,19 +434,18 @@ static bool object_to_vim(Object obj, typval_T *tv, Error *err) return true; } -static Object vim_to_object_rec(typval_T *obj, khash_t(Lookup) *lookup) +static Object vim_to_object_rec(typval_T *obj, Map(ptr_t) *lookup) { Object rv = {.type = kObjectTypeNil}; if (obj->v_type == VAR_LIST || obj->v_type == VAR_DICT) { - int ret; // Container object, add it to the lookup table - kh_put(Lookup, lookup, (uintptr_t)obj, &ret); - if (!ret) { + if (map_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); } switch (obj->v_type) { diff --git a/src/nvim/map.c b/src/nvim/map.c index d8260c9a7d..28fd0af61c 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -15,6 +15,15 @@ #define uint32_t_hash kh_int_hash_func #define uint32_t_eq kh_int_hash_equal +#if defined(ARCH_64) +#define ptr_t_hash(key) uint64_t_hash((uint64_t)key) +#define ptr_t_eq(a, b) uint64_t_eq((uint64_t)a, (uint64_t)b) +#elif defined(ARCH_32) +#define ptr_t_hash(key) uint32_t_hash((uint32_t)key) +#define ptr_t_eq(a, b) uint32_t_eq((uint32_t)a, (uint32_t)b) +#endif + + #define MAP_IMPL(T) \ __KHASH_IMPL(T##_map,, T, void *, 1, T##_hash, T##_eq) \ \ @@ -27,7 +36,6 @@ \ void map_##T##_free(Map(T) *map) \ { \ - kh_clear(T##_map, map->table); \ kh_destroy(T##_map, map->table); \ free(map); \ } \ @@ -56,11 +64,9 @@ \ if (!ret) { \ rv = kh_val(map->table, k); \ - kh_del(T##_map, map->table, k); \ } \ \ kh_val(map->table, k) = value; \ - \ return rv; \ } \ \ @@ -78,3 +84,4 @@ } MAP_IMPL(cstr_t) +MAP_IMPL(ptr_t) diff --git a/src/nvim/map.h b/src/nvim/map.h index e85b4d3a5e..ae47561deb 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -16,10 +16,11 @@ 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); + void* map_##T##_put(Map(T) *map, T key, void *value); \ + void* map_##T##_del(Map(T) *map, T key); MAP_DECLS(cstr_t) +MAP_DECLS(ptr_t) #define map_new(T) map_##T##_new #define map_free(T) map_##T##_free diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h index e6bbe42fb8..d9f35dfc67 100644 --- a/src/nvim/map_defs.h +++ b/src/nvim/map_defs.h @@ -5,6 +5,7 @@ #include "nvim/lib/khash.h" typedef const char * cstr_t; +typedef void * ptr_t; #define Map(T) Map_##T -- cgit