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
This commit is contained in:
parent
a7cab09e47
commit
b281925eba
5 changed files with 84 additions and 136 deletions
|
@ -4,17 +4,14 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <patty/hash.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
|
63
src/dict.c
63
src/dict.c
|
@ -2,7 +2,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <patty/dict.h>
|
||||
#include <patty/hash.h>
|
||||
|
||||
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; i<PATTY_DICT_BUCKET_SIZE; i++) {
|
||||
patty_dict_slot *slot = &bucket->slots[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);
|
||||
}
|
||||
|
|
23
src/if.c
23
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) {
|
||||
|
|
16
src/route.c
16
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);
|
||||
}
|
||||
|
|
86
src/server.c
86
src/server.c
|
@ -10,6 +10,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <patty/ax25.h>
|
||||
#include <patty/hash.h>
|
||||
|
||||
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue