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/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;

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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)