From b281925ebae0a94366af4cf9273e58bd19a534dc Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 8 Jul 2020 17:12:40 -0400 Subject: [PATCH] Significantly simplify dictionaries Significantly simplify dictionaries so that dictionary keys are always uint32_t; this number can be an arbitrary integer, be it a file descriptor, for instance, or a hashed value --- include/patty/dict.h | 32 +++++------------ src/dict.c | 63 ++++++++++++-------------------- src/if.c | 23 ++++++------ src/route.c | 16 ++++----- src/server.c | 86 +++++++++++++++++++------------------------- 5 files changed, 84 insertions(+), 136 deletions(-) diff --git a/include/patty/dict.h b/include/patty/dict.h index 003fd7f..8d6fb76 100644 --- a/include/patty/dict.h +++ b/include/patty/dict.h @@ -4,17 +4,14 @@ #include #include -#include - #define PATTY_DICT_BUCKET_SIZE 16 typedef struct _patty_dict_slot { - uint32_t hash; - void * key; - size_t keysz; - void * value; + uint32_t key; + void *value; + int set; - struct _patty_dict_slot * next; + struct _patty_dict_slot *next; } patty_dict_slot; typedef struct _patty_dict_bucket { @@ -27,10 +24,9 @@ typedef struct _patty_dict { patty_dict *patty_dict_new(); -patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t hash); +patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t key); -typedef int (*patty_dict_callback)(void *key, - size_t keysz, +typedef int (*patty_dict_callback)(uint32_t key, void *value, void *ctx); @@ -38,21 +34,11 @@ int patty_dict_each(patty_dict *dict, patty_dict_callback callback, void *ctx); -void *patty_dict_get_with_hash(patty_dict *dict, uint32_t hash); +void *patty_dict_get(patty_dict *dict, uint32_t key); -void *patty_dict_get(patty_dict *dict, void *key, size_t keysz); +void *patty_dict_set(patty_dict *dict, uint32_t key, void *value); -void *patty_dict_set_with_hash(patty_dict *dict, - void *key, - size_t keysz, - void *value, - uint32_t hash); - -void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value); - -int patty_dict_delete_with_hash(patty_dict *dict, uint32_t hash); - -int patty_dict_delete(patty_dict *dict, void *key, size_t keysz); +int patty_dict_delete(patty_dict *dict, uint32_t key); void patty_dict_destroy(patty_dict *dict); diff --git a/src/dict.c b/src/dict.c index 9ade654..a33017f 100644 --- a/src/dict.c +++ b/src/dict.c @@ -2,7 +2,6 @@ #include #include -#include patty_dict *patty_dict_new() { patty_dict *dict; @@ -19,24 +18,24 @@ error_malloc_dict: return NULL; } -patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t hash) { +patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t key) { patty_dict_bucket *bucket = &dict->bucket; int collisions; for (collisions = 0; collisions < 7; collisions++) { uint32_t mask = 0x0f << (4 * collisions); - uint8_t index = (hash & mask) >> (4 * collisions); + uint8_t index = (key & mask) >> (4 * collisions); patty_dict_slot *slot = &bucket->slots[index]; - if (slot->hash == 0x00000000) { + if (!slot->set) { /* * In this case, we have determined that there is no value in the - * dict for the given hash. + * dict for the given key. */ return NULL; - } else if (slot->hash == hash) { + } else if (slot->key == key) { /* * We have found the desired slot, so return that. */ @@ -59,7 +58,10 @@ patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t hash) { return NULL; } -static int bucket_each_slot(int level, patty_dict_bucket *bucket, patty_dict_callback callback, void *ctx) { +static int bucket_each_slot(int level, + patty_dict_bucket *bucket, + patty_dict_callback callback, + void *ctx) { int i; if (level > 7) { @@ -69,8 +71,8 @@ static int bucket_each_slot(int level, patty_dict_bucket *bucket, patty_dict_cal for (i=0; islots[i]; - if (slot->key != NULL && slot->keysz > 0) { - if (callback(slot->key, slot->keysz, slot->value, ctx) < 0) { + if (slot->set) { + if (callback(slot->key, slot->value, ctx) < 0) { goto error_callback; } } @@ -96,46 +98,39 @@ int patty_dict_each(patty_dict *dict, patty_dict_callback callback, void *ctx) { return bucket_each_slot(0, &dict->bucket, callback, ctx); } -void *patty_dict_get_with_hash(patty_dict *dict, uint32_t hash) { +void *patty_dict_get(patty_dict *dict, uint32_t key) { patty_dict_slot *slot; - if ((slot = patty_dict_slot_find(dict, hash)) == NULL) { + if ((slot = patty_dict_slot_find(dict, key)) == NULL) { return NULL; } return slot->value; } -void *patty_dict_get(patty_dict *dict, void *key, size_t keysz) { - return patty_dict_get_with_hash(dict, patty_hash(key, keysz)); -} - -void *patty_dict_set_with_hash(patty_dict *dict, - void *key, - size_t keysz, - void *value, - uint32_t hash) { +void *patty_dict_set(patty_dict *dict, + uint32_t key, + void *value) { patty_dict_bucket *bucket = &dict->bucket; int collisions; for (collisions = 0; collisions < 7; collisions++) { uint32_t mask = 0x0f << (4 * collisions); - uint8_t index = (hash & mask) >> (4 * collisions); + uint8_t index = (key & mask) >> (4 * collisions); patty_dict_slot *slot = &bucket->slots[index]; - if (slot->hash == 0x00000000 && slot->key == NULL) { + if (!slot->set) { /* - * We have found an empty hash slot, so let's store the value. + * We have found an empty slot, so let's store the value. */ - slot->hash = hash; slot->key = key; - slot->keysz = keysz; slot->value = value; + slot->set = 1; return value; - } else if (slot->hash == hash) { + } else if (slot->key == key) { /* * Otherwise, we've found an existing slot, so let's update that * and bail. @@ -168,18 +163,10 @@ error_malloc_bucket: return NULL; } -void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value) { - return patty_dict_set_with_hash(dict, - key, - keysz, - value, - patty_hash(key, keysz)); -} - -int patty_dict_delete_with_hash(patty_dict *dict, uint32_t hash) { +int patty_dict_delete(patty_dict *dict, uint32_t key) { patty_dict_slot *slot; - if ((slot = patty_dict_slot_find(dict, hash)) == NULL) { + if ((slot = patty_dict_slot_find(dict, key)) == NULL) { goto error_dict_slot_find; } @@ -191,10 +178,6 @@ error_dict_slot_find: return -1; } -int patty_dict_delete(patty_dict *dict, void *key, size_t keysz) { - return patty_dict_delete_with_hash(dict, patty_hash(key, keysz)); -} - void patty_dict_destroy(patty_dict *dict) { free(dict); } diff --git a/src/if.c b/src/if.c index c747c85..c52fa00 100644 --- a/src/if.c +++ b/src/if.c @@ -273,33 +273,31 @@ error_ntop: int patty_ax25_if_promisc_add(patty_ax25_if *iface, int fd) { - if (patty_dict_get_with_hash(iface->promisc_fds, (uint32_t)fd)) { + if (patty_dict_get(iface->promisc_fds, (uint32_t)fd)) { errno = EEXIST; goto error_exists; } - if (patty_dict_set_with_hash(iface->promisc_fds, - NULL + fd, - sizeof(fd), - NULL + fd, - (uint32_t)fd) == NULL) { + if (patty_dict_set(iface->promisc_fds, + (uint32_t)fd, + NULL + fd) == NULL) { errno = ENOMEM; - goto error_dict_set_with_hash; + goto error_dict_set; } return 0; -error_dict_set_with_hash: +error_dict_set: error_exists: return -1; } int patty_ax25_if_promisc_delete(patty_ax25_if *iface, int fd) { - if (patty_dict_delete_with_hash(iface->promisc_fds, - (uint32_t)fd) < 0) { + if (patty_dict_delete(iface->promisc_fds, + (uint32_t)fd) < 0) { errno = ENOENT; goto error_notfound; @@ -317,11 +315,10 @@ struct promisc_frame { patty_ax25_if *iface; }; -static int handle_promisc_frame(void *key, - size_t keysz, +static int handle_promisc_frame(uint32_t key, void *value, void *ctx) { - int fd = (int)(value - NULL); + int fd = (int)key; struct promisc_frame *frame = ctx; if (write(fd, frame->buf, frame->len) < 0) { diff --git a/src/route.c b/src/route.c index 36e1824..ca09d02 100644 --- a/src/route.c +++ b/src/route.c @@ -71,7 +71,7 @@ patty_ax25_route *patty_ax25_route_table_find(patty_ax25_route_table *table, patty_ax25_addr_hash(&hash, dest); patty_hash_end(&hash); - route = patty_dict_get_with_hash(table, hash); + route = patty_dict_get(table, hash); if (route) { return route; @@ -91,7 +91,7 @@ patty_ax25_route *patty_ax25_route_table_default(patty_ax25_route_table *table) patty_ax25_addr_hash(&hash, &empty); patty_hash_end(&hash); - return patty_dict_get_with_hash(table, hash); + return patty_dict_get(table, hash); } int patty_ax25_route_table_add(patty_ax25_route_table *table, @@ -108,17 +108,13 @@ int patty_ax25_route_table_add(patty_ax25_route_table *table, goto error_exists; } - if (patty_dict_set_with_hash(table, - &route->dest, - sizeof(route->dest), - route, - hash) == NULL) { - goto error_dict_set_with_hash; + if (patty_dict_set(table, hash, route) == NULL) { + goto error_dict_set; } return 0; -error_dict_set_with_hash: +error_dict_set: error_exists: return -1; } @@ -131,5 +127,5 @@ int patty_ax25_route_table_delete(patty_ax25_route_table *route, patty_ax25_addr_hash(&hash, dest); patty_hash_end(&hash); - return patty_dict_delete_with_hash(route, hash); + return patty_dict_delete(route, hash); } diff --git a/src/server.c b/src/server.c index f7017fc..520afac 100644 --- a/src/server.c +++ b/src/server.c @@ -10,6 +10,7 @@ #include #include +#include typedef int (*patty_ax25_server_call)(patty_ax25_server *, int); @@ -154,7 +155,7 @@ static inline void clear_fd(patty_ax25_server *server, int fd) { static patty_ax25_sock *sock_by_fd(patty_dict *dict, int fd) { - return patty_dict_get_with_hash(dict, (uint32_t)fd); + return patty_dict_get(dict, (uint32_t)fd); } static patty_ax25_sock *sock_by_addr(patty_dict *dict, @@ -165,7 +166,7 @@ static patty_ax25_sock *sock_by_addr(patty_dict *dict, patty_ax25_addr_hash(&hash, addr); patty_hash_end(&hash); - return patty_dict_get_with_hash(dict, hash); + return patty_dict_get(dict, hash); } static patty_ax25_sock *sock_by_addrpair(patty_dict *dict, @@ -178,15 +179,13 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict, patty_ax25_addr_hash(&hash, remote); patty_hash_end(&hash); - return patty_dict_get_with_hash(dict, hash); + return patty_dict_get(dict, hash); } static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) { - if (patty_dict_set_with_hash(dict, - NULL + sock->fd, - sizeof(sock->fd), - sock, - (uint32_t)sock->fd) == NULL) { + if (patty_dict_set(dict, + (uint32_t)sock->fd, + sock) == NULL) { goto error_dict_set; } @@ -200,37 +199,35 @@ static inline int client_by_sock(patty_ax25_server *server, patty_ax25_sock *sock) { void *value; - if ((value = patty_dict_get_with_hash(server->clients_by_sock, - (uint32_t)sock->fd)) == NULL) { - goto error_dict_get_with_hash; + if ((value = patty_dict_get(server->clients_by_sock, + (uint32_t)sock->fd)) == NULL) { + goto error_dict_get; } return (int)((int64_t)value); -error_dict_get_with_hash: +error_dict_get: return -1; } static inline int client_save_by_sock(patty_ax25_server *server, int client, patty_ax25_sock *sock) { - if (patty_dict_set_with_hash(server->clients_by_sock, - NULL + sock->fd, - sizeof(sock->fd), - NULL + client, - (uint32_t)sock->fd) == NULL) { - goto error_dict_set_with_hash; + if (patty_dict_set(server->clients_by_sock, + (uint32_t)sock->fd, + NULL + client) == NULL) { + goto error_dict_set; } return 0; -error_dict_set_with_hash: +error_dict_set: return -1; } static inline int client_delete_by_sock(patty_ax25_server *server, patty_ax25_sock *sock) { - return patty_dict_delete_with_hash(server->clients_by_sock, sock->fd); + return patty_dict_delete(server->clients_by_sock, (uint32_t)sock->fd); } static inline uint32_t hash_addr(patty_ax25_addr *addr) { @@ -260,17 +257,15 @@ static int sock_save_by_addr(patty_dict *dict, patty_ax25_addr *addr) { uint32_t hash = hash_addr(addr); - if (patty_dict_set_with_hash(dict, - addr, - sizeof(*addr), - sock, - hash) == NULL) { - goto error_dict_set_with_hash; + if (patty_dict_set(dict, + hash, + sock) == NULL) { + goto error_dict_set; } return 0; -error_dict_set_with_hash: +error_dict_set: return -1; } @@ -280,17 +275,15 @@ static int sock_save_by_addrpair(patty_dict *dict, patty_ax25_addr *remote) { uint32_t hash = hash_addrpair(local, remote); - if (patty_dict_set_with_hash(dict, - NULL + sock->fd, - sizeof(*sock), - sock, - hash) == NULL) { - goto error_dict_set_with_hash; + if (patty_dict_set(dict, + hash, + sock) == NULL) { + goto error_dict_set; } return 0; -error_dict_set_with_hash: +error_dict_set: return -1; } @@ -298,7 +291,7 @@ static int sock_delete_by_addr(patty_dict *dict, patty_ax25_addr *addr) { uint32_t hash = hash_addr(addr); - return patty_dict_delete_with_hash(dict, hash); + return patty_dict_delete(dict, hash); } static int sock_delete_by_addrpair(patty_dict *dict, @@ -306,7 +299,7 @@ static int sock_delete_by_addrpair(patty_dict *dict, patty_ax25_addr *remote) { uint32_t hash = hash_addrpair(local, remote); - return patty_dict_delete_with_hash(dict, hash); + return patty_dict_delete(dict, hash); } static int sock_close(patty_ax25_server *server, @@ -338,7 +331,7 @@ static int sock_close(patty_ax25_server *server, } } - if (patty_dict_delete_with_hash(server->socks_by_fd, sock->fd) < 0) { + if (patty_dict_delete(server->socks_by_fd, (uint32_t)sock->fd) < 0) { goto error_dict_delete_by_fd_socks; } @@ -398,7 +391,7 @@ int patty_ax25_server_delete_if(patty_ax25_server *server, if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) { watch_fd(server, fd); - if (patty_dict_delete(server->socks_by_fd, NULL + fd, sizeof(fd)) < 0) { + if (patty_dict_delete(server->socks_by_fd, (uint32_t)fd) < 0) { goto error_dict_delete; } } @@ -909,11 +902,7 @@ static int accept_client(patty_ax25_server *server) { goto error_accept; } - if (patty_dict_set_with_hash(server->clients, - NULL + fd, - sizeof(fd), - NULL + fd, - (uint32_t)fd) == NULL) { + if (patty_dict_set(server->clients, (uint32_t)fd, NULL + fd) == NULL) { goto error_dict_set; } @@ -929,12 +918,11 @@ error_accept: return -1; } -static int handle_client(void *key, - size_t keysz, +static int handle_client(uint32_t key, void *value, void *ctx) { patty_ax25_server *server = ctx; - int client = (int)(key - NULL); + int client = (int)key; ssize_t readlen; enum patty_ax25_call call; @@ -948,8 +936,7 @@ static int handle_client(void *key, } else if (readlen == 0) { clear_fd(server, client); - if (patty_dict_delete_with_hash(server->clients, - (uint32_t)(key - NULL)) < 0) { + if (patty_dict_delete(server->clients, key) < 0) { goto error_dict_delete; } @@ -1390,8 +1377,7 @@ error_io: return -1; } -static int handle_sock(void *key, - size_t keysz, +static int handle_sock(uint32_t key, void *value, void *ctx) { patty_ax25_server *server = ctx;