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:
2025-09-22 10:48:05 +01:00
parent d9041cda3f
commit b7da91ac93
2 changed files with 54 additions and 19 deletions

View File

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

View File

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