From 2966d6dc7c0aa3c95fd01f6ba660e4aabbd1795b Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Sat, 22 Jan 2022 15:55:09 +0100 Subject: [PATCH] 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. --- src/eval.c | 19 ++-- src/hashmap.c | 249 ++++++++++++++++++++++++-------------------------- src/hashmap.h | 44 +++++---- src/value.c | 75 ++++++--------- 4 files changed, 184 insertions(+), 203 deletions(-) diff --git a/src/eval.c b/src/eval.c index 5c7306b..4743a10 100644 --- a/src/eval.c +++ b/src/eval.c @@ -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; } diff --git a/src/hashmap.c b/src/hashmap.c index 4d35ae3..2b1f0d7 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -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) } diff --git a/src/hashmap.h b/src/hashmap.h index 17c898c..7cbcc89 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -11,12 +11,13 @@ extern "C" { #define APFL_HASH_FNV1A_INIT 14695981039346656037U // offset_basis for 64bit FNV-1(a) -// TODO: 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 } diff --git a/src/value.c b/src/value.c index 045fd80..a7dc686 100644 --- a/src/value.c +++ b/src/value.c @@ -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;