object: hashmap: implement integer-based hashmap keys
rather than always interpreting a b_hashmap_key as a buffer to be hashed, b_hashmap can now be told to consider the value of the key_data pointer itself as the key, treating it as a buffer of size sizeof(void*).
This commit is contained in:
@@ -38,6 +38,45 @@ static uint64_t hash_data(const void *p, size_t size)
|
||||
return hash;
|
||||
}
|
||||
|
||||
static uint64_t hash_key(const struct b_hashmap_key *key)
|
||||
{
|
||||
if (key->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
|
||||
return hash_data(&key->key_data, sizeof key->key_data);
|
||||
} else {
|
||||
return hash_data(key->key_data, key->key_size);
|
||||
}
|
||||
}
|
||||
|
||||
static bool compare_key(
|
||||
const struct b_hashmap_key *a, const struct b_hashmap_key *b)
|
||||
{
|
||||
const void *a_data = NULL, *b_data = NULL;
|
||||
size_t a_len = 0, b_len = 0;
|
||||
|
||||
if (a->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
|
||||
a_data = &a->key_data;
|
||||
a_len = sizeof a->key_data;
|
||||
} else {
|
||||
a_data = a->key_data;
|
||||
a_len = a->key_size;
|
||||
}
|
||||
|
||||
if (b->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
|
||||
b_data = &b->key_data;
|
||||
b_len = sizeof b->key_data;
|
||||
} else {
|
||||
b_data = b->key_data;
|
||||
b_len = b->key_size;
|
||||
}
|
||||
|
||||
if (a_len != b_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t cmp_len = a_len;
|
||||
return memcmp(a_data, b_data, cmp_len) == 0;
|
||||
}
|
||||
|
||||
static void hashmap_release(struct b_object *obj);
|
||||
|
||||
static struct b_object_type hashmap_type = {
|
||||
@@ -101,7 +140,7 @@ b_status b_hashmap_put(
|
||||
struct b_hashmap *hashmap, const b_hashmap_key *key,
|
||||
const b_hashmap_value *value)
|
||||
{
|
||||
uint64_t hash = hash_data(key->key_data, key->key_size);
|
||||
uint64_t hash = hash_key(key);
|
||||
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||
|
||||
if (!bucket) {
|
||||
@@ -119,12 +158,9 @@ b_status b_hashmap_put(
|
||||
struct b_hashmap_bucket_item *item = b_unbox(
|
||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||
|
||||
if (item->bi_key.key_size != key->key_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
||||
return B_ERR_NAME_EXISTS;
|
||||
if (compare_key(&item->bi_key, key)) {
|
||||
memcpy(&item->bi_value, value, sizeof *value);
|
||||
return B_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +180,8 @@ b_status b_hashmap_put(
|
||||
const struct b_hashmap_value *b_hashmap_get(
|
||||
const struct b_hashmap *hashmap, const struct b_hashmap_key *key)
|
||||
{
|
||||
uint64_t hash = hash_data(key->key_data, key->key_size);
|
||||
uint64_t hash = hash_key(key);
|
||||
|
||||
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||
if (!bucket) {
|
||||
return NULL;
|
||||
@@ -155,11 +192,7 @@ const struct b_hashmap_value *b_hashmap_get(
|
||||
struct b_hashmap_bucket_item *item = b_unbox(
|
||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||
|
||||
if (item->bi_key.key_size != key->key_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
||||
if (compare_key(&item->bi_key, key)) {
|
||||
return &item->bi_value;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +202,7 @@ const struct b_hashmap_value *b_hashmap_get(
|
||||
|
||||
bool b_hashmap_has_key(const struct b_hashmap *hashmap, const b_hashmap_key *key)
|
||||
{
|
||||
uint64_t hash = hash_data(key->key_data, key->key_size);
|
||||
uint64_t hash = hash_key(key);
|
||||
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||
if (!bucket) {
|
||||
return false;
|
||||
@@ -180,11 +213,7 @@ bool b_hashmap_has_key(const struct b_hashmap *hashmap, const b_hashmap_key *key
|
||||
struct b_hashmap_bucket_item *item = b_unbox(
|
||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||
|
||||
if (item->bi_key.key_size != key->key_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
||||
if (compare_key(&item->bi_key, key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <blue/core/status.h>
|
||||
#include <blue/object/object.h>
|
||||
#include <blue/object/type.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define B_HASHMAP(p) ((b_hashmap *)(p))
|
||||
|
||||
@@ -38,7 +39,12 @@ typedef struct b_hashmap b_hashmap;
|
||||
typedef void (*b_hashmap_key_destructor)(void *);
|
||||
typedef void (*b_hashmap_value_destructor)(void *);
|
||||
|
||||
typedef enum b_hashmap_key_flags {
|
||||
B_HASHMAP_KEY_F_INTVALUE = 0x01u,
|
||||
} b_hashmap_key_flags;
|
||||
|
||||
typedef struct b_hashmap_key {
|
||||
b_hashmap_key_flags key_flags;
|
||||
const void *key_data;
|
||||
size_t key_size;
|
||||
} b_hashmap_key;
|
||||
|
||||
Reference in New Issue
Block a user