hashmap: Don't hide hashmap struct behind a pointer any more

Since the hashmap is meant for internal use only, there is no need to hide
the internal data. This also allows us to save some malloc() calls.
This commit is contained in:
Laria 2022-01-22 15:55:09 +01:00
parent afd5d8e1d2
commit 2966d6dc7c
4 changed files with 184 additions and 203 deletions

View file

@ -15,7 +15,7 @@
} while (0)
struct apfl_ctx_data {
apfl_hashmap scope;
struct apfl_hashmap scope;
struct apfl_value *stack;
size_t stack_len;
@ -150,10 +150,11 @@ static const struct apfl_hashmap_callbacks scope_hashmap_callbacks = {
.copy_value = scope_copy_value,
};
apfl_hashmap
scope_new(void)
bool
scope_init(struct apfl_hashmap *map)
{
return apfl_hashmap_new(
return apfl_hashmap_init(
map,
scope_hashmap_callbacks,
sizeof(apfl_refcounted_string),
sizeof(variable)
@ -315,7 +316,7 @@ apfl_ctx_new(void)
return NULL;
}
if ((ctx->scope = scope_new()) == NULL) {
if (!scope_init(&ctx->scope)) {
free(ctx);
return NULL;
}
@ -334,7 +335,7 @@ apfl_ctx_destroy(apfl_ctx ctx)
return;
}
apfl_hashmap_destroy(ctx->scope);
apfl_hashmap_deinit(&ctx->scope);
while (ctx->stack_len > 0) {
stack_must_drop(ctx, -1);
}
@ -347,7 +348,7 @@ static variable
ctx_get_var_for_assignment_inner(apfl_ctx ctx, /*borrowed*/ apfl_refcounted_string name)
{
variable var;
if (apfl_hashmap_get(ctx->scope, &name, &var)) {
if (apfl_hashmap_get(&ctx->scope, &name, &var)) {
return var;
}
@ -355,7 +356,7 @@ ctx_get_var_for_assignment_inner(apfl_ctx ctx, /*borrowed*/ apfl_refcounted_stri
return NULL;
}
if (!apfl_hashmap_set(ctx->scope, &name, &var)) {
if (!apfl_hashmap_set(&ctx->scope, &name, &var)) {
variable_unref(var);
return NULL;
}
@ -375,7 +376,7 @@ static variable
ctx_get_var(apfl_ctx ctx, apfl_refcounted_string name)
{
variable var;
bool ok = apfl_hashmap_get(ctx->scope, &name, &var);
bool ok = apfl_hashmap_get(&ctx->scope, &name, &var);
apfl_refcounted_string_unref(name);
return ok ? var : NULL;
}

View file

@ -5,27 +5,13 @@
#include "hashmap.h"
#include "resizable.h"
struct bucket {
struct apfl_hashmap_bucket {
void *keys;
void *values;
size_t len;
size_t cap;
};
struct apfl_hashmap_struct {
struct apfl_hashmap_callbacks callbacks;
size_t keysize;
size_t valsize;
size_t nbuckets;
struct bucket *buckets;
};
struct apfl_hashmap_cursor_struct {
apfl_hashmap map;
size_t bucket;
size_t i;
};
#define FNV_PRIME 1099511628211U
apfl_hash
@ -45,31 +31,31 @@ apfl_hash_fnv1a(const void *data, size_t len)
return apfl_hash_fnv1a_add(data, len, APFL_HASH_FNV1A_INIT);
}
#define HAS_CALLBACK(map, cb) ((map)->callbacks.cb != NULL)
#define INVOKE_CALLBACK(map, cb, ...) (map)->callbacks.cb((map)->callbacks.opaque, __VA_ARGS__)
#define HAS_CALLBACK(map, cb) ((map).callbacks.cb != NULL)
#define INVOKE_CALLBACK(map, cb, ...) (map).callbacks.cb((map).callbacks.opaque, __VA_ARGS__)
static bool
keys_eq(const apfl_hashmap map, const void *a, const void *b)
keys_eq(const struct apfl_hashmap map, const void *a, const void *b)
{
if (HAS_CALLBACK(map, keys_eq)) {
return INVOKE_CALLBACK(map, keys_eq, a, b);
} else {
return memcmp(a, b, map->keysize) == 0;
return memcmp(a, b, map.keysize) == 0;
}
}
static apfl_hash
calc_hash(apfl_hashmap map, const void *key)
calc_hash(const struct apfl_hashmap map, const void *key)
{
if (HAS_CALLBACK(map, calc_hash)) {
return INVOKE_CALLBACK(map, calc_hash, key);
} else {
return apfl_hash_fnv1a(key, map->keysize);
return apfl_hash_fnv1a(key, map.keysize);
}
}
static void
destroy_key(apfl_hashmap map, void *key)
destroy_key(const struct apfl_hashmap map, void *key)
{
if (HAS_CALLBACK(map, destroy_key)) {
INVOKE_CALLBACK(map, destroy_key, key);
@ -77,7 +63,7 @@ destroy_key(apfl_hashmap map, void *key)
}
static void
destroy_value(apfl_hashmap map, void *value)
destroy_value(const struct apfl_hashmap map, void *value)
{
if (HAS_CALLBACK(map, destroy_value)) {
INVOKE_CALLBACK(map, destroy_value, value);
@ -85,22 +71,22 @@ destroy_value(apfl_hashmap map, void *value)
}
static void
copy_key(apfl_hashmap map, void *dest, void *src)
copy_key(const struct apfl_hashmap map, void *dest, void *src)
{
if (HAS_CALLBACK(map, copy_key)) {
INVOKE_CALLBACK(map, copy_key, dest, src);
} else {
memcpy(dest, src, map->keysize);
memcpy(dest, src, map.keysize);
}
}
static void
copy_value(apfl_hashmap map, void *dest, void *src)
copy_value(const struct apfl_hashmap map, void *dest, void *src)
{
if (HAS_CALLBACK(map, copy_value)) {
INVOKE_CALLBACK(map, copy_value, dest, src);
} else {
memcpy(dest, src, map->valsize);
memcpy(dest, src, map.valsize);
}
}
@ -116,9 +102,9 @@ calc_new_cap(size_t old_cap)
#define KVADDR(base, elemsize, off) (((char*)(base)) + ((elemsize)*(off)))
static bool
find_key_in_bucket(const apfl_hashmap map, struct bucket *bucket, const void *key, size_t *off)
find_key_in_bucket(const struct apfl_hashmap map, struct apfl_hashmap_bucket *bucket, const void *key, size_t *off)
{
size_t keysize = map->keysize;
size_t keysize = map.keysize;
for (size_t i = 0; i < bucket->len; i++) {
if (keys_eq(map, key, KVADDR(bucket->keys, keysize, i))) {
@ -131,10 +117,10 @@ find_key_in_bucket(const apfl_hashmap map, struct bucket *bucket, const void *ke
}
static bool
set_in_bucket(apfl_hashmap map, struct bucket *bucket, void *key, void *value)
set_in_bucket(struct apfl_hashmap map, struct apfl_hashmap_bucket *bucket, void *key, void *value)
{
size_t keysize = map->keysize;
size_t valsize = map->valsize;
size_t keysize = map.keysize;
size_t valsize = map.valsize;
size_t i;
if (find_key_in_bucket(map, bucket, key, &i)) {
@ -174,7 +160,7 @@ set_in_bucket(apfl_hashmap map, struct bucket *bucket, void *key, void *value)
}
static bool
get_in_bucket(const apfl_hashmap map, struct bucket *bucket, const void *key, void *value)
get_in_bucket(const struct apfl_hashmap map, struct apfl_hashmap_bucket *bucket, const void *key, void *value)
{
size_t i;
if (!find_key_in_bucket(map, bucket, key, &i)) {
@ -182,30 +168,30 @@ get_in_bucket(const apfl_hashmap map, struct bucket *bucket, const void *key, vo
}
if (value != NULL) {
size_t valsize = map->valsize;
size_t valsize = map.valsize;
copy_value(map, value, KVADDR(bucket->values, valsize, i));
}
return true;
}
static struct bucket *
bucket_by_key(apfl_hashmap map, const void *key)
static struct apfl_hashmap_bucket *
bucket_by_key(struct apfl_hashmap map, const void *key)
{
apfl_hash hash = calc_hash(map, key);
return &map->buckets[hash % map->nbuckets];
return &map.buckets[hash % map.nbuckets];
}
static void
delete_in_bucket(apfl_hashmap map, struct bucket *bucket, const void *key)
delete_in_bucket(struct apfl_hashmap map, struct apfl_hashmap_bucket *bucket, const void *key)
{
size_t i;
if (!find_key_in_bucket(map, bucket, key, &i)) {
return;
}
size_t keysize = map->keysize;
size_t valsize = map->valsize;
size_t keysize = map.keysize;
size_t valsize = map.valsize;
destroy_key(map, KVADDR(bucket->keys, keysize, i));
destroy_value(map, KVADDR(bucket->values, valsize, i));
@ -226,27 +212,26 @@ delete_in_bucket(apfl_hashmap map, struct bucket *bucket, const void *key)
bucket->len--;
}
#define INITIAL_NBUCKETS 16 // Must be a power of 2
static apfl_hashmap
hashmap_new(struct apfl_hashmap_callbacks callbacks, size_t nbuckets, size_t keysize, size_t valsize)
{
apfl_hashmap map = malloc(sizeof(struct apfl_hashmap_struct));
if (map == NULL) {
goto fail;
}
#define INITIAL_NBUCKETS 16
static bool
hashmap_init(
struct apfl_hashmap *map,
struct apfl_hashmap_callbacks callbacks,
size_t nbuckets,
size_t keysize,
size_t valsize
) {
map->callbacks = callbacks;
map->keysize = keysize;
map->valsize = valsize;
map->nbuckets = nbuckets;
map->buckets = malloc(sizeof(struct bucket) * nbuckets);
if (map->buckets == NULL) {
goto fail;
if ((map->buckets = malloc(sizeof(struct apfl_hashmap_bucket) * nbuckets)) == NULL) {
return false;
}
for (size_t i = 0; i < nbuckets; i++) {
map->buckets[i] = (struct bucket) {
map->buckets[i] = (struct apfl_hashmap_bucket) {
.keys = NULL,
.values = NULL,
.len = 0,
@ -254,43 +239,43 @@ hashmap_new(struct apfl_hashmap_callbacks callbacks, size_t nbuckets, size_t key
};
}
return map;
fail:
free(map);
return NULL;
return true;
}
apfl_hashmap
apfl_hashmap_new(struct apfl_hashmap_callbacks callbacks, size_t keysize, size_t valsize)
{
return hashmap_new(callbacks, INITIAL_NBUCKETS, keysize, valsize);
bool
apfl_hashmap_init(
struct apfl_hashmap *map,
struct apfl_hashmap_callbacks callbacks,
size_t keysize,
size_t valsize
) {
return hashmap_init(map, callbacks, INITIAL_NBUCKETS, keysize, valsize);
}
void
apfl_hashmap_delete(apfl_hashmap map, const void *key)
apfl_hashmap_delete(struct apfl_hashmap *map, const void *key)
{
delete_in_bucket(map, bucket_by_key(map, key), key);
delete_in_bucket(*map, bucket_by_key(*map, key), key);
}
bool
apfl_hashmap_get(const apfl_hashmap map, const void *key, void *value)
apfl_hashmap_get(const struct apfl_hashmap *map, const void *key, void *value)
{
return get_in_bucket(map, bucket_by_key(map, key), key, value);
return get_in_bucket(*map, bucket_by_key(*map, key), key, value);
}
bool
apfl_hashmap_set(apfl_hashmap map, void *key, void *value)
apfl_hashmap_set(struct apfl_hashmap *map, void *key, void *value)
{
return set_in_bucket(map, bucket_by_key(map, key), key, value);
return set_in_bucket(*map, bucket_by_key(*map, key), key, value);
}
static void
destroy_bucket(apfl_hashmap map, struct bucket *bucket)
destroy_bucket(const struct apfl_hashmap map, struct apfl_hashmap_bucket *bucket)
{
for (size_t i = 0; i < bucket->len; i++) {
destroy_key(map, KVADDR(bucket->keys, map->keysize, i));
destroy_value(map, KVADDR(bucket->values, map->valsize, i));
destroy_key(map, KVADDR(bucket->keys, map.keysize, i));
destroy_value(map, KVADDR(bucket->values, map.valsize, i));
}
free(bucket->keys);
free(bucket->values);
@ -299,17 +284,17 @@ destroy_bucket(apfl_hashmap map, struct bucket *bucket)
}
size_t
apfl_hashmap_count(const apfl_hashmap map)
apfl_hashmap_count(const struct apfl_hashmap map)
{
size_t count = 0;
for (size_t i = 0; i < map->nbuckets; i++) {
count += map->buckets[i].len;
for (size_t i = 0; i < map.nbuckets; i++) {
count += map.buckets[i].len;
}
return count;
}
void
apfl_hashmap_destroy(apfl_hashmap map)
apfl_hashmap_deinit(struct apfl_hashmap *map)
{
if (map == NULL) {
return;
@ -317,28 +302,34 @@ apfl_hashmap_destroy(apfl_hashmap map)
if (map->buckets != NULL) {
for (size_t i = 0; i < map->nbuckets; i++) {
destroy_bucket(map, &map->buckets[i]);
destroy_bucket(*map, &map->buckets[i]);
}
free(map->buckets);
}
free(map);
}
apfl_hashmap
apfl_hashmap_copy(apfl_hashmap src)
struct apfl_hashmap
apfl_hashmap_move(struct apfl_hashmap *src)
{
size_t keysize = src->keysize;
size_t valsize = src->valsize;
struct apfl_hashmap out = *src;
src->buckets = NULL;
src->nbuckets = 0;
return out;
}
apfl_hashmap dst = hashmap_new(src->callbacks, src->nbuckets, keysize, valsize);
if (dst == NULL) {
return NULL;
bool
apfl_hashmap_copy(struct apfl_hashmap *dst, struct apfl_hashmap src)
{
size_t keysize = src.keysize;
size_t valsize = src.valsize;
if (!hashmap_init(dst, src.callbacks, src.nbuckets, keysize, valsize)) {
return false;
}
for (size_t i = 0; i < dst->nbuckets; i++) {
struct bucket *srcbucket = &src->buckets[i];
struct bucket *dstbucket = &dst->buckets[i];
struct apfl_hashmap_bucket *srcbucket = &src.buckets[i];
struct apfl_hashmap_bucket *dstbucket = &dst->buckets[i];
size_t len = srcbucket->len;
if (len == 0) {
@ -360,13 +351,13 @@ apfl_hashmap_copy(apfl_hashmap src)
for (size_t j = 0; j < len; j++) {
copy_key(
dst,
*dst,
KVADDR(dstbucket->keys, keysize, j),
KVADDR(srcbucket->keys, keysize, j)
);
copy_value(
dst,
*dst,
KVADDR(dstbucket->values, valsize, j),
KVADDR(srcbucket->values, valsize, j)
);
@ -378,52 +369,50 @@ apfl_hashmap_copy(apfl_hashmap src)
return dst;
fail:
apfl_hashmap_destroy(dst);
return NULL;
apfl_hashmap_deinit(dst);
return false;
}
static void
cursor_skip_empty_buckets(apfl_hashmap_cursor cur)
cursor_skip_empty_buckets(struct apfl_hashmap_cursor *cur)
{
apfl_hashmap map = cur->map;
struct apfl_hashmap *map = cur->map;
while (cur->bucket < map->nbuckets && map->buckets[cur->bucket].len == 0) {
cur->bucket++;
}
}
apfl_hashmap_cursor
apfl_hashmap_get_cursor(const apfl_hashmap map)
struct apfl_hashmap_cursor
apfl_hashmap_get_cursor(struct apfl_hashmap *map)
{
apfl_hashmap_cursor cursor = malloc(sizeof(struct apfl_hashmap_cursor_struct));
if (cursor != NULL) {
cursor->map = map;
cursor->i = 0;
cursor->bucket = 0;
cursor_skip_empty_buckets(cursor);
}
struct apfl_hashmap_cursor cursor = {
.map = map,
.i = 0,
.bucket = 0,
};
cursor_skip_empty_buckets(&cursor);
return cursor;
}
bool
apfl_hashmap_cursor_is_end(apfl_hashmap_cursor cursor)
apfl_hashmap_cursor_is_end(struct apfl_hashmap_cursor cursor)
{
return cursor->bucket >= cursor->map->nbuckets;
return cursor.bucket >= cursor.map->nbuckets;
}
static struct bucket *
cursor_get_bucket(apfl_hashmap_cursor cursor)
static struct apfl_hashmap_bucket *
cursor_get_bucket(struct apfl_hashmap_cursor cursor)
{
return apfl_hashmap_cursor_is_end(cursor)
? NULL
: &cursor->map->buckets[cursor->bucket];
: &cursor.map->buckets[cursor.bucket];
}
void
apfl_hashmap_cursor_next(apfl_hashmap_cursor cursor)
apfl_hashmap_cursor_next(struct apfl_hashmap_cursor *cursor)
{
struct bucket *bucket = cursor_get_bucket(cursor);
struct apfl_hashmap_bucket *bucket = cursor_get_bucket(*cursor);
if (bucket == NULL) {
return; // End already reached
@ -439,33 +428,33 @@ apfl_hashmap_cursor_next(apfl_hashmap_cursor cursor)
cursor_skip_empty_buckets(cursor);
}
#define CURSOR_GET(cursor, out, bucketmemb, sizememb, copy) \
struct bucket *bucket = cursor_get_bucket(cursor); \
\
if (bucket == NULL) { \
return; /* End already reached */ \
} \
\
if (cursor->i >= bucket->len) { \
return; \
} \
\
size_t size = cursor->map->sizememb; \
\
copy( \
cursor->map, \
out, \
KVADDR(bucket->bucketmemb, size, cursor->i) \
); \
#define CURSOR_GET(cursor, out, bucketmemb, sizememb, copy) \
struct apfl_hashmap_bucket *bucket = cursor_get_bucket(cursor); \
\
if (bucket == NULL) { \
return; /* End already reached */ \
} \
\
if (cursor.i >= bucket->len) { \
return; \
} \
\
size_t size = cursor.map->sizememb; \
\
copy( \
*cursor.map, \
out, \
KVADDR(bucket->bucketmemb, size, cursor.i) \
); \
void
apfl_hashmap_cursor_get_key(apfl_hashmap_cursor cursor, void *key)
apfl_hashmap_cursor_get_key(struct apfl_hashmap_cursor cursor, void *key)
{
CURSOR_GET(cursor, key, keys, keysize, copy_key)
}
void
apfl_hashmap_cursor_get_value(apfl_hashmap_cursor cursor, void *value)
apfl_hashmap_cursor_get_value(struct apfl_hashmap_cursor cursor, void *value)
{
CURSOR_GET(cursor, value, values, valsize, copy_value)
}

View file

@ -11,12 +11,13 @@ extern "C" {
#define APFL_HASH_FNV1A_INIT 14695981039346656037U // offset_basis for 64bit FNV-1(a)
// TODO: <stdint.h> is not required to provide uint64_t
typedef uint64_t apfl_hash;
typedef struct apfl_hashmap_struct *apfl_hashmap;
typedef struct apfl_hashmap_cursor_struct *apfl_hashmap_cursor;
struct apfl_hashmap_cursor {
struct apfl_hashmap *map;
size_t bucket;
size_t i;
};
struct apfl_hashmap_callbacks {
void *opaque;
@ -43,27 +44,34 @@ struct apfl_hashmap_callbacks {
void (*copy_value) (void *opaque, void *dest, void *src);
};
struct apfl_hashmap {
struct apfl_hashmap_callbacks callbacks;
size_t keysize;
size_t valsize;
size_t nbuckets;
struct apfl_hashmap_bucket *buckets;
};
apfl_hash apfl_hash_fnv1a_add(const void *, size_t len, apfl_hash);
apfl_hash apfl_hash_fnv1a(const void *, size_t len);
apfl_hashmap apfl_hashmap_new(struct apfl_hashmap_callbacks, size_t keysize, size_t valsize);
void apfl_hashmap_delete(apfl_hashmap, const void *key);
bool apfl_hashmap_get(const apfl_hashmap, const void *key, void *value);
bool apfl_hashmap_set(apfl_hashmap, void *key, void *value);
size_t apfl_hashmap_count(const apfl_hashmap);
void apfl_hashmap_destroy(apfl_hashmap);
bool apfl_hashmap_init(struct apfl_hashmap *, struct apfl_hashmap_callbacks, size_t keysize, size_t valsize);
void apfl_hashmap_delete(struct apfl_hashmap *, const void *key);
bool apfl_hashmap_get(const struct apfl_hashmap *, const void *key, void *value);
bool apfl_hashmap_set(struct apfl_hashmap *, void *key, void *value);
size_t apfl_hashmap_count(const struct apfl_hashmap);
void apfl_hashmap_deinit(struct apfl_hashmap *);
apfl_hashmap apfl_hashmap_copy(apfl_hashmap src);
struct apfl_hashmap apfl_hashmap_move(struct apfl_hashmap *src);
bool apfl_hashmap_copy(struct apfl_hashmap *dst, struct apfl_hashmap src);
#define apfl_hashmap_isset(m, k) (apfl_hashmap_get((m), (k), NULL))
apfl_hashmap_cursor apfl_hashmap_get_cursor(apfl_hashmap);
bool apfl_hashmap_cursor_is_end(apfl_hashmap_cursor);
void apfl_hashmap_cursor_next(apfl_hashmap_cursor);
void apfl_hashmap_cursor_get_key(apfl_hashmap_cursor, void *key);
void apfl_hashmap_cursor_get_value(apfl_hashmap_cursor, void *value);
#define apfl_hashmap_cursor_destroy(cur) (free(cur))
struct apfl_hashmap_cursor apfl_hashmap_get_cursor(struct apfl_hashmap *);
bool apfl_hashmap_cursor_is_end(struct apfl_hashmap_cursor);
void apfl_hashmap_cursor_next(struct apfl_hashmap_cursor *);
void apfl_hashmap_cursor_get_key(struct apfl_hashmap_cursor, void *key);
void apfl_hashmap_cursor_get_value(struct apfl_hashmap_cursor, void *value);
#ifdef __cplusplus
}

View file

@ -14,7 +14,7 @@ struct apfl_list_data {
struct apfl_dict_data {
unsigned refcount;
apfl_hashmap map;
struct apfl_hashmap map;
};
static apfl_hash value_hash(const struct apfl_value);
@ -92,10 +92,11 @@ static const struct apfl_hashmap_callbacks dict_hashmap_callbacks = {
.copy_value = dict_copy_key_or_value,
};
static apfl_hashmap
new_hashmap_for_dict(void)
static bool
init_hashmap_for_dict(struct apfl_hashmap *map)
{
return apfl_hashmap_new(
return apfl_hashmap_init(
map,
dict_hashmap_callbacks,
sizeof(struct apfl_value),
sizeof(struct apfl_value)
@ -119,7 +120,7 @@ apfl_dict_unref(apfl_dict dict)
return;
}
apfl_hashmap_destroy(dict->map);
apfl_hashmap_deinit(&dict->map);
free(dict);
}
@ -161,13 +162,10 @@ print(unsigned indent, FILE *out, struct apfl_value value, bool skip_first_inden
return;
}
apfl_hashmap_cursor cur = apfl_hashmap_get_cursor(value.dict->map);
if (cur == NULL) {
return; // TODO: Handle failure in a better way
}
struct apfl_hashmap_cursor cur = apfl_hashmap_get_cursor(&value.dict->map);
apfl_print_indented(first_indent, out, "[\n");
for (; !apfl_hashmap_cursor_is_end(cur); apfl_hashmap_cursor_next(cur)) {
for (; !apfl_hashmap_cursor_is_end(cur); apfl_hashmap_cursor_next(&cur)) {
struct apfl_value k, v;
apfl_hashmap_cursor_get_key(cur, &k);
apfl_hashmap_cursor_get_value(cur, &v);
@ -179,7 +177,6 @@ print(unsigned indent, FILE *out, struct apfl_value value, bool skip_first_inden
apfl_value_deinit(&v);
fprintf(out, "\n");
}
apfl_hashmap_cursor_destroy(cur);
apfl_print_indented(indent, out, "]");
return;
}
@ -247,10 +244,15 @@ list_eq(apfl_list a, apfl_list b)
}
static bool
dict_eq_inner(apfl_hashmap_cursor cur, const apfl_dict b)
dict_eq(const apfl_dict a, const apfl_dict b)
{
if (a == b) {
return true;
}
struct apfl_hashmap_cursor cur = apfl_hashmap_get_cursor(&a->map);
size_t total = 0;
for (; !apfl_hashmap_cursor_is_end(cur); apfl_hashmap_cursor_next(cur)) {
for (; !apfl_hashmap_cursor_is_end(cur); apfl_hashmap_cursor_next(&cur)) {
struct apfl_value key;
struct apfl_value val;
@ -258,7 +260,7 @@ dict_eq_inner(apfl_hashmap_cursor cur, const apfl_dict b)
apfl_hashmap_cursor_get_value(cur, &val);
struct apfl_value other_val;
if (!apfl_hashmap_get(b->map, &key, &other_val)) {
if (!apfl_hashmap_get(&b->map, &key, &other_val)) {
apfl_value_deinit(&key);
apfl_value_deinit(&val);
return false;
@ -278,24 +280,6 @@ dict_eq_inner(apfl_hashmap_cursor cur, const apfl_dict b)
return total == apfl_hashmap_count(b->map);
}
static bool
dict_eq(const apfl_dict a, const apfl_dict b)
{
if (a == b) {
return true;
}
apfl_hashmap_cursor cur = apfl_hashmap_get_cursor(a->map);
if (cur == NULL) {
assert(false); // TODO: It's rather ugly that this can fail and that we return false then!
return false;
}
bool eq = dict_eq_inner(cur, b);
apfl_hashmap_cursor_destroy(cur);
return eq;
}
bool
apfl_value_eq(const struct apfl_value a, const struct apfl_value b)
{
@ -456,9 +440,8 @@ apfl_editable_list_finalize(apfl_editable_list elist)
return list;
}
struct apfl_editable_dict_data {
apfl_hashmap map;
struct apfl_hashmap map;
};
apfl_editable_dict
@ -469,7 +452,7 @@ apfl_editable_dict_new(void)
return NULL;
}
if ((ed->map = new_hashmap_for_dict()) == NULL) {
if (!init_hashmap_for_dict(&ed->map)) {
free(ed);
return NULL;
}
@ -492,10 +475,10 @@ apfl_editable_dict_new_from_dict(apfl_dict dict)
if (dict->refcount == 1) {
// We're the only one having a reference to the dict. We can directly use it's hashmap!
MOVEPTR(ed->map, dict->map);
ed->map = apfl_hashmap_move(&dict->map);
} else {
// There are other places referencing the dict, we need to create a shallow copy first.
if ((ed->map = apfl_hashmap_copy(dict->map)) == NULL) {
if (!apfl_hashmap_copy(&ed->map, dict->map)) {
free(ed);
apfl_dict_unref(dict);
return NULL;
@ -513,7 +496,7 @@ apfl_editable_dict_get(
struct apfl_value key,
struct apfl_value *out
) {
bool ok = apfl_hashmap_get(ed->map, &key, out);
bool ok = apfl_hashmap_get(&ed->map, &key, out);
apfl_value_deinit(&key);
return ok;
}
@ -521,11 +504,11 @@ apfl_editable_dict_get(
bool
apfl_editable_dict_set(apfl_editable_dict ed, struct apfl_value key, struct apfl_value value)
{
if (ed == NULL || ed->map == NULL) {
if (ed == NULL) {
return false;
}
bool ok = apfl_hashmap_set(ed->map, &key, &value);
bool ok = apfl_hashmap_set(&ed->map, &key, &value);
apfl_value_deinit(&key);
apfl_value_deinit(&value);
return ok;
@ -534,18 +517,18 @@ apfl_editable_dict_set(apfl_editable_dict ed, struct apfl_value key, struct apfl
void
apfl_editable_dict_delete(apfl_editable_dict ed, struct apfl_value key)
{
if (ed == NULL || ed->map == NULL) {
if (ed == NULL) {
return;
}
apfl_hashmap_delete(ed->map, &key);
apfl_hashmap_delete(&ed->map, &key);
apfl_value_deinit(&key);
}
apfl_dict
apfl_editable_dict_finalize(apfl_editable_dict ed)
{
if (ed == NULL || ed->map == NULL) {
if (ed == NULL) {
return NULL;
}
@ -556,7 +539,7 @@ apfl_editable_dict_finalize(apfl_editable_dict ed)
}
dict->refcount = 1;
MOVEPTR(dict->map, ed->map);
dict->map = apfl_hashmap_move(&ed->map);
free(ed);
@ -570,7 +553,7 @@ apfl_editable_dict_destroy(apfl_editable_dict ed)
return;
}
apfl_hashmap_destroy(ed->map);
apfl_hashmap_deinit(&ed->map);
free(ed);
}
@ -618,7 +601,7 @@ apfl_list_get_item(apfl_list list, size_t index, struct apfl_value *out)
bool
apfl_dict_get_item(apfl_dict dict, struct apfl_value key, struct apfl_value *out)
{
bool ok = apfl_hashmap_get(dict->map, &key, out);
bool ok = apfl_hashmap_get(&dict->map, &key, out);
apfl_dict_unref(dict);
apfl_value_deinit(&key);
return ok;