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:
Thiago de Arruda
2014-05-30 18:41:57 -03:00
parent a581173e71
commit 82e3e7047f
7 changed files with 129 additions and 118 deletions

View File

@@ -4,26 +4,26 @@
#include "nvim/map.h" #include "nvim/map.h"
#include "nvim/api/private/handle.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) \ #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) \ 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) \ void handle_register_##name(type *name) \
{ \ { \
assert(!name->handle); \ assert(!name->handle); \
name->handle = next_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) \ 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; static uint64_t next_handle = 1;

View File

@@ -21,7 +21,7 @@
/// @param obj The source object /// @param obj The source object
/// @param lookup Lookup table containing pointers to all processed objects /// @param lookup Lookup table containing pointers to all processed objects
/// @return The converted value /// @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); 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; Object rv;
// We use a lookup table to break out of cyclic references // 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); rv = vim_to_object_rec(obj, lookup);
// Free the table // Free the table
map_free(ptr_t)(lookup); pmap_free(ptr_t)(lookup);
return rv; return rv;
} }
@@ -422,18 +422,18 @@ static bool object_to_vim(Object obj, typval_T *tv, Error *err)
return true; 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}; Object rv = {.type = kObjectTypeNil};
if (obj->v_type == VAR_LIST || obj->v_type == VAR_DICT) { if (obj->v_type == VAR_LIST || obj->v_type == VAR_DICT) {
// Container object, add it to the lookup table // 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 // It's already present, meaning we alredy processed it so just return
// nil instead. // nil instead.
return rv; return rv;
} }
map_put(ptr_t)(lookup, obj, NULL); pmap_put(ptr_t)(lookup, obj, NULL);
} }
switch (obj->v_type) { switch (obj->v_type) {

View File

@@ -23,66 +23,70 @@
#define ptr_t_eq(a, b) uint32_t_eq((uint32_t)a, (uint32_t)b) #define ptr_t_eq(a, b) uint32_t_eq((uint32_t)a, (uint32_t)b)
#endif #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) \ #define MAP_IMPL(T, U, ...) \
__KHASH_IMPL(T##_map,, T, void *, 1, T##_hash, T##_eq) \ INITIALIZER_DECLARE(T, U, __VA_ARGS__); \
\ __KHASH_IMPL(T##_##U##_map,, T, U, 1, T##_hash, T##_eq) \
Map(T) *map_##T##_new() \ \
{ \ Map(T, U) *map_##T##_##U##_new() \
Map(T) *rv = xmalloc(sizeof(Map(T))); \ { \
rv->table = kh_init(T##_map); \ Map(T, U) *rv = xmalloc(sizeof(Map(T, U))); \
return rv; \ rv->table = kh_init(T##_##U##_map); \
} \ return rv; \
\ } \
void map_##T##_free(Map(T) *map) \ \
{ \ void map_##T##_##U##_free(Map(T, U) *map) \
kh_destroy(T##_map, map->table); \ { \
free(map); \ kh_destroy(T##_##U##_map, map->table); \
} \ free(map); \
\ } \
void *map_##T##_get(Map(T) *map, T key) \ \
{ \ U map_##T##_##U##_get(Map(T, U) *map, T key) \
khiter_t k; \ { \
\ khiter_t k; \
if ((k = kh_get(T##_map, map->table, key)) == kh_end(map->table)) { \ \
return NULL; \ if ((k = kh_get(T##_##U##_map, map->table, key)) == kh_end(map->table)) { \
} \ return INITIALIZER(T, U); \
\ } \
return kh_val(map->table, k); \ \
} \ return kh_val(map->table, k); \
\ } \
bool map_##T##_has(Map(T) *map, T key) \ \
{ \ bool map_##T##_##U##_has(Map(T, U) *map, T key) \
return kh_get(T##_map, map->table, key) != kh_end(map->table); \ { \
} \ return kh_get(T##_##U##_map, map->table, key) != kh_end(map->table); \
\ } \
void *map_##T##_put(Map(T) *map, T key, void *value) \ \
{ \ U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \
int ret; \ { \
void *rv = NULL; \ int ret; \
khiter_t k = kh_put(T##_map, map->table, key, &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); \ if (!ret) { \
} \ rv = kh_val(map->table, k); \
\ } \
kh_val(map->table, k) = value; \ \
return rv; \ kh_val(map->table, k) = value; \
} \ return rv; \
\ } \
void *map_##T##_del(Map(T) *map, T key) \ \
{ \ U map_##T##_##U##_del(Map(T, U) *map, T key) \
void *rv = NULL; \ { \
khiter_t k; \ U rv = INITIALIZER(T, U); \
\ khiter_t k; \
if ((k = kh_get(T##_map, map->table, key)) != kh_end(map->table)) { \ \
rv = kh_val(map->table, k); \ if ((k = kh_get(T##_##U##_map, map->table, key)) != kh_end(map->table)) { \
kh_del(T##_map, map->table, k); \ rv = kh_val(map->table, k); \
} \ kh_del(T##_##U##_map, map->table, k); \
\ } \
return rv; \ \
return rv; \
} }
MAP_IMPL(cstr_t) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(ptr_t) MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t) MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)

View File

@@ -5,30 +5,37 @@
#include "nvim/map_defs.h" #include "nvim/map_defs.h"
#define MAP_DECLS(T) \ #define MAP_DECLS(T, U) \
KHASH_DECLARE(T##_map, T, void *) \ KHASH_DECLARE(T##_##U##_map, T, U) \
\ \
typedef struct { \ typedef struct { \
khash_t(T##_map) *table; \ khash_t(T##_##U##_map) *table; \
} Map(T); \ } Map(T, U); \
\ \
Map(T) *map_##T##_new(void); \ Map(T, U) *map_##T##_##U##_new(void); \
void map_##T##_free(Map(T) *map); \ void map_##T##_##U##_free(Map(T, U) *map); \
void *map_##T##_get(Map(T) *map, T key); \ U map_##T##_##U##_get(Map(T, U) *map, T key); \
bool map_##T##_has(Map(T) *map, T key); \ bool map_##T##_##U##_has(Map(T, U) *map, T key); \
void* map_##T##_put(Map(T) *map, T key, void *value); \ U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \
void* map_##T##_del(Map(T) *map, T key); U map_##T##_##U##_del(Map(T, U) *map, T key);
MAP_DECLS(cstr_t) MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(ptr_t) MAP_DECLS(ptr_t, ptr_t)
MAP_DECLS(uint64_t) MAP_DECLS(uint64_t, ptr_t)
#define map_new(T) map_##T##_new #define map_new(T, U) map_##T##_##U##_new
#define map_free(T) map_##T##_free #define map_free(T, U) map_##T##_##U##_free
#define map_get(T) map_##T##_get #define map_get(T, U) map_##T##_##U##_get
#define map_has(T) map_##T##_has #define map_has(T, U) map_##T##_##U##_has
#define map_put(T) map_##T##_put #define map_put(T, U) map_##T##_##U##_put
#define map_del(T) map_##T##_del #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) \ #define map_foreach(map, key, value, block) \
kh_foreach(map->table, key, value, block) kh_foreach(map->table, key, value, block)

View File

@@ -7,8 +7,8 @@
typedef const char * cstr_t; typedef const char * cstr_t;
typedef void * ptr_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 #endif // NVIM_MAP_DEFS_H

View File

@@ -19,7 +19,7 @@
typedef struct { typedef struct {
uint64_t id; uint64_t id;
Map(cstr_t) *subscribed_events; PMap(cstr_t) *subscribed_events;
bool is_job; bool is_job;
msgpack_unpacker *unpacker; msgpack_unpacker *unpacker;
msgpack_sbuffer *sbuffer; msgpack_sbuffer *sbuffer;
@@ -34,8 +34,8 @@ typedef struct {
} Channel; } Channel;
static uint64_t next_id = 1; static uint64_t next_id = 1;
static Map(uint64_t) *channels = NULL; static PMap(uint64_t) *channels = NULL;
static Map(cstr_t) *event_strings = NULL; static PMap(cstr_t) *event_strings = NULL;
static msgpack_sbuffer msgpack_event_buffer; static msgpack_sbuffer msgpack_event_buffer;
static void job_out(RStream *rstream, void *data, bool eof); static void job_out(RStream *rstream, void *data, bool eof);
@@ -51,8 +51,8 @@ static Channel *register_channel(void);
void channel_init() void channel_init()
{ {
channels = map_new(uint64_t)(); channels = pmap_new(uint64_t)();
event_strings = map_new(cstr_t)(); event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&msgpack_event_buffer); 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; Channel *channel = NULL;
if (id > 0) { if (id > 0) {
if (!(channel = map_get(uint64_t)(channels, id))) { if (!(channel = pmap_get(uint64_t)(channels, id))) {
return false; return false;
} }
send_event(channel, type, data); send_event(channel, type, data);
@@ -111,25 +111,25 @@ void channel_subscribe(uint64_t id, char *event)
{ {
Channel *channel; Channel *channel;
if (!(channel = map_get(uint64_t)(channels, id))) { if (!(channel = pmap_get(uint64_t)(channels, id))) {
return; return;
} }
char *event_string = map_get(cstr_t)(event_strings, event); char *event_string = pmap_get(cstr_t)(event_strings, event);
if (!event_string) { if (!event_string) {
event_string = xstrdup(event); 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) void channel_unsubscribe(uint64_t id, char *event)
{ {
Channel *channel; Channel *channel;
if (!(channel = map_get(uint64_t)(channels, id))) { if (!(channel = pmap_get(uint64_t)(channels, id))) {
return; return;
} }
@@ -195,7 +195,7 @@ static void broadcast_event(char *type, typval_T *data)
Channel *channel; Channel *channel;
map_foreach_value(channels, 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); kv_push(Channel *, subscribed, channel);
} }
}); });
@@ -216,23 +216,23 @@ end:
static void unsubscribe(Channel *channel, char *event) static void unsubscribe(Channel *channel, char *event)
{ {
char *event_string = map_get(cstr_t)(event_strings, event); char *event_string = pmap_get(cstr_t)(event_strings, event);
map_del(cstr_t)(channel->subscribed_events, event_string); pmap_del(cstr_t)(channel->subscribed_events, event_string);
map_foreach_value(channels, channel, { 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; return;
} }
}); });
// Since the string is no longer used by other channels, release it's memory // 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); free(event_string);
} }
static void close_channel(Channel *channel) 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_sbuffer_free(channel->sbuffer);
msgpack_unpacker_free(channel->unpacker); msgpack_unpacker_free(channel->unpacker);
@@ -250,7 +250,7 @@ static void close_channel(Channel *channel)
unsubscribe(channel, event_string); unsubscribe(channel, event_string);
}); });
map_free(cstr_t)(channel->subscribed_events); pmap_free(cstr_t)(channel->subscribed_events);
free(channel); free(channel);
} }
@@ -282,7 +282,7 @@ static Channel *register_channel()
rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE); rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
rv->sbuffer = msgpack_sbuffer_new(); rv->sbuffer = msgpack_sbuffer_new();
rv->id = next_id++; rv->id = next_id++;
rv->subscribed_events = map_new(cstr_t)(); rv->subscribed_events = pmap_new(cstr_t)();
map_put(uint64_t)(channels, rv->id, rv); pmap_put(uint64_t)(channels, rv->id, rv);
return rv; return rv;
} }

View File

@@ -40,7 +40,7 @@ typedef struct {
} socket; } socket;
} Server; } 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 connection_cb(uv_stream_t *server, int status);
static void free_client(uv_handle_t *handle); static void free_client(uv_handle_t *handle);
@@ -48,7 +48,7 @@ static void free_server(uv_handle_t *handle);
void server_init() void server_init()
{ {
servers = map_new(cstr_t)(); servers = pmap_new(cstr_t)();
if (!os_getenv("NEOVIM_LISTEN_ADDRESS")) { if (!os_getenv("NEOVIM_LISTEN_ADDRESS")) {
char *listen_address = (char *)vim_tempname('s'); char *listen_address = (char *)vim_tempname('s');
@@ -88,7 +88,7 @@ void server_start(char *endpoint)
} }
// Check if the server already exists // 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); EMSG2("Already listening on %s", addr);
return; return;
} }
@@ -172,7 +172,7 @@ void server_start(char *endpoint)
server->type = server_type; server->type = server_type;
// Add the server to the hash table // 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) void server_stop(char *endpoint)
@@ -183,7 +183,7 @@ void server_stop(char *endpoint)
// Trim to `ADDRESS_MAX_SIZE` // Trim to `ADDRESS_MAX_SIZE`
xstrlcpy(addr, endpoint, sizeof(addr)); 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); EMSG2("Not listening on %s", addr);
return; return;
} }
@@ -194,7 +194,7 @@ void server_stop(char *endpoint)
uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server); 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) static void connection_cb(uv_stream_t *server, int status)