Renaming bidimap to hashbidimap

This commit is contained in:
Leonardo committed 2020-05-04 23:02:57 -03:00
1 parent c58f3df50a
commit b35281b8dc
6 files changed
+1130 -1120

No files matched your search

+16 -16
View File
@@ -25,22 +25,22 @@ OUTPUT_DIR = './tests/main/src'
collections = [
# type, header, pfx, sname, key, val
{'t': 'BIDIMAP', 'h': '"cmc/bidimap.h"', 'pfx': 'bm', 'sname': 'bidimap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'BITSET', 'h': '"cmc/bitset.h"', 'pfx': 'bs', 'sname': 'bitset', 'key': '', 'val': '' },
{'t': 'DEQUE', 'h': '"cmc/deque.h"', 'pfx': 'd', 'sname': 'deque', 'key': '', 'val': 'size_t'},
{'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'},
{'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'},
{'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'},
{'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'},
{'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'},
{'t': 'MULTIMAP', 'h': '"cmc/multimap.h"', 'pfx': 'mm', 'sname': 'multimap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'MULTISET', 'h': '"cmc/multiset.h"', 'pfx': 'ms', 'sname': 'multiset', 'key': '', 'val': 'size_t'},
{'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'},
{'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'},
{'t': 'STACK', 'h': '"cmc/stack.h"', 'pfx': 's', 'sname': 'stack', 'key': '', 'val': 'size_t'},
{'t': 'TREEMAP', 'h': '"cmc/treemap.h"', 'pfx': 'tm', 'sname': 'treemap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'TREESET', 'h': '"cmc/treeset.h"', 'pfx': 'ts', 'sname': 'treeset', 'key': '', 'val': 'size_t'}
{'t': 'HASHBIDIMAP', 'h': '"cmc/hashbidimap.h"', 'pfx': 'hbm', 'sname': 'hashbidimap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'BITSET', 'h': '"cmc/bitset.h"', 'pfx': 'bs', 'sname': 'bitset', 'key': '', 'val': '' },
{'t': 'DEQUE', 'h': '"cmc/deque.h"', 'pfx': 'd', 'sname': 'deque', 'key': '', 'val': 'size_t'},
{'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'},
{'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'},
{'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'},
{'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'},
{'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'},
{'t': 'MULTIMAP', 'h': '"cmc/multimap.h"', 'pfx': 'mm', 'sname': 'multimap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'MULTISET', 'h': '"cmc/multiset.h"', 'pfx': 'ms', 'sname': 'multiset', 'key': '', 'val': 'size_t'},
{'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'},
{'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'},
{'t': 'STACK', 'h': '"cmc/stack.h"', 'pfx': 's', 'sname': 'stack', 'key': '', 'val': 'size_t'},
{'t': 'TREEMAP', 'h': '"cmc/treemap.h"', 'pfx': 'tm', 'sname': 'treemap', 'key': 'size_t', 'val': 'size_t'},
{'t': 'TREESET', 'h': '"cmc/treeset.h"', 'pfx': 'ts', 'sname': 'treeset', 'key': '', 'val': 'size_t'}
]
# Create output directory
+34 -34
View File
@@ -1,5 +1,5 @@
/**
* bidimap.h
* hashbidimap.h
*
* Creation Date: 26/09/2019
*
@@ -9,7 +9,7 @@
*/
/**
* BidiMap
* HashBidiMap
*
* A bidirectional map is a map that allows you to create a bijection in both
* directions between two sets of elements (K <-> V). It is possible to retrieve
@@ -23,8 +23,8 @@
* the key and the value.
*/
#ifndef CMC_BIDIMAP_H
#define CMC_BIDIMAP_H
#ifndef CMC_HASHBIDIMAP_H
#define CMC_HASHBIDIMAP_H
/* -------------------------------------------------------------------------
* Core functionalities of the C Macro Collections Library
@@ -37,37 +37,37 @@
#include "../cor/hashtable.h"
/* -------------------------------------------------------------------------
* Bidimap Specific
* HashBidimap Specific
* ------------------------------------------------------------------------- */
/* to_string format */
static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
"at %p { "
"buffer:%p, "
"capacity:%" PRIuMAX ", "
"count:%" PRIuMAX ", "
"load:%lf, "
"flag:%d, "
"f_key:%p, "
"f_val:%p, "
"alloc:%p, "
"callbacks:%p }";
static const char *cmc_string_fmt_hashbidimap = "struct %s<%s, %s> "
"at %p { "
"buffer:%p, "
"capacity:%" PRIuMAX ", "
"count:%" PRIuMAX ", "
"load:%lf, "
"flag:%d, "
"f_key:%p, "
"f_val:%p, "
"alloc:%p, "
"callbacks:%p }";
#define CMC_GENERATE_BIDIMAP(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V)
#define CMC_GENERATE_HASHBIDIMAP(PFX, SNAME, K, V) \
CMC_GENERATE_HASHBIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_HASHBIDIMAP_SOURCE(PFX, SNAME, K, V)
#define CMC_WRAPGEN_BIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V)
#define CMC_WRAPGEN_HASHBIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_HASHBIDIMAP_HEADER(PFX, SNAME, K, V)
#define CMC_WRAPGEN_BIDIMAP_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V)
#define CMC_WRAPGEN_HASHBIDIMAP_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_HASHBIDIMAP_SOURCE(PFX, SNAME, K, V)
/* -------------------------------------------------------------------------
* Header
* ------------------------------------------------------------------------- */
#define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \
#define CMC_GENERATE_HASHBIDIMAP_HEADER(PFX, SNAME, K, V) \
\
/* BidiMap Structure */ \
/* HashBidiMap Structure */ \
struct SNAME \
{ \
/* Array 0 is K -> V and array 1 is V -> K */ \
@@ -98,14 +98,14 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
struct cmc_callbacks *callbacks; \
\
/* Methods */ \
/* Function that returns an iterator to the start of the bidimap */ \
/* Returns an iterator to the start of the hashbidimap */ \
struct SNAME##_iter (*it_start)(struct SNAME *); \
\
/* Function that returns an iterator to the end of the bidimap */ \
/* Returns an iterator to the end of the hashbidimap */ \
struct SNAME##_iter (*it_end)(struct SNAME *); \
}; \
\
/* BidiMap Entry */ \
/* HashBidiMap Entry */ \
struct SNAME##_entry \
{ \
/* Entry Key */ \
@@ -119,7 +119,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
/* dist[1] is relative to V -> K */ \
size_t dist[2]; \
\
/* References to this node in the bidimap buffer. Used to */ \
/* References to this node in the hashbidimap buffer. Used to */ \
/* prevent searching for this node twice for update() and */ \
/* remove(). Increases memory overhead but reduces execution time */ \
/* ref[0] is relative to K -> V */ \
@@ -171,10 +171,10 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
int (*pri)(V, V); \
}; \
\
/* BidiMap Iterator */ \
/* HashBidiMap Iterator */ \
struct SNAME##_iter \
{ \
/* Target bidimap */ \
/* Target hashbidimap */ \
struct SNAME *target; \
\
/* Cursor's position (index) */ \
@@ -262,7 +262,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
/* -------------------------------------------------------------------------
* Source
* ------------------------------------------------------------------------- */
#define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \
#define CMC_GENERATE_HASHBIDIMAP_SOURCE(PFX, SNAME, K, V) \
\
/* Implementation Detail Functions */ \
static struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, \
@@ -973,7 +973,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
struct cmc_string str; \
struct SNAME *m_ = _map_; \
\
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashbidimap, \
#SNAME, #K, #V, m_, m_->buffer, m_->capacity, \
m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, \
m_->alloc, m_->callbacks); \
@@ -1439,4 +1439,4 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> "
return iter; \
}
#endif /* CMC_BIDIMAP_H */
#endif /* CMC_HASHBIDIMAP_H */
+2 -2
View File
@@ -1,6 +1,6 @@
#include "utl/timer.h"
#include "unt/bidimap.c"
#include "unt/hashbidimap.c"
#include "unt/bitset.c"
#include "unt/deque.c"
#include "unt/hashmap.c"
@@ -47,10 +47,10 @@ int main(void)
cmc_timer_start(timer);
uintmax_t tests = 0, units = 0;
cmc_run(BidiMap, units, tests);
cmc_run(BitSet, units, tests);
cmc_run(BitSetIter, units, tests);
cmc_run(Deque, units, tests);
cmc_run(HashBidiMap, units, tests);
cmc_run(DequeIter, units, tests);
cmc_run(HashMap, units, tests);
cmc_run(HashMapIter, units, tests);
@@ -1,27 +1,27 @@
#include "cmc/bidimap.h"
#include "cmc/hashbidimap.h"
struct bidimap
struct hashbidimap
{
struct bidimap_entry *(*buffer)[2];
struct hashbidimap_entry *(*buffer)[2];
size_t capacity;
size_t count;
double load;
int flag;
struct bidimap_fkey *f_key;
struct bidimap_fval *f_val;
struct hashbidimap_fkey *f_key;
struct hashbidimap_fval *f_val;
struct cmc_alloc_node *alloc;
struct cmc_callbacks *callbacks;
struct bidimap_iter (*it_start)(struct bidimap *);
struct bidimap_iter (*it_end)(struct bidimap *);
struct hashbidimap_iter (*it_start)(struct hashbidimap *);
struct hashbidimap_iter (*it_end)(struct hashbidimap *);
};
struct bidimap_entry
struct hashbidimap_entry
{
size_t key;
size_t value;
size_t dist[2];
struct bidimap_entry **ref[2];
struct hashbidimap_entry **ref[2];
};
struct bidimap_fkey
struct hashbidimap_fkey
{
int (*cmp)(size_t, size_t);
size_t (*cpy)(size_t);
@@ -30,7 +30,7 @@ struct bidimap_fkey
size_t (*hash)(size_t);
int (*pri)(size_t, size_t);
};
struct bidimap_fval
struct hashbidimap_fval
{
int (*cmp)(size_t, size_t);
size_t (*cpy)(size_t);
@@ -39,9 +39,9 @@ struct bidimap_fval
size_t (*hash)(size_t);
int (*pri)(size_t, size_t);
};
struct bidimap_iter
struct hashbidimap_iter
{
struct bidimap *target;
struct hashbidimap *target;
size_t cursor;
size_t index;
size_t first;
@@ -49,69 +49,73 @@ struct bidimap_iter
_Bool start;
_Bool end;
};
struct bidimap *bm_new(size_t capacity, double load, struct bidimap_fkey *f_key,
struct bidimap_fval *f_val);
struct bidimap *bm_new_custom(size_t capacity, double load,
struct bidimap_fkey *f_key,
struct bidimap_fval *f_val,
struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks);
void bm_clear(struct bidimap *_map_);
void bm_free(struct bidimap *_map_);
void bm_customize(struct bidimap *_map_, struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks);
_Bool bm_insert(struct bidimap *_map_, size_t key, size_t value);
_Bool bm_update_key(struct bidimap *_map_, size_t val, size_t new_key);
_Bool bm_update_val(struct bidimap *_map_, size_t key, size_t new_val);
_Bool bm_remove_by_key(struct bidimap *_map_, size_t key, size_t *out_key,
size_t *out_val);
_Bool bm_remove_by_val(struct bidimap *_map_, size_t val, size_t *out_key,
size_t *out_val);
size_t bm_get_key(struct bidimap *_map_, size_t val);
size_t bm_get_val(struct bidimap *_map_, size_t key);
_Bool bm_contains_key(struct bidimap *_map_, size_t key);
_Bool bm_contains_val(struct bidimap *_map_, size_t val);
_Bool bm_empty(struct bidimap *_map_);
_Bool bm_full(struct bidimap *_map_);
size_t bm_count(struct bidimap *_map_);
size_t bm_capacity(struct bidimap *_map_);
double bm_load(struct bidimap *_map_);
int bm_flag(struct bidimap *_map_);
_Bool bm_resize(struct bidimap *_map_, size_t capacity);
struct bidimap *bm_copy_of(struct bidimap *_map_);
_Bool bm_equals(struct bidimap *_map1_, struct bidimap *_map2_);
struct cmc_string bm_to_string(struct bidimap *_map_);
_Bool bm_print(struct bidimap *_map_, FILE *fptr);
struct bidimap_iter *bm_iter_new(struct bidimap *target);
void bm_iter_free(struct bidimap_iter *iter);
void bm_iter_init(struct bidimap_iter *iter, struct bidimap *target);
_Bool bm_iter_start(struct bidimap_iter *iter);
_Bool bm_iter_end(struct bidimap_iter *iter);
void bm_iter_to_start(struct bidimap_iter *iter);
void bm_iter_to_end(struct bidimap_iter *iter);
_Bool bm_iter_next(struct bidimap_iter *iter);
_Bool bm_iter_prev(struct bidimap_iter *iter);
_Bool bm_iter_advance(struct bidimap_iter *iter, size_t steps);
_Bool bm_iter_rewind(struct bidimap_iter *iter, size_t steps);
_Bool bm_iter_go_to(struct bidimap_iter *iter, size_t index);
size_t bm_iter_key(struct bidimap_iter *iter);
size_t bm_iter_value(struct bidimap_iter *iter);
size_t bm_iter_index(struct bidimap_iter *iter);
static struct bidimap_entry *bm_impl_new_entry(struct bidimap *_map_,
size_t key, size_t value);
static struct bidimap_entry **bm_impl_get_entry_by_key(struct bidimap *_map_,
size_t key);
static struct bidimap_entry **bm_impl_get_entry_by_val(struct bidimap *_map_,
size_t val);
static struct bidimap_entry **
bm_impl_add_entry_to_key(struct bidimap *_map_, struct bidimap_entry *entry);
static struct bidimap_entry **
bm_impl_add_entry_to_val(struct bidimap *_map_, struct bidimap_entry *entry);
static size_t bm_impl_calculate_size(size_t required);
static struct bidimap_iter bm_impl_it_start(struct bidimap *_map_);
static struct bidimap_iter bm_impl_it_end(struct bidimap *_map_);
struct bidimap *bm_new(size_t capacity, double load, struct bidimap_fkey *f_key,
struct bidimap_fval *f_val)
struct hashbidimap *hbm_new(size_t capacity, double load,
struct hashbidimap_fkey *f_key,
struct hashbidimap_fval *f_val);
struct hashbidimap *hbm_new_custom(size_t capacity, double load,
struct hashbidimap_fkey *f_key,
struct hashbidimap_fval *f_val,
struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks);
void hbm_clear(struct hashbidimap *_map_);
void hbm_free(struct hashbidimap *_map_);
void hbm_customize(struct hashbidimap *_map_, struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks);
_Bool hbm_insert(struct hashbidimap *_map_, size_t key, size_t value);
_Bool hbm_update_key(struct hashbidimap *_map_, size_t val, size_t new_key);
_Bool hbm_update_val(struct hashbidimap *_map_, size_t key, size_t new_val);
_Bool hbm_remove_by_key(struct hashbidimap *_map_, size_t key, size_t *out_key,
size_t *out_val);
_Bool hbm_remove_by_val(struct hashbidimap *_map_, size_t val, size_t *out_key,
size_t *out_val);
size_t hbm_get_key(struct hashbidimap *_map_, size_t val);
size_t hbm_get_val(struct hashbidimap *_map_, size_t key);
_Bool hbm_contains_key(struct hashbidimap *_map_, size_t key);
_Bool hbm_contains_val(struct hashbidimap *_map_, size_t val);
_Bool hbm_empty(struct hashbidimap *_map_);
_Bool hbm_full(struct hashbidimap *_map_);
size_t hbm_count(struct hashbidimap *_map_);
size_t hbm_capacity(struct hashbidimap *_map_);
double hbm_load(struct hashbidimap *_map_);
int hbm_flag(struct hashbidimap *_map_);
_Bool hbm_resize(struct hashbidimap *_map_, size_t capacity);
struct hashbidimap *hbm_copy_of(struct hashbidimap *_map_);
_Bool hbm_equals(struct hashbidimap *_map1_, struct hashbidimap *_map2_);
struct cmc_string hbm_to_string(struct hashbidimap *_map_);
_Bool hbm_print(struct hashbidimap *_map_, FILE *fptr);
struct hashbidimap_iter *hbm_iter_new(struct hashbidimap *target);
void hbm_iter_free(struct hashbidimap_iter *iter);
void hbm_iter_init(struct hashbidimap_iter *iter, struct hashbidimap *target);
_Bool hbm_iter_start(struct hashbidimap_iter *iter);
_Bool hbm_iter_end(struct hashbidimap_iter *iter);
void hbm_iter_to_start(struct hashbidimap_iter *iter);
void hbm_iter_to_end(struct hashbidimap_iter *iter);
_Bool hbm_iter_next(struct hashbidimap_iter *iter);
_Bool hbm_iter_prev(struct hashbidimap_iter *iter);
_Bool hbm_iter_advance(struct hashbidimap_iter *iter, size_t steps);
_Bool hbm_iter_rewind(struct hashbidimap_iter *iter, size_t steps);
_Bool hbm_iter_go_to(struct hashbidimap_iter *iter, size_t index);
size_t hbm_iter_key(struct hashbidimap_iter *iter);
size_t hbm_iter_value(struct hashbidimap_iter *iter);
size_t hbm_iter_index(struct hashbidimap_iter *iter);
static struct hashbidimap_entry *hbm_impl_new_entry(struct hashbidimap *_map_,
size_t key, size_t value);
static struct hashbidimap_entry **
hbm_impl_get_entry_by_key(struct hashbidimap *_map_, size_t key);
static struct hashbidimap_entry **
hbm_impl_get_entry_by_val(struct hashbidimap *_map_, size_t val);
static struct hashbidimap_entry **
hbm_impl_add_entry_to_key(struct hashbidimap *_map_,
struct hashbidimap_entry *entry);
static struct hashbidimap_entry **
hbm_impl_add_entry_to_val(struct hashbidimap *_map_,
struct hashbidimap_entry *entry);
static size_t hbm_impl_calculate_size(size_t required);
static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap *_map_);
static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap *_map_);
struct hashbidimap *hbm_new(size_t capacity, double load,
struct hashbidimap_fkey *f_key,
struct hashbidimap_fval *f_val)
{
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
if (capacity == 0 || load <= 0 || load >= 1)
@@ -120,12 +124,12 @@ struct bidimap *bm_new(size_t capacity, double load, struct bidimap_fkey *f_key,
return ((void *)0);
if (!f_key || !f_val)
return ((void *)0);
size_t real_capacity = bm_impl_calculate_size(capacity / load);
struct bidimap *_map_ = alloc->malloc(sizeof(struct bidimap));
size_t real_capacity = hbm_impl_calculate_size(capacity / load);
struct hashbidimap *_map_ = alloc->malloc(sizeof(struct hashbidimap));
if (!_map_)
return ((void *)0);
_map_->buffer =
alloc->calloc(real_capacity, sizeof(struct bidimap_entry *[2]));
alloc->calloc(real_capacity, sizeof(struct hashbidimap_entry *[2]));
if (!_map_->buffer)
{
alloc->free(_map_->buffer);
@@ -140,15 +144,15 @@ struct bidimap *bm_new(size_t capacity, double load, struct bidimap_fkey *f_key,
_map_->f_val = f_val;
_map_->alloc = alloc;
_map_->callbacks = ((void *)0);
_map_->it_start = bm_impl_it_start;
_map_->it_end = bm_impl_it_end;
_map_->it_start = hbm_impl_it_start;
_map_->it_end = hbm_impl_it_end;
return _map_;
}
struct bidimap *bm_new_custom(size_t capacity, double load,
struct bidimap_fkey *f_key,
struct bidimap_fval *f_val,
struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks)
struct hashbidimap *hbm_new_custom(size_t capacity, double load,
struct hashbidimap_fkey *f_key,
struct hashbidimap_fval *f_val,
struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks)
{
if (capacity == 0 || load <= 0 || load >= 1)
return ((void *)0);
@@ -156,14 +160,14 @@ struct bidimap *bm_new_custom(size_t capacity, double load,
return ((void *)0);
if (!f_key || !f_val)
return ((void *)0);
size_t real_capacity = bm_impl_calculate_size(capacity / load);
size_t real_capacity = hbm_impl_calculate_size(capacity / load);
if (!alloc)
alloc = &cmc_alloc_node_default;
struct bidimap *_map_ = alloc->malloc(sizeof(struct bidimap));
struct hashbidimap *_map_ = alloc->malloc(sizeof(struct hashbidimap));
if (!_map_)
return ((void *)0);
_map_->buffer =
alloc->calloc(real_capacity, sizeof(struct bidimap_entry *[2]));
alloc->calloc(real_capacity, sizeof(struct hashbidimap_entry *[2]));
if (!_map_->buffer)
{
alloc->free(_map_->buffer);
@@ -179,15 +183,15 @@ struct bidimap *bm_new_custom(size_t capacity, double load,
_map_->flag = cmc_flags.OK;
_map_->alloc = alloc;
_map_->callbacks = callbacks;
_map_->it_start = bm_impl_it_start;
_map_->it_end = bm_impl_it_end;
_map_->it_start = hbm_impl_it_start;
_map_->it_end = hbm_impl_it_end;
return _map_;
}
void bm_clear(struct bidimap *_map_)
void hbm_clear(struct hashbidimap *_map_)
{
for (size_t i = 0; i < _map_->capacity; i++)
{
struct bidimap_entry *entry = _map_->buffer[i][0];
struct hashbidimap_entry *entry = _map_->buffer[i][0];
if (entry && entry != ((void *)1))
{
if (_map_->f_key->free)
@@ -202,14 +206,14 @@ void bm_clear(struct bidimap *_map_)
_map_->count = 0;
_map_->flag = cmc_flags.OK;
}
void bm_free(struct bidimap *_map_)
void hbm_free(struct hashbidimap *_map_)
{
bm_clear(_map_);
hbm_clear(_map_);
_map_->alloc->free(_map_->buffer);
_map_->alloc->free(_map_);
}
void bm_customize(struct bidimap *_map_, struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks)
void hbm_customize(struct hashbidimap *_map_, struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks)
{
if (!alloc)
_map_->alloc = &cmc_alloc_node_default;
@@ -218,22 +222,24 @@ void bm_customize(struct bidimap *_map_, struct cmc_alloc_node *alloc,
_map_->callbacks = callbacks;
_map_->flag = cmc_flags.OK;
}
_Bool bm_insert(struct bidimap *_map_, size_t key, size_t value)
_Bool hbm_insert(struct hashbidimap *_map_, size_t key, size_t value)
{
if (bm_full(_map_))
if (hbm_full(_map_))
{
if (!bm_resize(_map_, _map_->capacity + 1))
if (!hbm_resize(_map_, _map_->capacity + 1))
return 0;
}
if (bm_impl_get_entry_by_key(_map_, key) != ((void *)0) ||
bm_impl_get_entry_by_val(_map_, value) != ((void *)0))
if (hbm_impl_get_entry_by_key(_map_, key) != ((void *)0) ||
hbm_impl_get_entry_by_val(_map_, value) != ((void *)0))
{
_map_->flag = cmc_flags.DUPLICATE;
return 0;
}
struct bidimap_entry *entry = bm_impl_new_entry(_map_, key, value);
struct bidimap_entry **key_entry = bm_impl_add_entry_to_key(_map_, entry);
struct bidimap_entry **val_entry = bm_impl_add_entry_to_val(_map_, entry);
struct hashbidimap_entry *entry = hbm_impl_new_entry(_map_, key, value);
struct hashbidimap_entry **key_entry =
hbm_impl_add_entry_to_key(_map_, entry);
struct hashbidimap_entry **val_entry =
hbm_impl_add_entry_to_val(_map_, entry);
if (!key_entry || !val_entry)
{
if (key_entry)
@@ -250,15 +256,15 @@ _Bool bm_insert(struct bidimap *_map_, size_t key, size_t value)
_map_->callbacks->create();
return 1;
}
_Bool bm_update_key(struct bidimap *_map_, size_t val, size_t new_key)
_Bool hbm_update_key(struct hashbidimap *_map_, size_t val, size_t new_key)
{
if (bm_empty(_map_))
if (hbm_empty(_map_))
{
_map_->flag = cmc_flags.EMPTY;
return 0;
}
struct bidimap_entry **key_entry, **val_entry;
val_entry = bm_impl_get_entry_by_val(_map_, val);
struct hashbidimap_entry **key_entry, **val_entry;
val_entry = hbm_impl_get_entry_by_val(_map_, val);
if (!val_entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -266,7 +272,7 @@ _Bool bm_update_key(struct bidimap *_map_, size_t val, size_t new_key)
}
if (_map_->f_key->cmp(new_key, (*val_entry)->key) == 0)
goto success;
if (bm_impl_get_entry_by_key(_map_, new_key) != ((void *)0))
if (hbm_impl_get_entry_by_key(_map_, new_key) != ((void *)0))
{
_map_->flag = cmc_flags.DUPLICATE;
return 0;
@@ -277,11 +283,11 @@ _Bool bm_update_key(struct bidimap *_map_, size_t val, size_t new_key)
_map_->flag = cmc_flags.ERROR;
return 0;
}
struct bidimap_entry *to_add = *key_entry;
struct hashbidimap_entry *to_add = *key_entry;
size_t tmp_key = to_add->key;
to_add->key = new_key;
*key_entry = ((void *)1);
if (!bm_impl_add_entry_to_key(_map_, to_add))
if (!hbm_impl_add_entry_to_key(_map_, to_add))
{
to_add->key = tmp_key;
*key_entry = to_add;
@@ -294,15 +300,15 @@ success:
_map_->callbacks->update();
return 1;
}
_Bool bm_update_val(struct bidimap *_map_, size_t key, size_t new_val)
_Bool hbm_update_val(struct hashbidimap *_map_, size_t key, size_t new_val)
{
if (bm_empty(_map_))
if (hbm_empty(_map_))
{
_map_->flag = cmc_flags.EMPTY;
return 0;
}
struct bidimap_entry **key_entry, **val_entry;
key_entry = bm_impl_get_entry_by_key(_map_, key);
struct hashbidimap_entry **key_entry, **val_entry;
key_entry = hbm_impl_get_entry_by_key(_map_, key);
if (!key_entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -310,7 +316,7 @@ _Bool bm_update_val(struct bidimap *_map_, size_t key, size_t new_val)
}
if (_map_->f_key->cmp(new_val, (*key_entry)->value) == 0)
goto success;
if (bm_impl_get_entry_by_val(_map_, new_val) != ((void *)0))
if (hbm_impl_get_entry_by_val(_map_, new_val) != ((void *)0))
{
_map_->flag = cmc_flags.DUPLICATE;
return 0;
@@ -321,11 +327,11 @@ _Bool bm_update_val(struct bidimap *_map_, size_t key, size_t new_val)
_map_->flag = cmc_flags.ERROR;
return 0;
}
struct bidimap_entry *to_add = *val_entry;
struct hashbidimap_entry *to_add = *val_entry;
size_t tmp_val = to_add->value;
to_add->value = new_val;
*val_entry = ((void *)1);
if (!bm_impl_add_entry_to_val(_map_, to_add))
if (!hbm_impl_add_entry_to_val(_map_, to_add))
{
to_add->value = tmp_val;
*val_entry = to_add;
@@ -338,16 +344,16 @@ success:
_map_->callbacks->update();
return 1;
}
_Bool bm_remove_by_key(struct bidimap *_map_, size_t key, size_t *out_key,
size_t *out_val)
_Bool hbm_remove_by_key(struct hashbidimap *_map_, size_t key, size_t *out_key,
size_t *out_val)
{
if (bm_empty(_map_))
if (hbm_empty(_map_))
{
_map_->flag = cmc_flags.EMPTY;
return 0;
}
struct bidimap_entry **key_entry, **val_entry;
key_entry = bm_impl_get_entry_by_key(_map_, key);
struct hashbidimap_entry **key_entry, **val_entry;
key_entry = hbm_impl_get_entry_by_key(_map_, key);
if (!key_entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -372,16 +378,16 @@ _Bool bm_remove_by_key(struct bidimap *_map_, size_t key, size_t *out_key,
_map_->callbacks->delete ();
return 1;
}
_Bool bm_remove_by_val(struct bidimap *_map_, size_t val, size_t *out_key,
size_t *out_val)
_Bool hbm_remove_by_val(struct hashbidimap *_map_, size_t val, size_t *out_key,
size_t *out_val)
{
if (bm_empty(_map_))
if (hbm_empty(_map_))
{
_map_->flag = cmc_flags.EMPTY;
return 0;
}
struct bidimap_entry **key_entry, **val_entry;
val_entry = bm_impl_get_entry_by_val(_map_, val);
struct hashbidimap_entry **key_entry, **val_entry;
val_entry = hbm_impl_get_entry_by_val(_map_, val);
if (!val_entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -406,9 +412,9 @@ _Bool bm_remove_by_val(struct bidimap *_map_, size_t val, size_t *out_key,
_map_->callbacks->delete ();
return 1;
}
size_t bm_get_key(struct bidimap *_map_, size_t val)
size_t hbm_get_key(struct hashbidimap *_map_, size_t val)
{
struct bidimap_entry **entry = bm_impl_get_entry_by_val(_map_, val);
struct hashbidimap_entry **entry = hbm_impl_get_entry_by_val(_map_, val);
if (!entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -419,9 +425,9 @@ size_t bm_get_key(struct bidimap *_map_, size_t val)
_map_->callbacks->read();
return (*entry)->key;
}
size_t bm_get_val(struct bidimap *_map_, size_t key)
size_t hbm_get_val(struct hashbidimap *_map_, size_t key)
{
struct bidimap_entry **entry = bm_impl_get_entry_by_key(_map_, key);
struct hashbidimap_entry **entry = hbm_impl_get_entry_by_key(_map_, key);
if (!entry)
{
_map_->flag = cmc_flags.NOT_FOUND;
@@ -432,47 +438,47 @@ size_t bm_get_val(struct bidimap *_map_, size_t key)
_map_->callbacks->read();
return (*entry)->value;
}
_Bool bm_contains_key(struct bidimap *_map_, size_t key)
_Bool hbm_contains_key(struct hashbidimap *_map_, size_t key)
{
_map_->flag = cmc_flags.OK;
_Bool result = bm_impl_get_entry_by_key(_map_, key) != ((void *)0);
_Bool result = hbm_impl_get_entry_by_key(_map_, key) != ((void *)0);
if (_map_->callbacks && _map_->callbacks->read)
_map_->callbacks->read();
return result;
}
_Bool bm_contains_val(struct bidimap *_map_, size_t val)
_Bool hbm_contains_val(struct hashbidimap *_map_, size_t val)
{
_map_->flag = cmc_flags.OK;
_Bool result = bm_impl_get_entry_by_val(_map_, val) != ((void *)0);
_Bool result = hbm_impl_get_entry_by_val(_map_, val) != ((void *)0);
if (_map_->callbacks && _map_->callbacks->read)
_map_->callbacks->read();
return result;
}
_Bool bm_empty(struct bidimap *_map_)
_Bool hbm_empty(struct hashbidimap *_map_)
{
return _map_->count == 0;
}
_Bool bm_full(struct bidimap *_map_)
_Bool hbm_full(struct hashbidimap *_map_)
{
return (double)_map_->capacity * _map_->load <= (double)_map_->count;
}
size_t bm_count(struct bidimap *_map_)
size_t hbm_count(struct hashbidimap *_map_)
{
return _map_->count;
}
size_t bm_capacity(struct bidimap *_map_)
size_t hbm_capacity(struct hashbidimap *_map_)
{
return _map_->capacity;
}
double bm_load(struct bidimap *_map_)
double hbm_load(struct hashbidimap *_map_)
{
return _map_->load;
}
int bm_flag(struct bidimap *_map_)
int hbm_flag(struct hashbidimap *_map_)
{
return _map_->flag;
}
_Bool bm_resize(struct bidimap *_map_, size_t capacity)
_Bool hbm_resize(struct hashbidimap *_map_, size_t capacity)
{
_map_->flag = cmc_flags.OK;
if (_map_->capacity == capacity)
@@ -484,15 +490,15 @@ _Bool bm_resize(struct bidimap *_map_, size_t capacity)
_map_->flag = cmc_flags.ERROR;
return 0;
}
size_t new_cap = bm_impl_calculate_size(capacity);
size_t new_cap = hbm_impl_calculate_size(capacity);
if (new_cap < _map_->count / _map_->load)
{
_map_->flag = cmc_flags.INVALID;
return 0;
}
struct bidimap *_new_map_ =
bm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val,
_map_->alloc, ((void *)0));
struct hashbidimap *_new_map_ =
hbm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val,
_map_->alloc, ((void *)0));
if (!_new_map_)
{
_map_->flag = cmc_flags.ALLOC;
@@ -500,17 +506,17 @@ _Bool bm_resize(struct bidimap *_map_, size_t capacity)
}
for (size_t i = 0; i < _map_->capacity; i++)
{
struct bidimap_entry *scan = _map_->buffer[i][0];
struct hashbidimap_entry *scan = _map_->buffer[i][0];
if (scan && scan != ((void *)1))
{
struct bidimap_entry **e1 =
bm_impl_add_entry_to_key(_new_map_, scan);
struct bidimap_entry **e2 =
bm_impl_add_entry_to_val(_new_map_, scan);
struct hashbidimap_entry **e1 =
hbm_impl_add_entry_to_key(_new_map_, scan);
struct hashbidimap_entry **e2 =
hbm_impl_add_entry_to_val(_new_map_, scan);
if (!e1 || !e2)
{
_new_map_->f_key = &(struct bidimap_fkey){ ((void *)0) };
_new_map_->f_val = &(struct bidimap_fval){ ((void *)0) };
_new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) };
_new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) };
_map_->alloc->free(_new_map_->buffer);
_map_->alloc->free(_new_map_);
_map_->flag = cmc_flags.ERROR;
@@ -521,14 +527,14 @@ _Bool bm_resize(struct bidimap *_map_, size_t capacity)
}
if (_map_->count != _new_map_->count)
{
_new_map_->f_key = &(struct bidimap_fkey){ ((void *)0) };
_new_map_->f_val = &(struct bidimap_fval){ ((void *)0) };
_new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) };
_new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) };
_map_->alloc->free(_new_map_->buffer);
_map_->alloc->free(_new_map_);
_map_->flag = cmc_flags.ERROR;
return 0;
}
struct bidimap_entry *(*tmp_buff)[2] = _map_->buffer;
struct hashbidimap_entry *(*tmp_buff)[2] = _map_->buffer;
_map_->buffer = _new_map_->buffer;
_map_->capacity = _new_map_->capacity;
_map_->alloc->free(tmp_buff);
@@ -538,11 +544,11 @@ success:
_map_->callbacks->resize();
return 1;
}
struct bidimap *bm_copy_of(struct bidimap *_map_)
struct hashbidimap *hbm_copy_of(struct hashbidimap *_map_)
{
struct bidimap *result =
bm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key,
_map_->f_val, _map_->alloc, _map_->callbacks);
struct hashbidimap *result =
hbm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key,
_map_->f_val, _map_->alloc, _map_->callbacks);
if (!result)
{
_map_->flag = cmc_flags.ERROR;
@@ -550,7 +556,7 @@ struct bidimap *bm_copy_of(struct bidimap *_map_)
}
for (size_t i = 0; i < _map_->capacity; i++)
{
struct bidimap_entry *scan = _map_->buffer[i][0];
struct hashbidimap_entry *scan = _map_->buffer[i][0];
if (scan && scan != ((void *)1))
{
size_t tmp_key;
@@ -563,24 +569,24 @@ struct bidimap *bm_copy_of(struct bidimap *_map_)
tmp_val = _map_->f_val->cpy(scan->value);
else
tmp_val = scan->value;
struct bidimap_entry *entry =
bm_impl_new_entry(result, tmp_key, tmp_val);
bm_impl_add_entry_to_key(result, entry);
bm_impl_add_entry_to_val(result, entry);
struct hashbidimap_entry *entry =
hbm_impl_new_entry(result, tmp_key, tmp_val);
hbm_impl_add_entry_to_key(result, entry);
hbm_impl_add_entry_to_val(result, entry);
result->count++;
}
}
_map_->flag = cmc_flags.OK;
return result;
}
_Bool bm_equals(struct bidimap *_map1_, struct bidimap *_map2_)
_Bool hbm_equals(struct hashbidimap *_map1_, struct hashbidimap *_map2_)
{
_map1_->flag = cmc_flags.OK;
_map2_->flag = cmc_flags.OK;
if (_map1_->count != _map2_->count)
return 0;
struct bidimap *_mapA_;
struct bidimap *_mapB_;
struct hashbidimap *_mapA_;
struct hashbidimap *_mapB_;
if (_map1_->capacity < _map2_->capacity)
{
_mapA_ = _map1_;
@@ -593,11 +599,11 @@ _Bool bm_equals(struct bidimap *_map1_, struct bidimap *_map2_)
}
for (size_t i = 0; i < _mapA_->capacity; i++)
{
struct bidimap_entry *scan = _mapA_->buffer[i][0];
struct hashbidimap_entry *scan = _mapA_->buffer[i][0];
if (scan && scan != ((void *)1))
{
struct bidimap_entry **entry_B =
bm_impl_get_entry_by_key(_mapB_, scan->key);
struct hashbidimap_entry **entry_B =
hbm_impl_get_entry_by_key(_mapB_, scan->key);
if (!entry_B)
return 0;
if (_mapA_->f_val->cmp((*entry_B)->value, scan->value) != 0)
@@ -606,21 +612,21 @@ _Bool bm_equals(struct bidimap *_map1_, struct bidimap *_map2_)
}
return 1;
}
struct cmc_string bm_to_string(struct bidimap *_map_)
struct cmc_string hbm_to_string(struct hashbidimap *_map_)
{
struct cmc_string str;
struct bidimap *m_ = _map_;
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, "bidimap",
"size_t", "size_t", m_, m_->buffer, m_->capacity,
m_->count, m_->load, m_->flag, m_->f_key, m_->f_val,
m_->alloc, m_->callbacks);
struct hashbidimap *m_ = _map_;
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashbidimap,
"hashbidimap", "size_t", "size_t", m_, m_->buffer,
m_->capacity, m_->count, m_->load, m_->flag, m_->f_key,
m_->f_val, m_->alloc, m_->callbacks);
return n >= 0 ? str : (struct cmc_string){ 0 };
}
_Bool bm_print(struct bidimap *_map_, FILE *fptr)
_Bool hbm_print(struct hashbidimap *_map_, FILE *fptr)
{
for (size_t i = 0; i < _map_->capacity; i++)
{
struct bidimap_entry *target = _map_->buffer[i][0];
struct hashbidimap_entry *target = _map_->buffer[i][0];
if (target && target != ((void *)1))
{
if (!_map_->f_key->str(fptr, target->key) ||
@@ -630,30 +636,30 @@ _Bool bm_print(struct bidimap *_map_, FILE *fptr)
}
return 1;
}
struct bidimap_iter *bm_iter_new(struct bidimap *target)
struct hashbidimap_iter *hbm_iter_new(struct hashbidimap *target)
{
struct bidimap_iter *iter =
target->alloc->malloc(sizeof(struct bidimap_iter));
struct hashbidimap_iter *iter =
target->alloc->malloc(sizeof(struct hashbidimap_iter));
if (!iter)
return ((void *)0);
bm_iter_init(iter, target);
hbm_iter_init(iter, target);
return iter;
}
void bm_iter_free(struct bidimap_iter *iter)
void hbm_iter_free(struct hashbidimap_iter *iter)
{
iter->target->alloc->free(iter);
}
void bm_iter_init(struct bidimap_iter *iter, struct bidimap *target)
void hbm_iter_init(struct hashbidimap_iter *iter, struct hashbidimap *target)
{
memset(iter, 0, sizeof(struct bidimap_iter));
memset(iter, 0, sizeof(struct hashbidimap_iter));
iter->target = target;
iter->start = 1;
iter->end = bm_empty(target);
if (!bm_empty(target))
iter->end = hbm_empty(target);
if (!hbm_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
struct bidimap_entry *tmp = target->buffer[i][0];
struct hashbidimap_entry *tmp = target->buffer[i][0];
if (tmp != ((void *)0) && tmp != ((void *)1))
{
iter->first = i;
@@ -663,7 +669,7 @@ void bm_iter_init(struct bidimap_iter *iter, struct bidimap *target)
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
struct bidimap_entry *tmp = target->buffer[i - 1][0];
struct hashbidimap_entry *tmp = target->buffer[i - 1][0];
if (tmp != ((void *)0) && tmp != ((void *)1))
{
iter->last = i - 1;
@@ -672,17 +678,17 @@ void bm_iter_init(struct bidimap_iter *iter, struct bidimap *target)
}
}
}
_Bool bm_iter_start(struct bidimap_iter *iter)
_Bool hbm_iter_start(struct hashbidimap_iter *iter)
{
return bm_empty(iter->target) || iter->start;
return hbm_empty(iter->target) || iter->start;
}
_Bool bm_iter_end(struct bidimap_iter *iter)
_Bool hbm_iter_end(struct hashbidimap_iter *iter)
{
return bm_empty(iter->target) || iter->end;
return hbm_empty(iter->target) || iter->end;
}
void bm_iter_to_start(struct bidimap_iter *iter)
void hbm_iter_to_start(struct hashbidimap_iter *iter)
{
if (!bm_empty(iter->target))
if (!hbm_empty(iter->target))
{
iter->cursor = iter->first;
iter->index = 0;
@@ -690,9 +696,9 @@ void bm_iter_to_start(struct bidimap_iter *iter)
iter->end = 0;
}
}
void bm_iter_to_end(struct bidimap_iter *iter)
void hbm_iter_to_end(struct hashbidimap_iter *iter)
{
if (!bm_empty(iter->target))
if (!hbm_empty(iter->target))
{
iter->cursor = iter->last;
iter->index = iter->target->count - 1;
@@ -700,7 +706,7 @@ void bm_iter_to_end(struct bidimap_iter *iter)
iter->end = 1;
}
}
_Bool bm_iter_next(struct bidimap_iter *iter)
_Bool hbm_iter_next(struct hashbidimap_iter *iter)
{
if (iter->end)
return 0;
@@ -709,8 +715,8 @@ _Bool bm_iter_next(struct bidimap_iter *iter)
iter->end = 1;
return 0;
}
iter->start = bm_empty(iter->target);
struct bidimap_entry *scan = iter->target->buffer[iter->cursor][0];
iter->start = hbm_empty(iter->target);
struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0];
iter->index++;
while (1)
{
@@ -721,7 +727,7 @@ _Bool bm_iter_next(struct bidimap_iter *iter)
}
return 1;
}
_Bool bm_iter_prev(struct bidimap_iter *iter)
_Bool hbm_iter_prev(struct hashbidimap_iter *iter)
{
if (iter->start)
return 0;
@@ -730,8 +736,8 @@ _Bool bm_iter_prev(struct bidimap_iter *iter)
iter->start = 1;
return 0;
}
iter->end = bm_empty(iter->target);
struct bidimap_entry *scan = iter->target->buffer[iter->cursor][0];
iter->end = hbm_empty(iter->target);
struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0];
iter->index--;
while (1)
{
@@ -742,7 +748,7 @@ _Bool bm_iter_prev(struct bidimap_iter *iter)
}
return 1;
}
_Bool bm_iter_advance(struct bidimap_iter *iter, size_t steps)
_Bool hbm_iter_advance(struct hashbidimap_iter *iter, size_t steps)
{
if (iter->end)
return 0;
@@ -754,10 +760,10 @@ _Bool bm_iter_advance(struct bidimap_iter *iter, size_t steps)
if (steps == 0 || iter->index + steps >= iter->target->count)
return 0;
for (size_t i = 0; i < steps; i++)
bm_iter_next(iter);
hbm_iter_next(iter);
return 1;
}
_Bool bm_iter_rewind(struct bidimap_iter *iter, size_t steps)
_Bool hbm_iter_rewind(struct hashbidimap_iter *iter, size_t steps)
{
if (iter->start)
return 0;
@@ -769,46 +775,46 @@ _Bool bm_iter_rewind(struct bidimap_iter *iter, size_t steps)
if (steps == 0 || iter->index < steps)
return 0;
for (size_t i = 0; i < steps; i++)
bm_iter_prev(iter);
hbm_iter_prev(iter);
return 1;
}
_Bool bm_iter_go_to(struct bidimap_iter *iter, size_t index)
_Bool hbm_iter_go_to(struct hashbidimap_iter *iter, size_t index)
{
if (index >= iter->target->count)
return 0;
if (iter->index > index)
return bm_iter_rewind(iter, iter->index - index);
return hbm_iter_rewind(iter, iter->index - index);
else if (iter->index < index)
return bm_iter_advance(iter, index - iter->index);
return hbm_iter_advance(iter, index - iter->index);
return 1;
}
size_t bm_iter_key(struct bidimap_iter *iter)
size_t hbm_iter_key(struct hashbidimap_iter *iter)
{
if (bm_empty(iter->target))
if (hbm_empty(iter->target))
{
iter->target->flag = cmc_flags.EMPTY;
return (size_t){ 0 };
}
return iter->target->buffer[iter->cursor][0]->key;
}
size_t bm_iter_value(struct bidimap_iter *iter)
size_t hbm_iter_value(struct hashbidimap_iter *iter)
{
if (bm_empty(iter->target))
if (hbm_empty(iter->target))
{
iter->target->flag = cmc_flags.EMPTY;
return (size_t){ 0 };
}
return iter->target->buffer[iter->cursor][0]->value;
}
size_t bm_iter_index(struct bidimap_iter *iter)
size_t hbm_iter_index(struct hashbidimap_iter *iter)
{
return iter->index;
}
static struct bidimap_entry *bm_impl_new_entry(struct bidimap *_map_,
size_t key, size_t value)
static struct hashbidimap_entry *hbm_impl_new_entry(struct hashbidimap *_map_,
size_t key, size_t value)
{
struct bidimap_entry *entry =
_map_->alloc->malloc(sizeof(struct bidimap_entry));
struct hashbidimap_entry *entry =
_map_->alloc->malloc(sizeof(struct hashbidimap_entry));
if (!entry)
return ((void *)0);
entry->key = key;
@@ -819,12 +825,12 @@ static struct bidimap_entry *bm_impl_new_entry(struct bidimap *_map_,
entry->ref[1] = ((void *)0);
return entry;
}
static struct bidimap_entry **bm_impl_get_entry_by_key(struct bidimap *_map_,
size_t key)
static struct hashbidimap_entry **
hbm_impl_get_entry_by_key(struct hashbidimap *_map_, size_t key)
{
size_t hash = _map_->f_key->hash(key);
size_t pos = hash % _map_->capacity;
struct bidimap_entry *target = _map_->buffer[pos][0];
struct hashbidimap_entry *target = _map_->buffer[pos][0];
while (target != ((void *)0))
{
if (target != ((void *)1) && _map_->f_key->cmp(target->key, key) == 0)
@@ -834,12 +840,12 @@ static struct bidimap_entry **bm_impl_get_entry_by_key(struct bidimap *_map_,
}
return ((void *)0);
}
static struct bidimap_entry **bm_impl_get_entry_by_val(struct bidimap *_map_,
size_t val)
static struct hashbidimap_entry **
hbm_impl_get_entry_by_val(struct hashbidimap *_map_, size_t val)
{
size_t hash = _map_->f_val->hash(val);
size_t pos = hash % _map_->capacity;
struct bidimap_entry *target = _map_->buffer[pos][1];
struct hashbidimap_entry *target = _map_->buffer[pos][1];
while (target != ((void *)0))
{
if (target != ((void *)1) && _map_->f_val->cmp(target->value, val) == 0)
@@ -849,14 +855,16 @@ static struct bidimap_entry **bm_impl_get_entry_by_val(struct bidimap *_map_,
}
return ((void *)0);
}
static struct bidimap_entry **
bm_impl_add_entry_to_key(struct bidimap *_map_, struct bidimap_entry *entry)
static struct hashbidimap_entry **
hbm_impl_add_entry_to_key(struct hashbidimap *_map_,
struct hashbidimap_entry *entry)
{
struct bidimap_entry **to_return = ((void *)0);
struct hashbidimap_entry **to_return = ((void *)0);
size_t hash = _map_->f_key->hash(entry->key);
size_t original_pos = hash % _map_->capacity;
size_t pos = original_pos;
struct bidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][0]);
struct hashbidimap_entry **scan =
&(_map_->buffer[hash % _map_->capacity][0]);
if (*scan == ((void *)0))
{
*scan = entry;
@@ -886,7 +894,7 @@ bm_impl_add_entry_to_key(struct bidimap *_map_, struct bidimap_entry *entry)
entry->dist[0] = pos - original_pos;
original_pos = pos - tmp_dist;
entry->ref[0] = scan;
struct bidimap_entry *_tmp_ = *scan;
struct hashbidimap_entry *_tmp_ = *scan;
*scan = entry;
entry = _tmp_;
}
@@ -894,14 +902,16 @@ bm_impl_add_entry_to_key(struct bidimap *_map_, struct bidimap_entry *entry)
}
return ((void *)0);
}
static struct bidimap_entry **
bm_impl_add_entry_to_val(struct bidimap *_map_, struct bidimap_entry *entry)
static struct hashbidimap_entry **
hbm_impl_add_entry_to_val(struct hashbidimap *_map_,
struct hashbidimap_entry *entry)
{
struct bidimap_entry **to_return = ((void *)0);
struct hashbidimap_entry **to_return = ((void *)0);
size_t hash = _map_->f_val->hash(entry->value);
size_t original_pos = hash % _map_->capacity;
size_t pos = original_pos;
struct bidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][1]);
struct hashbidimap_entry **scan =
&(_map_->buffer[hash % _map_->capacity][1]);
if (*scan == ((void *)0))
{
*scan = entry;
@@ -931,7 +941,7 @@ bm_impl_add_entry_to_val(struct bidimap *_map_, struct bidimap_entry *entry)
entry->dist[1] = pos - original_pos;
original_pos = pos - tmp_dist;
entry->ref[1] = scan;
struct bidimap_entry *_tmp_ = *scan;
struct hashbidimap_entry *_tmp_ = *scan;
*scan = entry;
entry = _tmp_;
}
@@ -939,7 +949,7 @@ bm_impl_add_entry_to_val(struct bidimap *_map_, struct bidimap_entry *entry)
}
return ((void *)0);
}
static size_t bm_impl_calculate_size(size_t required)
static size_t hbm_impl_calculate_size(size_t required)
{
const size_t count =
sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]);
@@ -950,16 +960,16 @@ static size_t bm_impl_calculate_size(size_t required)
i++;
return cmc_hashtable_primes[i];
}
static struct bidimap_iter bm_impl_it_start(struct bidimap *_map_)
static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap *_map_)
{
struct bidimap_iter iter;
bm_iter_init(&iter, _map_);
struct hashbidimap_iter iter;
hbm_iter_init(&iter, _map_);
return iter;
}
static struct bidimap_iter bm_impl_it_end(struct bidimap *_map_)
static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap *_map_)
{
struct bidimap_iter iter;
bm_iter_init(&iter, _map_);
bm_iter_to_end(&iter);
struct hashbidimap_iter iter;
hbm_iter_init(&iter, _map_);
hbm_iter_to_end(&iter);
return iter;
}
-822
View File
@@ -1,822 +0,0 @@
#include "utl.c"
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/bidimap.c"
struct bidimap_fkey *bm_fkey = &(struct bidimap_fkey){ .cmp = cmc_size_cmp,
.cpy = NULL,
.str = cmc_size_str,
.free = NULL,
.hash = cmc_size_hash,
.pri = cmc_size_cmp };
struct bidimap_fval *bm_fval = &(struct bidimap_fval){ .cmp = cmc_size_cmp,
.cpy = NULL,
.str = cmc_size_str,
.free = NULL,
.hash = cmc_size_hash,
.pri = cmc_size_cmp };
struct bidimap_fkey *bm_fkey_counter = &(struct bidimap_fkey){ .cmp = k_c_cmp,
.cpy = k_c_cpy,
.str = k_c_str,
.free = k_c_free,
.hash = k_c_hash,
.pri = k_c_pri };
struct bidimap_fval *bm_fval_counter = &(struct bidimap_fval){ .cmp = v_c_cmp,
.cpy = v_c_cpy,
.str = v_c_str,
.free = v_c_free,
.hash = v_c_hash,
.pri = v_c_pri };
struct cmc_alloc_node *bm_alloc_node = &(struct cmc_alloc_node){
.malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free
};
CMC_CREATE_UNIT(BidiMap, true, {
CMC_CREATE_TEST(PFX##_new(), {
struct bidimap *map = bm_new(943722, 0.6, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(double, 0.6, map->load);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(ptr, bm_fkey, map->f_key);
cmc_assert_equals(ptr, bm_fval, map->f_val);
cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc);
cmc_assert_equals(ptr, NULL, map->callbacks);
cmc_assert_greater_equals(size_t, (943722 / 0.6), bm_capacity(map));
bm_free(map);
map = bm_new(100, 0.6, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < map->capacity; i++)
{
cmc_assert_equals(ptr, NULL, map->buffer[i][0]);
cmc_assert_equals(ptr, NULL, map->buffer[i][1]);
}
bm_free(map);
map = bm_new(0, 0.6, bm_fkey, bm_fval);
cmc_assert_equals(ptr, NULL, map);
map = bm_new(UINT64_MAX, 0.99, bm_fkey, bm_fval);
cmc_assert_equals(ptr, NULL, map);
map = bm_new(1000, 0.6, bm_fkey, NULL);
cmc_assert_equals(ptr, NULL, map);
map = bm_new(1000, 0.6, NULL, bm_fval);
cmc_assert_equals(ptr, NULL, map);
map = bm_new(1000, 0.6, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(PFX##_new_custom(), {
struct bidimap *map = bm_new_custom(943722, 0.6, bm_fkey, bm_fval,
bm_alloc_node, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(double, 0.6, map->load);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(ptr, bm_fkey, map->f_key);
cmc_assert_equals(ptr, bm_fval, map->f_val);
cmc_assert_equals(ptr, bm_alloc_node, map->alloc);
cmc_assert_equals(ptr, callbacks, map->callbacks);
cmc_assert_greater_equals(size_t, (943722 / 0.6), bm_capacity(map));
bm_free(map);
map = bm_new_custom(0, 0.6, bm_fkey, bm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = bm_new_custom(UINT64_MAX, 0.99, bm_fkey, bm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = bm_new_custom(1000, 0.6, bm_fkey, NULL, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = bm_new_custom(1000, 0.6, NULL, bm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = bm_new_custom(1000, 0.6, NULL, NULL, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(PFX##_clear(), {
k_total_free = 0;
v_total_free = 0;
struct bidimap *map =
bm_new(100, 0.6, bm_fkey_counter, bm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
bm_insert(map, i, i);
cmc_assert_equals(size_t, 1000, map->count);
map->flag = cmc_flags.ERROR;
bm_clear(map);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
bm_free(map);
k_total_free = 0;
v_total_free = 0;
});
CMC_CREATE_TEST(PFX##_free(), {
k_total_free = 0;
v_total_free = 0;
struct bidimap *map =
bm_new(100, 0.6, bm_fkey_counter, bm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
bm_insert(map, i, i);
cmc_assert_equals(size_t, 1000, map->count);
bm_free(map);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
map = bm_new(1000, 0.6, bm_fkey_counter, bm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
bm_free(map);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
k_total_free = 0;
v_total_free = 0;
});
CMC_CREATE_TEST(customize, {
struct bidimap *map =
bm_new_custom(100, 0.6, bm_fkey, bm_fval, NULL, NULL);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc);
cmc_assert_equals(ptr, NULL, map->callbacks);
bm_free(map);
struct cmc_alloc_node node;
node.malloc = malloc;
node.realloc = realloc;
node.free = free;
node.calloc = calloc;
map = bm_new_custom(100, 0.6, bm_fkey, bm_fval, &node, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, &node, map->alloc);
cmc_assert_equals(ptr, callbacks, map->callbacks);
bm_free(map);
});
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
struct bidimap *map = bm_new(1, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 10000; i++)
cmc_assert(bm_insert(map, i, i));
size_t sum = 0;
for (size_t i = 0; i < bm_capacity(map); i++)
{
if (map->buffer[i][0] && map->buffer[i][0] != CMC_ENTRY_DELETED)
{
sum += map->buffer[i][0]->key;
}
}
cmc_assert_equals(size_t, 50005000, sum);
bm_free(map);
});
CMC_CREATE_TEST(insert, {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(bm_insert(map, 1, 1));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert(bm_insert(map, 3, 3));
cmc_assert_equals(size_t, 3, bm_count(map));
bm_free(map);
});
CMC_CREATE_TEST(insert[duplicate], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(bm_insert(map, 1, 1));
cmc_assert(!bm_insert(map, 1, 1));
cmc_assert(!bm_insert(map, 2, 1));
cmc_assert(!bm_insert(map, 1, 2));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert_equals(size_t, 2, bm_count(map));
bm_free(map);
});
CMC_CREATE_TEST(insert[references], {
struct bidimap *map = bm_new(500, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 500; i++)
cmc_assert(bm_insert(map, i, i));
for (size_t i = 0; i < map->capacity; i++)
{
struct bidimap_entry *kentry = map->buffer[i][0];
struct bidimap_entry *ventry = map->buffer[i][1];
if (kentry && kentry != CMC_ENTRY_DELETED)
cmc_assert_equals(ptr, kentry, *(kentry->ref[0]));
if (ventry && ventry != CMC_ENTRY_DELETED)
cmc_assert_equals(ptr, ventry, *(ventry->ref[1]));
}
bm_free(map);
});
CMC_CREATE_TEST(insert[growth remove clear], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_equals(size_t, 1000, bm_count(map));
size_t j = 1;
while (!bm_empty(map))
{
if (bm_count(map) % 2 == 0)
cmc_assert(bm_remove_by_key(map, j++, NULL, NULL));
else
cmc_assert(bm_remove_by_val(map, j++, NULL, NULL));
}
cmc_assert_equals(size_t, 0, bm_count(map));
for (size_t i = 1; i <= 1000; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_equals(size_t, 1000, bm_count(map));
bm_clear(map);
cmc_assert_equals(size_t, 0, bm_count(map));
bm_free(map);
});
CMC_CREATE_TEST(insert[ftab hash calls], {
struct bidimap *map =
bm_new(100, 0.7, bm_fkey_counter, bm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
k_total_hash = 0;
v_total_hash = 0;
for (size_t i = 1; i <= 1000; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_greater_equals(int32_t, 1000, k_total_hash);
cmc_assert_greater_equals(int32_t, 1000, v_total_hash);
bm_free(map);
k_total_hash = 0;
v_total_hash = 0;
});
CMC_CREATE_TEST(update_key, {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_equals(size_t, 100, bm_count(map));
for (size_t i = 100; i > 0; i--)
cmc_assert(bm_update_key(map, i, i + 10));
cmc_assert_equals(size_t, 100, bm_count(map));
for (size_t i = 1; i <= 100; i++)
cmc_assert_equals(size_t, i + 10, bm_get_key(map, i));
cmc_assert_equals(size_t, 100, bm_count(map));
bm_free(map);
});
CMC_CREATE_TEST(update_key[empty], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, 0, bm_count(map));
cmc_assert(!bm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
bm_free(map);
});
CMC_CREATE_TEST(update_key[not_found duplicate], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(bm_insert(map, 1, 1));
cmc_assert_equals(size_t, 1, bm_count(map));
map->flag = cmc_flags.ERROR;
cmc_assert(bm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert(!bm_update_key(map, 2, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert(!bm_update_key(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
cmc_assert(!bm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
cmc_assert(bm_update_key(map, 2, 2));
bm_free(map);
});
CMC_CREATE_TEST(update_val, {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_equals(size_t, 100, bm_count(map));
for (size_t i = 100; i > 0; i--)
cmc_assert(bm_update_val(map, i, i + 10));
cmc_assert_equals(size_t, 100, bm_count(map));
for (size_t i = 1; i <= 100; i++)
cmc_assert_equals(size_t, i + 10, bm_get_val(map, i));
cmc_assert_equals(size_t, 100, bm_count(map));
bm_free(map);
});
CMC_CREATE_TEST(update_val[empty], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, 0, bm_count(map));
cmc_assert(!bm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
bm_free(map);
});
CMC_CREATE_TEST(update_val[not_found duplicate], {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(bm_insert(map, 1, 1));
cmc_assert_equals(size_t, 1, bm_count(map));
map->flag = cmc_flags.ERROR;
cmc_assert(bm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert(!bm_update_val(map, 2, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert(!bm_update_val(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
cmc_assert(!bm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
cmc_assert(bm_update_val(map, 2, 2));
bm_free(map);
});
CMC_CREATE_TEST(remove_by_key[cleanup custom], {
struct bidimap *map =
bm_new_custom(10000, 0.6, bm_fkey, bm_fval,
&(struct cmc_alloc_node){ .malloc = malloc,
.calloc = calloc,
.realloc = realloc,
.free = free },
&(struct cmc_callbacks){ 0 });
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(bm_insert(map, i, i));
}
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(bm_remove_by_key(map, i, NULL, NULL));
}
for (size_t i = 0; i < map->capacity; i++)
{
struct bidimap_entry *k = map->buffer[i][0];
struct bidimap_entry *v = map->buffer[i][1];
cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) &&
(v == NULL || v == CMC_ENTRY_DELETED));
}
bm_free(map);
});
CMC_CREATE_TEST(remove_by_val[cleanup custom], {
struct bidimap *map =
bm_new_custom(10000, 0.6, bm_fkey, bm_fval,
&(struct cmc_alloc_node){ .malloc = malloc,
.calloc = calloc,
.realloc = realloc,
.free = free },
&(struct cmc_callbacks){ 0 });
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(bm_insert(map, i, i));
}
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(bm_remove_by_val(map, i, NULL, NULL));
}
for (size_t i = 0; i < map->capacity; i++)
{
struct bidimap_entry *k = map->buffer[i][0];
struct bidimap_entry *v = map->buffer[i][1];
cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) &&
(v == NULL || v == CMC_ENTRY_DELETED));
}
bm_free(map);
});
CMC_CREATE_TEST(copy_of, {
struct bidimap *map1 = bm_new(100, 0.7, bm_fkey, bm_fval);
for (size_t i = 0; i < 100; i++)
cmc_assert(bm_insert(map1, i, i));
struct bidimap *map2 = bm_copy_of(map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert_equals(size_t, bm_count(map1), bm_count(map2));
for (size_t i = 0; i < 100; i++)
{
cmc_assert(bm_contains_key(map2, i) && bm_contains_key(map1, i));
cmc_assert(bm_contains_val(map2, i) && bm_contains_val(map1, i));
}
bm_free(map1);
bm_free(map2);
});
CMC_CREATE_TEST(equals, {
struct bidimap *map1 = bm_new(100, 0.7, bm_fkey, bm_fval);
struct bidimap *map2 = bm_new(1000, 0.9, bm_fkey, bm_fval);
for (size_t i = 0; i < 100; i++)
{
cmc_assert(bm_insert(map1, i, i));
cmc_assert(bm_insert(map2, 99 - i, 99 - i));
}
cmc_assert_not_equals(ptr, NULL, map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert_equals(size_t, bm_count(map1), bm_count(map2));
for (size_t i = 0; i < 100; i++)
{
cmc_assert(bm_contains_key(map2, i) && bm_contains_key(map1, i));
cmc_assert(bm_contains_val(map2, i) && bm_contains_val(map1, i));
}
bm_free(map1);
bm_free(map2);
});
CMC_CREATE_TEST(equals[from copy], {
struct bidimap *map1 = bm_new(100, 0.7, bm_fkey, bm_fval);
for (size_t i = 0; i < 100; i++)
cmc_assert(bm_insert(map1, i, i));
struct bidimap *map2 = bm_copy_of(map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert(bm_equals(map1, map2));
bm_free(map1);
bm_free(map2);
});
CMC_CREATE_TEST(flags, {
struct bidimap *map = bm_new(100, 0.7, bm_fkey, bm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// customize
bm_customize(map, &cmc_alloc_node_default,
&(struct cmc_callbacks){ 0 });
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// Insert
cmc_assert(bm_insert(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert(!bm_insert(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!bm_insert(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
// clear
bm_clear(map);
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// bm_update_key
cmc_assert(!bm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
cmc_assert(bm_insert(map, 1, 1));
cmc_assert(!bm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert(!bm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!bm_update_key(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
// clear
bm_clear(map);
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// bm_update_val
cmc_assert(!bm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
cmc_assert(bm_insert(map, 1, 1));
cmc_assert(!bm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_insert(map, 2, 2));
cmc_assert(!bm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!bm_update_val(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, bm_flag(map));
// remove_by_key
cmc_assert(bm_remove_by_key(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert(!bm_remove_by_key(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_remove_by_key(map, 2, NULL, NULL));
cmc_assert(!bm_remove_by_key(map, 2, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
// remove_by_val
cmc_assert(bm_insert(map, 1, 1) && bm_insert(map, 2, 2));
cmc_assert(bm_remove_by_val(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert(!bm_remove_by_val(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert(bm_remove_by_val(map, 2, NULL, NULL));
cmc_assert(!bm_remove_by_val(map, 2, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, bm_flag(map));
// get_key and get_val
cmc_assert(bm_insert(map, 2, 1));
cmc_assert_equals(size_t, 2, bm_get_key(map, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert_equals(size_t, 1, bm_get_val(map, 2));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert_equals(size_t, 0, bm_get_key(map, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert_equals(size_t, 0, bm_get_val(map, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
// contains_key
cmc_assert(bm_contains_key(map, 2));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// contains_val
map->flag = cmc_flags.ERROR;
cmc_assert(bm_contains_val(map, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
// copy_of
map->flag = cmc_flags.ERROR;
struct bidimap *map2 = bm_copy_of(map);
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map2));
size_t tmp = map->capacity;
map->capacity = 0;
struct bidimap *map3 = bm_copy_of(map);
cmc_assert_equals(ptr, NULL, map3);
cmc_assert_equals(int32_t, cmc_flags.ERROR, bm_flag(map));
map->capacity = tmp;
// equals
bm_get_key(map, 100);
bm_get_key(map2, 100);
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, bm_flag(map2));
map->flag = cmc_flags.ERROR;
cmc_assert(bm_equals(map, map2));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map));
cmc_assert_equals(int32_t, cmc_flags.OK, bm_flag(map2));
bm_free(map);
bm_free(map2);
});
CMC_CREATE_TEST(callbacks, {
struct bidimap *map =
bm_new_custom(100, 0.7, bm_fkey, bm_fval, NULL, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, callbacks, map->callbacks);
total_create = 0;
total_read = 0;
total_update = 0;
total_delete = 0;
total_resize = 0;
cmc_assert(bm_insert(map, 10, 10));
cmc_assert_equals(int32_t, 1, total_create);
cmc_assert(bm_update_key(map, 10, 5));
cmc_assert_equals(int32_t, 1, total_update);
cmc_assert(bm_update_val(map, 5, 5));
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert(bm_insert(map, 10, 10));
cmc_assert_equals(int32_t, 2, total_create);
cmc_assert(bm_remove_by_key(map, 5, NULL, NULL));
cmc_assert_equals(int32_t, 1, total_delete);
cmc_assert(bm_remove_by_val(map, 10, NULL, NULL));
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert(bm_insert(map, 1, 2));
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(size_t, 1, bm_get_key(map, 2));
cmc_assert_equals(int32_t, 1, total_read);
cmc_assert_equals(size_t, 2, bm_get_val(map, 1));
cmc_assert_equals(int32_t, 2, total_read);
cmc_assert(bm_resize(map, 1000));
cmc_assert_equals(int32_t, 1, total_resize);
cmc_assert(bm_resize(map, 200));
cmc_assert_equals(int32_t, 2, total_resize);
cmc_assert(bm_contains_key(map, 1));
cmc_assert_equals(int32_t, 3, total_read);
cmc_assert(bm_contains_val(map, 2));
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert_equals(int32_t, 2, total_resize);
bm_customize(map, NULL, NULL);
cmc_assert_equals(ptr, NULL, map->callbacks);
bm_clear(map);
cmc_assert(bm_insert(map, 10, 10));
cmc_assert(bm_update_key(map, 10, 5));
cmc_assert(bm_update_val(map, 5, 5));
cmc_assert(bm_insert(map, 10, 10));
cmc_assert(bm_remove_by_key(map, 5, NULL, NULL));
cmc_assert(bm_remove_by_val(map, 10, NULL, NULL));
cmc_assert(bm_insert(map, 1, 2));
cmc_assert_equals(size_t, 1, bm_get_key(map, 2));
cmc_assert_equals(size_t, 2, bm_get_val(map, 1));
cmc_assert(bm_resize(map, 1000));
cmc_assert(bm_resize(map, 200));
cmc_assert(bm_contains_key(map, 1));
cmc_assert(bm_contains_val(map, 2));
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert_equals(int32_t, 2, total_resize);
cmc_assert_equals(ptr, NULL, map->callbacks);
bm_free(map);
total_create = 0;
total_read = 0;
total_update = 0;
total_delete = 0;
total_resize = 0;
});
});
+822
View File
@@ -0,0 +1,822 @@
#include "utl.c"
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashbidimap.c"
struct hashbidimap_fkey *hbm_fkey = &(struct hashbidimap_fkey){ .cmp = cmc_size_cmp,
.cpy = NULL,
.str = cmc_size_str,
.free = NULL,
.hash = cmc_size_hash,
.pri = cmc_size_cmp };
struct hashbidimap_fval *hbm_fval = &(struct hashbidimap_fval){ .cmp = cmc_size_cmp,
.cpy = NULL,
.str = cmc_size_str,
.free = NULL,
.hash = cmc_size_hash,
.pri = cmc_size_cmp };
struct hashbidimap_fkey *hbm_fkey_counter = &(struct hashbidimap_fkey){ .cmp = k_c_cmp,
.cpy = k_c_cpy,
.str = k_c_str,
.free = k_c_free,
.hash = k_c_hash,
.pri = k_c_pri };
struct hashbidimap_fval *hbm_fval_counter = &(struct hashbidimap_fval){ .cmp = v_c_cmp,
.cpy = v_c_cpy,
.str = v_c_str,
.free = v_c_free,
.hash = v_c_hash,
.pri = v_c_pri };
struct cmc_alloc_node *hbm_alloc_node = &(struct cmc_alloc_node){
.malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free
};
CMC_CREATE_UNIT(HashBidiMap, true, {
CMC_CREATE_TEST(PFX##_new(), {
struct hashbidimap *map = hbm_new(943722, 0.6, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(double, 0.6, map->load);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(ptr, hbm_fkey, map->f_key);
cmc_assert_equals(ptr, hbm_fval, map->f_val);
cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc);
cmc_assert_equals(ptr, NULL, map->callbacks);
cmc_assert_greater_equals(size_t, (943722 / 0.6), hbm_capacity(map));
hbm_free(map);
map = hbm_new(100, 0.6, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < map->capacity; i++)
{
cmc_assert_equals(ptr, NULL, map->buffer[i][0]);
cmc_assert_equals(ptr, NULL, map->buffer[i][1]);
}
hbm_free(map);
map = hbm_new(0, 0.6, hbm_fkey, hbm_fval);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new(UINT64_MAX, 0.99, hbm_fkey, hbm_fval);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new(1000, 0.6, hbm_fkey, NULL);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new(1000, 0.6, NULL, hbm_fval);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new(1000, 0.6, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(PFX##_new_custom(), {
struct hashbidimap *map = hbm_new_custom(943722, 0.6, hbm_fkey, hbm_fval,
hbm_alloc_node, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(double, 0.6, map->load);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(ptr, hbm_fkey, map->f_key);
cmc_assert_equals(ptr, hbm_fval, map->f_val);
cmc_assert_equals(ptr, hbm_alloc_node, map->alloc);
cmc_assert_equals(ptr, callbacks, map->callbacks);
cmc_assert_greater_equals(size_t, (943722 / 0.6), hbm_capacity(map));
hbm_free(map);
map = hbm_new_custom(0, 0.6, hbm_fkey, hbm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new_custom(UINT64_MAX, 0.99, hbm_fkey, hbm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new_custom(1000, 0.6, hbm_fkey, NULL, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new_custom(1000, 0.6, NULL, hbm_fval, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
map = hbm_new_custom(1000, 0.6, NULL, NULL, NULL, NULL);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(PFX##_clear(), {
k_total_free = 0;
v_total_free = 0;
struct hashbidimap *map =
hbm_new(100, 0.6, hbm_fkey_counter, hbm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
hbm_insert(map, i, i);
cmc_assert_equals(size_t, 1000, map->count);
map->flag = cmc_flags.ERROR;
hbm_clear(map);
cmc_assert_equals(size_t, 0, map->count);
cmc_assert_equals(int32_t, cmc_flags.OK, map->flag);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
hbm_free(map);
k_total_free = 0;
v_total_free = 0;
});
CMC_CREATE_TEST(PFX##_free(), {
k_total_free = 0;
v_total_free = 0;
struct hashbidimap *map =
hbm_new(100, 0.6, hbm_fkey_counter, hbm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
hbm_insert(map, i, i);
cmc_assert_equals(size_t, 1000, map->count);
hbm_free(map);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
map = hbm_new(1000, 0.6, hbm_fkey_counter, hbm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
hbm_free(map);
cmc_assert_equals(int32_t, 1000, k_total_free);
cmc_assert_equals(int32_t, 1000, v_total_free);
k_total_free = 0;
v_total_free = 0;
});
CMC_CREATE_TEST(customize, {
struct hashbidimap *map =
hbm_new_custom(100, 0.6, hbm_fkey, hbm_fval, NULL, NULL);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc);
cmc_assert_equals(ptr, NULL, map->callbacks);
hbm_free(map);
struct cmc_alloc_node node;
node.malloc = malloc;
node.realloc = realloc;
node.free = free;
node.calloc = calloc;
map = hbm_new_custom(100, 0.6, hbm_fkey, hbm_fval, &node, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, &node, map->alloc);
cmc_assert_equals(ptr, callbacks, map->callbacks);
hbm_free(map);
});
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
struct hashbidimap *map = hbm_new(1, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 10000; i++)
cmc_assert(hbm_insert(map, i, i));
size_t sum = 0;
for (size_t i = 0; i < hbm_capacity(map); i++)
{
if (map->buffer[i][0] && map->buffer[i][0] != CMC_ENTRY_DELETED)
{
sum += map->buffer[i][0]->key;
}
}
cmc_assert_equals(size_t, 50005000, sum);
hbm_free(map);
});
CMC_CREATE_TEST(insert, {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert(hbm_insert(map, 3, 3));
cmc_assert_equals(size_t, 3, hbm_count(map));
hbm_free(map);
});
CMC_CREATE_TEST(insert[duplicate], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert(!hbm_insert(map, 1, 1));
cmc_assert(!hbm_insert(map, 2, 1));
cmc_assert(!hbm_insert(map, 1, 2));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert_equals(size_t, 2, hbm_count(map));
hbm_free(map);
});
CMC_CREATE_TEST(insert[references], {
struct hashbidimap *map = hbm_new(500, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 500; i++)
cmc_assert(hbm_insert(map, i, i));
for (size_t i = 0; i < map->capacity; i++)
{
struct hashbidimap_entry *kentry = map->buffer[i][0];
struct hashbidimap_entry *ventry = map->buffer[i][1];
if (kentry && kentry != CMC_ENTRY_DELETED)
cmc_assert_equals(ptr, kentry, *(kentry->ref[0]));
if (ventry && ventry != CMC_ENTRY_DELETED)
cmc_assert_equals(ptr, ventry, *(ventry->ref[1]));
}
hbm_free(map);
});
CMC_CREATE_TEST(insert[growth remove clear], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 1000; i++)
cmc_assert(hbm_insert(map, i, i));
cmc_assert_equals(size_t, 1000, hbm_count(map));
size_t j = 1;
while (!hbm_empty(map))
{
if (hbm_count(map) % 2 == 0)
cmc_assert(hbm_remove_by_key(map, j++, NULL, NULL));
else
cmc_assert(hbm_remove_by_val(map, j++, NULL, NULL));
}
cmc_assert_equals(size_t, 0, hbm_count(map));
for (size_t i = 1; i <= 1000; i++)
cmc_assert(hbm_insert(map, i, i));
cmc_assert_equals(size_t, 1000, hbm_count(map));
hbm_clear(map);
cmc_assert_equals(size_t, 0, hbm_count(map));
hbm_free(map);
});
CMC_CREATE_TEST(insert[ftab hash calls], {
struct hashbidimap *map =
hbm_new(100, 0.7, hbm_fkey_counter, hbm_fval_counter);
cmc_assert_not_equals(ptr, NULL, map);
k_total_hash = 0;
v_total_hash = 0;
for (size_t i = 1; i <= 1000; i++)
cmc_assert(hbm_insert(map, i, i));
cmc_assert_greater_equals(int32_t, 1000, k_total_hash);
cmc_assert_greater_equals(int32_t, 1000, v_total_hash);
hbm_free(map);
k_total_hash = 0;
v_total_hash = 0;
});
CMC_CREATE_TEST(update_key, {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hbm_insert(map, i, i));
cmc_assert_equals(size_t, 100, hbm_count(map));
for (size_t i = 100; i > 0; i--)
cmc_assert(hbm_update_key(map, i, i + 10));
cmc_assert_equals(size_t, 100, hbm_count(map));
for (size_t i = 1; i <= 100; i++)
cmc_assert_equals(size_t, i + 10, hbm_get_key(map, i));
cmc_assert_equals(size_t, 100, hbm_count(map));
hbm_free(map);
});
CMC_CREATE_TEST(update_key[empty], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, 0, hbm_count(map));
cmc_assert(!hbm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
hbm_free(map);
});
CMC_CREATE_TEST(update_key[not_found duplicate], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert_equals(size_t, 1, hbm_count(map));
map->flag = cmc_flags.ERROR;
cmc_assert(hbm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert(!hbm_update_key(map, 2, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert(!hbm_update_key(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
cmc_assert(!hbm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
cmc_assert(hbm_update_key(map, 2, 2));
hbm_free(map);
});
CMC_CREATE_TEST(update_val, {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hbm_insert(map, i, i));
cmc_assert_equals(size_t, 100, hbm_count(map));
for (size_t i = 100; i > 0; i--)
cmc_assert(hbm_update_val(map, i, i + 10));
cmc_assert_equals(size_t, 100, hbm_count(map));
for (size_t i = 1; i <= 100; i++)
cmc_assert_equals(size_t, i + 10, hbm_get_val(map, i));
cmc_assert_equals(size_t, 100, hbm_count(map));
hbm_free(map);
});
CMC_CREATE_TEST(update_val[empty], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, 0, hbm_count(map));
cmc_assert(!hbm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
hbm_free(map);
});
CMC_CREATE_TEST(update_val[not_found duplicate], {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert_equals(size_t, 1, hbm_count(map));
map->flag = cmc_flags.ERROR;
cmc_assert(hbm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert(!hbm_update_val(map, 2, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert(!hbm_update_val(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
cmc_assert(!hbm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
cmc_assert(hbm_update_val(map, 2, 2));
hbm_free(map);
});
CMC_CREATE_TEST(remove_by_key[cleanup custom], {
struct hashbidimap *map =
hbm_new_custom(10000, 0.6, hbm_fkey, hbm_fval,
&(struct cmc_alloc_node){ .malloc = malloc,
.calloc = calloc,
.realloc = realloc,
.free = free },
&(struct cmc_callbacks){ 0 });
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(hbm_insert(map, i, i));
}
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(hbm_remove_by_key(map, i, NULL, NULL));
}
for (size_t i = 0; i < map->capacity; i++)
{
struct hashbidimap_entry *k = map->buffer[i][0];
struct hashbidimap_entry *v = map->buffer[i][1];
cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) &&
(v == NULL || v == CMC_ENTRY_DELETED));
}
hbm_free(map);
});
CMC_CREATE_TEST(remove_by_val[cleanup custom], {
struct hashbidimap *map =
hbm_new_custom(10000, 0.6, hbm_fkey, hbm_fval,
&(struct cmc_alloc_node){ .malloc = malloc,
.calloc = calloc,
.realloc = realloc,
.free = free },
&(struct cmc_callbacks){ 0 });
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(hbm_insert(map, i, i));
}
for (size_t i = 0; i < 10000; i++)
{
cmc_assert(hbm_remove_by_val(map, i, NULL, NULL));
}
for (size_t i = 0; i < map->capacity; i++)
{
struct hashbidimap_entry *k = map->buffer[i][0];
struct hashbidimap_entry *v = map->buffer[i][1];
cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) &&
(v == NULL || v == CMC_ENTRY_DELETED));
}
hbm_free(map);
});
CMC_CREATE_TEST(copy_of, {
struct hashbidimap *map1 = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
for (size_t i = 0; i < 100; i++)
cmc_assert(hbm_insert(map1, i, i));
struct hashbidimap *map2 = hbm_copy_of(map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert_equals(size_t, hbm_count(map1), hbm_count(map2));
for (size_t i = 0; i < 100; i++)
{
cmc_assert(hbm_contains_key(map2, i) && hbm_contains_key(map1, i));
cmc_assert(hbm_contains_val(map2, i) && hbm_contains_val(map1, i));
}
hbm_free(map1);
hbm_free(map2);
});
CMC_CREATE_TEST(equals, {
struct hashbidimap *map1 = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
struct hashbidimap *map2 = hbm_new(1000, 0.9, hbm_fkey, hbm_fval);
for (size_t i = 0; i < 100; i++)
{
cmc_assert(hbm_insert(map1, i, i));
cmc_assert(hbm_insert(map2, 99 - i, 99 - i));
}
cmc_assert_not_equals(ptr, NULL, map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert_equals(size_t, hbm_count(map1), hbm_count(map2));
for (size_t i = 0; i < 100; i++)
{
cmc_assert(hbm_contains_key(map2, i) && hbm_contains_key(map1, i));
cmc_assert(hbm_contains_val(map2, i) && hbm_contains_val(map1, i));
}
hbm_free(map1);
hbm_free(map2);
});
CMC_CREATE_TEST(equals[from copy], {
struct hashbidimap *map1 = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
for (size_t i = 0; i < 100; i++)
cmc_assert(hbm_insert(map1, i, i));
struct hashbidimap *map2 = hbm_copy_of(map1);
cmc_assert_not_equals(ptr, NULL, map2);
cmc_assert(hbm_equals(map1, map2));
hbm_free(map1);
hbm_free(map2);
});
CMC_CREATE_TEST(flags, {
struct hashbidimap *map = hbm_new(100, 0.7, hbm_fkey, hbm_fval);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// customize
hbm_customize(map, &cmc_alloc_node_default,
&(struct cmc_callbacks){ 0 });
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// Insert
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert(!hbm_insert(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!hbm_insert(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
// clear
hbm_clear(map);
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// hbm_update_key
cmc_assert(!hbm_update_key(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert(!hbm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert(!hbm_update_key(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!hbm_update_key(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
// clear
hbm_clear(map);
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// hbm_update_val
cmc_assert(!hbm_update_val(map, 1, 1));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
cmc_assert(hbm_insert(map, 1, 1));
cmc_assert(!hbm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_insert(map, 2, 2));
cmc_assert(!hbm_update_val(map, 2, 1));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert(!hbm_update_val(map, 1, 2));
cmc_assert_equals(int32_t, cmc_flags.DUPLICATE, hbm_flag(map));
// remove_by_key
cmc_assert(hbm_remove_by_key(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert(!hbm_remove_by_key(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_remove_by_key(map, 2, NULL, NULL));
cmc_assert(!hbm_remove_by_key(map, 2, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
// remove_by_val
cmc_assert(hbm_insert(map, 1, 1) && hbm_insert(map, 2, 2));
cmc_assert(hbm_remove_by_val(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert(!hbm_remove_by_val(map, 1, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert(hbm_remove_by_val(map, 2, NULL, NULL));
cmc_assert(!hbm_remove_by_val(map, 2, NULL, NULL));
cmc_assert_equals(int32_t, cmc_flags.EMPTY, hbm_flag(map));
// get_key and get_val
cmc_assert(hbm_insert(map, 2, 1));
cmc_assert_equals(size_t, 2, hbm_get_key(map, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert_equals(size_t, 1, hbm_get_val(map, 2));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert_equals(size_t, 0, hbm_get_key(map, 2));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
map->flag = cmc_flags.ERROR;
cmc_assert_equals(size_t, 0, hbm_get_val(map, 1));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
// contains_key
cmc_assert(hbm_contains_key(map, 2));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// contains_val
map->flag = cmc_flags.ERROR;
cmc_assert(hbm_contains_val(map, 1));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
// copy_of
map->flag = cmc_flags.ERROR;
struct hashbidimap *map2 = hbm_copy_of(map);
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map2));
size_t tmp = map->capacity;
map->capacity = 0;
struct hashbidimap *map3 = hbm_copy_of(map);
cmc_assert_equals(ptr, NULL, map3);
cmc_assert_equals(int32_t, cmc_flags.ERROR, hbm_flag(map));
map->capacity = tmp;
// equals
hbm_get_key(map, 100);
hbm_get_key(map2, 100);
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map));
cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hbm_flag(map2));
map->flag = cmc_flags.ERROR;
cmc_assert(hbm_equals(map, map2));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map));
cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map2));
hbm_free(map);
hbm_free(map2);
});
CMC_CREATE_TEST(callbacks, {
struct hashbidimap *map =
hbm_new_custom(100, 0.7, hbm_fkey, hbm_fval, NULL, callbacks);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, callbacks, map->callbacks);
total_create = 0;
total_read = 0;
total_update = 0;
total_delete = 0;
total_resize = 0;
cmc_assert(hbm_insert(map, 10, 10));
cmc_assert_equals(int32_t, 1, total_create);
cmc_assert(hbm_update_key(map, 10, 5));
cmc_assert_equals(int32_t, 1, total_update);
cmc_assert(hbm_update_val(map, 5, 5));
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert(hbm_insert(map, 10, 10));
cmc_assert_equals(int32_t, 2, total_create);
cmc_assert(hbm_remove_by_key(map, 5, NULL, NULL));
cmc_assert_equals(int32_t, 1, total_delete);
cmc_assert(hbm_remove_by_val(map, 10, NULL, NULL));
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert(hbm_insert(map, 1, 2));
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(size_t, 1, hbm_get_key(map, 2));
cmc_assert_equals(int32_t, 1, total_read);
cmc_assert_equals(size_t, 2, hbm_get_val(map, 1));
cmc_assert_equals(int32_t, 2, total_read);
cmc_assert(hbm_resize(map, 1000));
cmc_assert_equals(int32_t, 1, total_resize);
cmc_assert(hbm_resize(map, 200));
cmc_assert_equals(int32_t, 2, total_resize);
cmc_assert(hbm_contains_key(map, 1));
cmc_assert_equals(int32_t, 3, total_read);
cmc_assert(hbm_contains_val(map, 2));
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert_equals(int32_t, 2, total_resize);
hbm_customize(map, NULL, NULL);
cmc_assert_equals(ptr, NULL, map->callbacks);
hbm_clear(map);
cmc_assert(hbm_insert(map, 10, 10));
cmc_assert(hbm_update_key(map, 10, 5));
cmc_assert(hbm_update_val(map, 5, 5));
cmc_assert(hbm_insert(map, 10, 10));
cmc_assert(hbm_remove_by_key(map, 5, NULL, NULL));
cmc_assert(hbm_remove_by_val(map, 10, NULL, NULL));
cmc_assert(hbm_insert(map, 1, 2));
cmc_assert_equals(size_t, 1, hbm_get_key(map, 2));
cmc_assert_equals(size_t, 2, hbm_get_val(map, 1));
cmc_assert(hbm_resize(map, 1000));
cmc_assert(hbm_resize(map, 200));
cmc_assert(hbm_contains_key(map, 1));
cmc_assert(hbm_contains_val(map, 2));
cmc_assert_equals(int32_t, 3, total_create);
cmc_assert_equals(int32_t, 4, total_read);
cmc_assert_equals(int32_t, 2, total_update);
cmc_assert_equals(int32_t, 2, total_delete);
cmc_assert_equals(int32_t, 2, total_resize);
cmc_assert_equals(ptr, NULL, map->callbacks);
hbm_free(map);
total_create = 0;
total_read = 0;
total_update = 0;
total_delete = 0;
total_resize = 0;
});
});