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;
|
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 void hashmap_release(struct b_object *obj);
|
||||||
|
|
||||||
static struct b_object_type hashmap_type = {
|
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,
|
struct b_hashmap *hashmap, const b_hashmap_key *key,
|
||||||
const b_hashmap_value *value)
|
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);
|
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||||
|
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
@@ -119,12 +158,9 @@ b_status b_hashmap_put(
|
|||||||
struct b_hashmap_bucket_item *item = b_unbox(
|
struct b_hashmap_bucket_item *item = b_unbox(
|
||||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||||
|
|
||||||
if (item->bi_key.key_size != key->key_size) {
|
if (compare_key(&item->bi_key, key)) {
|
||||||
continue;
|
memcpy(&item->bi_value, value, sizeof *value);
|
||||||
}
|
return B_SUCCESS;
|
||||||
|
|
||||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
|
||||||
return B_ERR_NAME_EXISTS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +180,8 @@ b_status b_hashmap_put(
|
|||||||
const struct b_hashmap_value *b_hashmap_get(
|
const struct b_hashmap_value *b_hashmap_get(
|
||||||
const struct b_hashmap *hashmap, const struct b_hashmap_key *key)
|
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);
|
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
return NULL;
|
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 *item = b_unbox(
|
||||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||||
|
|
||||||
if (item->bi_key.key_size != key->key_size) {
|
if (compare_key(&item->bi_key, key)) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
|
||||||
return &item->bi_value;
|
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)
|
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);
|
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
return false;
|
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 *item = b_unbox(
|
||||||
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
struct b_hashmap_bucket_item, it.entry, bi_entry);
|
||||||
|
|
||||||
if (item->bi_key.key_size != key->key_size) {
|
if (compare_key(&item->bi_key, key)) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(item->bi_key.key_data, key->key_data, key->key_size)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <blue/core/status.h>
|
#include <blue/core/status.h>
|
||||||
#include <blue/object/object.h>
|
#include <blue/object/object.h>
|
||||||
#include <blue/object/type.h>
|
#include <blue/object/type.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define B_HASHMAP(p) ((b_hashmap *)(p))
|
#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_key_destructor)(void *);
|
||||||
typedef void (*b_hashmap_value_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 {
|
typedef struct b_hashmap_key {
|
||||||
|
b_hashmap_key_flags key_flags;
|
||||||
const void *key_data;
|
const void *key_data;
|
||||||
size_t key_size;
|
size_t key_size;
|
||||||
} b_hashmap_key;
|
} b_hashmap_key;
|
||||||
|
|||||||
Reference in New Issue
Block a user