diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3d6c5f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +# This file is useful to format all the source files and header in this library using clang-format + +.PHONY +main: + clang-format --style=file -i ./src/cmc/*.h diff --git a/TODO b/TODO index 6dc82c1..f6c9df0 100644 --- a/TODO +++ b/TODO @@ -8,12 +8,13 @@ TODO [/] Tests [/] Documentation +[/] Add Function Tables that contains data type functions + (compare, copy, display, free, hash, priority) +[/] Add error codes that can be accessed from the collection's struct #!! Medium Priority -------------------------------------------------------------------------------- [/] Callback utility -[ ] Add interface that contains data type functions - (compare, copy, display, free, hash, priority) [ ] Add to iterators struct [ ] get_value [ ] get_index diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index efbb27b..4b8991f 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -56,16 +56,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ @@ -136,10 +151,9 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " "capacity:%" PRIuMAX ", " "count:%" PRIuMAX ", " "load:%lf, " - "key_cmp:%p, " - "val_cmp:%p, " - "key_hash:%p, " - "val_hash:%p, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " "alloc:%p, " "callbacks:%p }"; @@ -191,29 +205,27 @@ struct cmc_callbacks_bidimap /* Load factor in range (0.0, 1.0) */ \ double load; \ \ - /* Key comparison function */ \ - int (*key_cmp)(K, K); \ + /* Flags indicating errors or success */ \ + int flag; \ \ - /* Value comparison function */ \ - int (*val_cmp)(V, V); \ + /* Key function table */ \ + struct SNAME##_ftab_key *f_key; \ \ - /* Key hash function */ \ - size_t (*key_hash)(K); \ - \ - /* Value hash function */ \ - size_t (*val_hash)(V); \ - \ - /* Function that returns an iterator to the start of the bidimap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the bidimap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ + /* Value function table */ \ + struct SNAME##_ftab_val *f_val; \ \ /* Custom allocation functions */ \ struct cmc_alloc_node *alloc; \ \ /* Custom callback functions */ \ struct cmc_callbacks_bidimap *callbacks; \ + \ + /* Methods */ \ + /* Function that returns an iterator to the start of the bidimap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the bidimap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ }; \ \ /* BidiMap Entry */ \ @@ -234,6 +246,50 @@ struct cmc_callbacks_bidimap size_t val_dist; \ }; \ \ + /* Key struct function table */ \ + struct SNAME##_ftab_key \ + { \ + /* Comparator function */ \ + int (*cmp)(K, K); \ + \ + /* Copy function */ \ + K (*cpy)(K); \ + \ + /* To string function */ \ + bool (*str)(FILE *, K); \ + \ + /* Free from memory function */ \ + void (*free)(K); \ + \ + /* Hash function */ \ + size_t (*hash)(K); \ + \ + /* Priority function */ \ + int (*pri)(K, K); \ + }; \ + \ + /* Value struct function table */ \ + struct SNAME##_ftab_val \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + K (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ /* BidiMap Iterator */ \ struct SNAME##_iter \ { \ @@ -262,15 +318,14 @@ struct cmc_callbacks_bidimap /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ struct SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)); \ + struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val); \ struct SNAME *PFX##_new_custom( \ - size_t capacity, double load, int (*key_cmp)(K, K), \ - size_t (*key_hash)(K), int (*val_cmp)(V, V), size_t (*val_hash)(V), \ - struct cmc_alloc_node *alloc, \ + size_t capacity, double load, struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_bidimap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_clear(struct SNAME *_map_); \ + void PFX##_free(struct SNAME *_map_); \ /* Customization of Allocation and Callbacks */ \ void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_bidimap *callbacks); \ @@ -297,10 +352,10 @@ struct cmc_callbacks_bidimap double PFX##_load(struct SNAME *_map_); \ /* Collection Utility */ \ bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_); \ bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_); \ struct cmc_string PFX##_to_string(struct SNAME *_map_); \ + bool PFX##_print(struct SNAME *_map_, FILE *fptr); \ \ /* Iterator Functions */ \ /* Iterator Allocation and Deallocation */ \ @@ -345,8 +400,8 @@ struct cmc_callbacks_bidimap static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ \ struct SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)) \ + struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val) \ { \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ @@ -380,24 +435,21 @@ struct cmc_callbacks_bidimap _map_->count = 0; \ _map_->capacity = real_capacity; \ _map_->load = load; \ - _map_->key_cmp = key_cmp; \ - _map_->val_cmp = val_cmp; \ - _map_->key_hash = key_hash; \ - _map_->val_hash = val_hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ + _map_->flag = cmc_flags.OK; \ + _map_->f_key = f_key; \ + _map_->f_val = f_val; \ _map_->alloc = alloc; \ _map_->callbacks = NULL; \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ \ return _map_; \ } \ \ struct SNAME *PFX##_new_custom( \ - size_t capacity, double load, int (*key_cmp)(K, K), \ - size_t (*key_hash)(K), int (*val_cmp)(V, V), size_t (*val_hash)(V), \ - struct cmc_alloc_node *alloc, struct cmc_callbacks_bidimap *callbacks) \ + size_t capacity, double load, struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_bidimap *callbacks) \ { \ if (capacity == 0 || load <= 0 || load >= 1) \ return NULL; \ @@ -432,21 +484,18 @@ struct cmc_callbacks_bidimap _map_->count = 0; \ _map_->capacity = real_capacity; \ _map_->load = load; \ - _map_->key_cmp = key_cmp; \ - _map_->val_cmp = val_cmp; \ - _map_->key_hash = key_hash; \ - _map_->val_hash = val_hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ + _map_->f_key = f_key; \ + _map_->f_val = f_val; \ + _map_->flag = cmc_flags.OK; \ _map_->alloc = alloc; \ _map_->callbacks = callbacks; \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ \ return _map_; \ } \ \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + void PFX##_clear(struct SNAME *_map_) \ { \ for (size_t i = 0; i < _map_->capacity; i++) \ { \ @@ -454,8 +503,10 @@ struct cmc_callbacks_bidimap \ if (entry && entry != CMC_ENTRY_DELETED) \ { \ - if (deallocator) \ - deallocator(entry->key, entry->value); \ + if (_map_->f_key->free) \ + _map_->f_key->free(entry->key); \ + if (_map_->f_val->free) \ + _map_->f_val->free(entry->value); \ \ _map_->alloc->free(entry); \ } \ @@ -465,11 +516,12 @@ struct cmc_callbacks_bidimap } \ \ _map_->count = 0; \ + _map_->flag = cmc_flags.OK; \ } \ \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + void PFX##_free(struct SNAME *_map_) \ { \ - PFX##_clear(_map_, deallocator); \ + PFX##_clear(_map_); \ \ _map_->alloc->free(_map_->key_buffer); \ _map_->alloc->free(_map_->val_buffer); \ @@ -484,6 +536,8 @@ struct cmc_callbacks_bidimap \ if (callbacks) \ _map_->callbacks = callbacks; \ + \ + _map_->flag = cmc_flags.OK; \ } \ \ bool PFX##_insert(struct SNAME *_map_, K key, V value) \ @@ -496,7 +550,11 @@ struct cmc_callbacks_bidimap \ if (PFX##_impl_get_entry_by_key(_map_, key) != NULL || \ PFX##_impl_get_entry_by_val(_map_, value) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ + \ return false; \ + } \ \ struct SNAME##_entry *entry = PFX##_impl_new_entry(_map_, key, value); \ \ @@ -514,10 +572,13 @@ struct cmc_callbacks_bidimap \ _map_->alloc->free(entry); \ \ + _map_->flag = cmc_flags.ERROR; \ + \ return false; \ } \ \ _map_->count++; \ + _map_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -525,16 +586,25 @@ struct cmc_callbacks_bidimap bool PFX##_update_key(struct SNAME *_map_, K key, K new_key) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **entry = \ PFX##_impl_get_entry_by_key(_map_, key); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ - if (PFX##_contains_key(_map_, new_key)) \ + if (PFX##_impl_get_entry_by_key(_map_, new_key) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ return false; \ + } \ \ struct SNAME##_entry *to_add = *entry; \ K tmp_key = to_add->key; \ @@ -547,25 +617,37 @@ struct cmc_callbacks_bidimap to_add->key = tmp_key; \ *entry = to_add; \ \ + _map_->flag = cmc_flags.ERROR; \ return false; \ } \ \ + _map_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_update_key_by_val(struct SNAME *_map_, V val, K new_key) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **entry = \ PFX##_impl_get_entry_by_val(_map_, val); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ - if (PFX##_contains_key(_map_, new_key)) \ + if (PFX##_impl_get_entry_by_key(_map_, new_key) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ return false; \ + } \ \ struct SNAME##_entry *to_add = *entry; \ K tmp_key = to_add->key; \ @@ -578,25 +660,37 @@ struct cmc_callbacks_bidimap to_add->key = tmp_key; \ *entry = to_add; \ \ + _map_->flag = cmc_flags.ERROR; \ return false; \ } \ \ + _map_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_update_val(struct SNAME *_map_, V val, V new_val) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **entry = \ PFX##_impl_get_entry_by_val(_map_, val); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ - if (PFX##_contains_val(_map_, new_val)) \ + if (PFX##_impl_get_entry_by_val(_map_, new_val) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ return false; \ + } \ \ struct SNAME##_entry *to_add = *entry; \ V tmp_val = to_add->value; \ @@ -609,25 +703,37 @@ struct cmc_callbacks_bidimap to_add->value = tmp_val; \ *entry = to_add; \ \ + _map_->flag = cmc_flags.ERROR; \ return false; \ } \ \ + _map_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_update_val_by_key(struct SNAME *_map_, K key, V new_val) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **entry = \ PFX##_impl_get_entry_by_key(_map_, key); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ - if (PFX##_contains_val(_map_, new_val)) \ + if (PFX##_impl_get_entry_by_val(_map_, new_val) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ return false; \ + } \ \ struct SNAME##_entry *to_add = *entry; \ V tmp_val = to_add->value; \ @@ -640,9 +746,12 @@ struct cmc_callbacks_bidimap to_add->value = tmp_val; \ *entry = to_add; \ \ + _map_->flag = cmc_flags.ERROR; \ return false; \ } \ \ + _map_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ @@ -650,22 +759,34 @@ struct cmc_callbacks_bidimap V *out_val) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **key_entry, **val_entry; \ \ key_entry = PFX##_impl_get_entry_by_key(_map_, key); \ \ if (!key_entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ val_entry = PFX##_impl_get_entry_by_val(_map_, (*key_entry)->value); \ \ if (!val_entry) \ + { \ + _map_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (*val_entry != *key_entry) \ + { \ + _map_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (out_key) \ *out_key = (*key_entry)->key; \ @@ -678,6 +799,7 @@ struct cmc_callbacks_bidimap *val_entry = CMC_ENTRY_DELETED; \ \ _map_->count--; \ + _map_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -686,22 +808,34 @@ struct cmc_callbacks_bidimap V *out_val) \ { \ if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ struct SNAME##_entry **key_entry, **val_entry; \ \ val_entry = PFX##_impl_get_entry_by_val(_map_, val); \ \ if (!val_entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ key_entry = PFX##_impl_get_entry_by_key(_map_, (*val_entry)->key); \ \ if (!key_entry) \ + { \ + _map_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (*val_entry != *key_entry) \ + { \ + _map_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (out_key) \ *out_key = (*val_entry)->key; \ @@ -714,6 +848,7 @@ struct cmc_callbacks_bidimap *val_entry = CMC_ENTRY_DELETED; \ \ _map_->count--; \ + _map_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -724,7 +859,10 @@ struct cmc_callbacks_bidimap PFX##_impl_get_entry_by_val(_map_, val); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return (V){ 0 }; \ + } \ \ return (*entry)->key; \ } \ @@ -735,7 +873,10 @@ struct cmc_callbacks_bidimap PFX##_impl_get_entry_by_key(_map_, key); \ \ if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ return (V){ 0 }; \ + } \ \ return (*entry)->value; \ } \ @@ -786,21 +927,33 @@ struct cmc_callbacks_bidimap \ /* Prevent integer overflow */ \ if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ + { \ + _map_->flag = cmc_flags.ERROR; \ + \ return false; \ + } \ \ /* Calculate required capacity based on the prime numbers */ \ size_t new_cap = PFX##_impl_calculate_size(capacity); \ \ /* Not possible to shrink with current available prime numbers */ \ if (new_cap < PFX##_count(_map_) / PFX##_load(_map_)) \ - return false; \ + { \ + _map_->flag = cmc_flags.ERROR; \ \ - struct SNAME *_new_map_ = PFX##_new_custom( \ - capacity, PFX##_load(_map_), _map_->key_cmp, _map_->key_hash, \ - _map_->val_cmp, _map_->val_hash, _map_->alloc, _map_->callbacks); \ + return false; \ + } \ + \ + struct SNAME *_new_map_ = \ + PFX##_new_custom(capacity, PFX##_load(_map_), _map_->f_key, \ + _map_->f_val, _map_->alloc, _map_->callbacks); \ \ if (!_new_map_) \ + { \ + _map_->flag = cmc_flags.ALLOC; \ + \ return false; \ + } \ \ for (size_t i = 0; i < _map_->capacity; i++) \ { \ @@ -819,6 +972,8 @@ struct cmc_callbacks_bidimap _map_->alloc->free(_new_map_->val_buffer); \ _map_->alloc->free(_new_map_); \ \ + _map_->flag = cmc_flags.ERROR; \ + \ return false; \ } \ \ @@ -832,6 +987,8 @@ struct cmc_callbacks_bidimap _map_->alloc->free(_new_map_->val_buffer); \ _map_->alloc->free(_new_map_); \ \ + _map_->flag = cmc_flags.ERROR; \ + \ return false; \ } \ \ @@ -849,14 +1006,12 @@ struct cmc_callbacks_bidimap return true; \ } \ \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_) \ { \ /* TODO this function can be optimized */ \ - struct SNAME *result = \ - PFX##_new_custom(PFX##_capacity(_map_), PFX##_load(_map_), \ - _map_->key_cmp, _map_->key_hash, _map_->val_cmp, \ - _map_->val_hash, _map_->alloc, _map_->callbacks); \ + struct SNAME *result = PFX##_new_custom( \ + PFX##_capacity(_map_), PFX##_load(_map_), _map_->f_key, \ + _map_->f_val, _map_->alloc, _map_->callbacks); \ \ for (size_t i = 0; i < _map_->capacity; i++) \ { \ @@ -867,16 +1022,17 @@ struct cmc_callbacks_bidimap K tmp_key; \ V tmp_val; \ \ - if (key_copy_func) \ - tmp_key = key_copy_func(scan->key); \ + if (_map_->f_key->cpy) \ + tmp_key = _map_->f_key->cpy(scan->key); \ else \ tmp_key = scan->key; \ \ - if (value_copy_func) \ - tmp_val = value_copy_func(scan->value); \ + if (_map_->f_val->cpy) \ + tmp_val = _map_->f_val->cpy(scan->value); \ else \ tmp_val = scan->value; \ \ + /* TODO should this be checked for failures? */ \ PFX##_insert(result, tmp_key, tmp_val); \ } \ } \ @@ -915,7 +1071,7 @@ struct cmc_callbacks_bidimap if (!entry_B) \ return false; \ \ - if (_mapA_->val_cmp((*entry_B)->value, scan->value) != 0) \ + if (_mapA_->f_val->cmp((*entry_B)->value, scan->value) != 0) \ return false; \ } \ } \ @@ -928,18 +1084,29 @@ struct cmc_callbacks_bidimap struct cmc_string str; \ struct SNAME *m_ = _map_; \ \ - int n = \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, #SNAME, \ - #K, #V, m_, m_->key_buffer, m_->val_buffer, m_->capacity, \ - m_->count, m_->load, m_->key_cmp, m_->val_cmp, \ - m_->key_hash, m_->val_hash, m_->alloc, m_->callbacks); \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \ + #SNAME, #K, #V, m_, m_->key_buffer, m_->val_buffer, \ + m_->capacity, m_->count, m_->load, m_->f_key, \ + m_->f_val, m_->alloc, m_->callbacks); \ \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){ 0 }; \ + return n >= 0 ? str : (struct cmc_string){ 0 }; \ + } \ \ - str.s[n] = '\0'; \ + bool PFX##_print(struct SNAME *_map_, FILE *fptr) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *target = _map_->key_buffer[i]; \ \ - return str; \ + if (target && target != CMC_ENTRY_DELETED) \ + { \ + if (!_map_->f_key->str(fptr, target->key) || \ + !_map_->f_val->str(fptr, target->value)) \ + return false; \ + } \ + } \ + \ + return true; \ } \ \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ @@ -1184,7 +1351,7 @@ struct cmc_callbacks_bidimap static struct SNAME##_entry **PFX##_impl_get_entry_by_key( \ struct SNAME *_map_, K key) \ { \ - size_t hash = _map_->key_hash(key); \ + size_t hash = _map_->f_key->hash(key); \ size_t pos = hash % _map_->capacity; \ \ struct SNAME##_entry *target = _map_->key_buffer[pos]; \ @@ -1192,7 +1359,7 @@ struct cmc_callbacks_bidimap while (target != NULL) \ { \ if (target != CMC_ENTRY_DELETED && \ - _map_->key_cmp(target->key, key) == 0) \ + _map_->f_key->cmp(target->key, key) == 0) \ return &(_map_->key_buffer[pos % _map_->capacity]); \ \ pos++; \ @@ -1205,7 +1372,7 @@ struct cmc_callbacks_bidimap static struct SNAME##_entry **PFX##_impl_get_entry_by_val( \ struct SNAME *_map_, V val) \ { \ - size_t hash = _map_->val_hash(val); \ + size_t hash = _map_->f_val->hash(val); \ size_t pos = hash % _map_->capacity; \ \ struct SNAME##_entry *target = _map_->val_buffer[pos]; \ @@ -1213,7 +1380,7 @@ struct cmc_callbacks_bidimap while (target != NULL) \ { \ if (target != CMC_ENTRY_DELETED && \ - _map_->val_cmp(target->value, val) == 0) \ + _map_->f_val->cmp(target->value, val) == 0) \ return &(_map_->val_buffer[pos % _map_->capacity]); \ \ pos++; \ @@ -1228,7 +1395,7 @@ struct cmc_callbacks_bidimap { \ struct SNAME##_entry **to_return = NULL; \ \ - size_t hash = _map_->key_hash(entry->key); \ + size_t hash = _map_->f_key->hash(entry->key); \ size_t original_pos = hash % _map_->capacity; \ size_t pos = original_pos; \ \ @@ -1282,7 +1449,7 @@ struct cmc_callbacks_bidimap { \ struct SNAME##_entry **to_return = NULL; \ \ - size_t hash = _map_->val_hash(entry->value); \ + size_t hash = _map_->f_val->hash(entry->value); \ size_t original_pos = hash % _map_->capacity; \ size_t pos = original_pos; \ \ diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 75c8917..f0e5fae 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -61,16 +61,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 53562d8..d74f69b 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -49,16 +49,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 87de9a7..36ba581 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -49,16 +49,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index a5d2a5d..c116a0f 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -60,16 +60,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 4377696..1854402 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -51,16 +51,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index 2c0f630..0f0e1d2 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -58,16 +58,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/list.h b/src/cmc/list.h index d804e27..10d8070 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -73,16 +73,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ @@ -175,7 +190,6 @@ struct cmc_callbacks_list struct SNAME *PFX##_new_custom(size_t capacity, \ struct cmc_alloc_node *alloc, \ struct cmc_callbacks_list *callbacks); \ - struct SNAME *PFX##_new_from(V *elements, size_t size); \ void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ /* Customization of Allocation and Callbacks */ \ @@ -316,23 +330,6 @@ struct cmc_callbacks_list return _list_; \ } \ \ - struct SNAME *PFX##_new_from(V *elements, size_t size) \ - { \ - if (size == 0) \ - return NULL; \ - \ - struct SNAME *_list_ = PFX##_new(size + size / 2); \ - \ - if (!_list_) \ - return NULL; \ - \ - memcpy(_list_->buffer, elements, size * sizeof(V)); \ - \ - _list_->count = size; \ - \ - return _list_; \ - } \ - \ void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ @@ -428,7 +425,7 @@ struct cmc_callbacks_list return false; \ \ memmove(_list_->buffer, _list_->buffer + 1, \ - _list_->count * sizeof(V)); \ + (_list_->count - 1) * sizeof(V)); \ \ _list_->buffer[--_list_->count] = (V){ 0 }; \ \ @@ -441,7 +438,7 @@ struct cmc_callbacks_list return false; \ \ memmove(_list_->buffer + index, _list_->buffer + index + 1, \ - (_list_->count - index) * sizeof(V)); \ + (_list_->count - index - 1) * sizeof(V)); \ \ _list_->buffer[--_list_->count] = (V){ 0 }; \ \ diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index 0bb7961..b5abcba 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -73,16 +73,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index 1604ca3..3d41bdf 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -51,16 +51,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ @@ -829,7 +844,7 @@ struct cmc_callbacks_multiset { \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash, _set1_->alloc, _set1_->callbacks); \ + _set1_->hash, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -870,7 +885,7 @@ struct cmc_callbacks_multiset { \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash, _set1_->alloc, _set1_->callbacks); \ + _set1_->hash, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -901,7 +916,7 @@ struct cmc_callbacks_multiset { \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash, _set1_->alloc, _set1_->callbacks); \ + _set1_->hash, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -928,7 +943,7 @@ struct cmc_callbacks_multiset { \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash, _set1_->alloc, _set1_->callbacks); \ + _set1_->hash, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -961,7 +976,7 @@ struct cmc_callbacks_multiset \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash, _set1_->alloc, _set1_->callbacks); \ + _set1_->hash, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index e3814f0..4d53589 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -73,16 +73,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/sortedlist.h b/src/cmc/sortedlist.h index 228d9d2..382248d 100644 --- a/src/cmc/sortedlist.h +++ b/src/cmc/sortedlist.h @@ -52,16 +52,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 6672e92..691e555 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -58,16 +58,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index f570a13..e98e27c 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -49,16 +49,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 2c81e1b..512d499 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -49,16 +49,31 @@ static const size_t cmc_string_len = 400; * Custom allocation node. Allows collections to use custom allocation * functions. */ -struct cmc_alloc_node +static struct cmc_alloc_node { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); -}; +} cmc_alloc_node_default = { malloc, calloc, realloc, free }; -static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, - free }; +/** + * enum cmc_flags + * + * Defines common error codes used by all collections. These are flags that + * indicate if something went wrong in the last operation by the collection. + */ +static struct +{ + int OK; // Everything went as expected + int ALLOC; // Allocation failed + int EMPTY; // The collection is empty and the operation could not proceed + int NOT_FOUND; // Key or value not found + int INVALID; // Something is invalid + int OUT_OF_RANGE; // Index out of array range + int DUPLICATE; // Duplicate key or value + int ERROR; // Generic error, usually caused by unexpected behaviour +} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7 }; #endif /* CMC_CORE_H */ @@ -677,7 +692,7 @@ struct cmc_callbacks_treeset struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -705,7 +720,7 @@ struct cmc_callbacks_treeset struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -732,7 +747,7 @@ struct cmc_callbacks_treeset struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -756,7 +771,7 @@ struct cmc_callbacks_treeset struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ diff --git a/tests/Makefile b/tests/Makefile index 84e8804..63d94a4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -std=c11 -Wall -Wextra -CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label +CFLAGS += -Wno-unused -Wno-missing-braces main: FORCE $(CC) foreach.c -o foreach.exe $(CFLAGS) @@ -11,10 +11,7 @@ main: FORCE ./contains.exe $(CC) types.c -o types.exe $(CFLAGS) ./types.exe - $(CC) -c ./sep/collections.c -o ./sep/collections.o $(CFLAGS) - $(CC) -c ./sep/main.c -o ./sep/main.o $(CFLAGS) - $(CC) ./sep/collections.o ./sep/main.o -o ./sep/sep.exe - ./sep/sep.exe + make -C ./sep dev: main rm *.exe ./sep/*.o ./sep/*.exe diff --git a/tests/main/Makefile b/tests/main/Makefile index 584297a..879474d 100644 --- a/tests/main/Makefile +++ b/tests/main/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -std=c11 -Wall -Wextra -CFLAGS += -Wno-unused +CFLAGS += -Wno-unused -Wno-missing-braces CFLAGS += -DCMC_TEST_COLOR INCLUDE = ../../src/ diff --git a/tests/main/unt/bidimap.c b/tests/main/unt/bidimap.c index 629da56..5cf0100 100644 --- a/tests/main/unt/bidimap.c +++ b/tests/main/unt/bidimap.c @@ -7,17 +7,36 @@ CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t) +struct bidimap_ftab_key *bm_ftab_key = &(struct bidimap_ftab_key) { + .cmp = cmp, + .cpy = copy, + .str = to_string, + .free = custom_free, + .hash = hash, + .pri = priority +}; + +struct bidimap_ftab_val *bm_ftab_val = &(struct bidimap_ftab_val) { + .cmp = cmp, + .cpy = copy, + .str = to_string, + .free = custom_free, + .hash = hash, + .pri = priority +}; + CMC_CREATE_UNIT(bidimap_test, true, { CMC_CREATE_TEST(new, { - struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.6, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(new[null buffer], { - struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.6, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -27,11 +46,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(ptr, NULL, map->val_buffer[i]); } - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(new_custom, { - struct bidimap *map = bm_new_custom(100, 0.6, cmp, hash, cmp, hash, + struct bidimap *map = bm_new_custom(100, 0.6, bm_ftab_key, bm_ftab_val, &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, @@ -41,11 +60,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_not_equals(ptr, NULL, map); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(new_custom[insert remove], { - struct bidimap *map = bm_new_custom(500, 0.6, cmp, hash, cmp, hash, + struct bidimap *map = bm_new_custom(500, 0.6, bm_ftab_key, bm_ftab_val, &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, @@ -74,11 +93,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 0, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(clear[count], { - struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.6, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -87,15 +106,15 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 500, bm_count(map)); - bm_clear(map, NULL); + bm_clear(map); cmc_assert_equals(size_t, 0, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - struct bidimap *map = bm_new(1, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(1, 0.7, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -114,11 +133,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 50005000, sum); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(insert, { - struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -130,11 +149,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 2, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(insert[growth remove clear], { - struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -159,17 +178,18 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 1000, bm_count(map)); - bm_clear(map, NULL); + bm_clear(map); cmc_assert_equals(size_t, 0, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(update_key, { - struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); for (size_t i = 1; i <= 100; i++) cmc_assert(bm_insert(map, i, i)); @@ -186,11 +206,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 100, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(update_val, { - struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -209,11 +229,11 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(size_t, 100, bm_count(map)); - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(remove_by_key[cleanup custom], { - struct bidimap *map = bm_new_custom(10000, 0.6, cmp, hash, cmp, hash, + struct bidimap *map = bm_new_custom(10000, 0.6, bm_ftab_key, bm_ftab_val, &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, @@ -238,14 +258,15 @@ CMC_CREATE_UNIT(bidimap_test, true, { struct bidimap_entry *k = map->key_buffer[i]; struct bidimap_entry *v = map->val_buffer[i]; - cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) && (v == NULL || v == CMC_ENTRY_DELETED)); + cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) + && (v == NULL || v == CMC_ENTRY_DELETED)); } - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(remove_by_val[cleanup custom], { - struct bidimap *map = bm_new_custom(10000, 0.6, cmp, hash, cmp, hash, + struct bidimap *map = bm_new_custom(10000, 0.6, bm_ftab_key, bm_ftab_val, &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, @@ -273,16 +294,16 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) && (v == NULL || v == CMC_ENTRY_DELETED)); } - bm_free(map, NULL); + bm_free(map); }); CMC_CREATE_TEST(copy_of, { - struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); for (size_t i = 0; i < 100; i++) cmc_assert(bm_insert(map1, i, i)); - struct bidimap *map2 = bm_copy_of(map1, NULL, NULL); + 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)); @@ -293,13 +314,13 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert(bm_contains_val(map2, i) && bm_contains_val(map1, i)); } - bm_free(map1, NULL); - bm_free(map2, NULL); + bm_free(map1); + bm_free(map2); }); CMC_CREATE_TEST(equals, { - struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); - struct bidimap *map2 = bm_new(1000, 0.9, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); + struct bidimap *map2 = bm_new(1000, 0.9, bm_ftab_key, bm_ftab_val); for (size_t i = 0; i < 100; i++) { @@ -317,23 +338,23 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert(bm_contains_val(map2, i) && bm_contains_val(map1, i)); } - bm_free(map1, NULL); - bm_free(map2, NULL); + bm_free(map1); + bm_free(map2); }); CMC_CREATE_TEST(equals[from copy], { - struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, bm_ftab_key, bm_ftab_val); for (size_t i = 0; i < 100; i++) cmc_assert(bm_insert(map1, i, i)); - struct bidimap *map2 = bm_copy_of(map1, NULL, NULL); + struct bidimap *map2 = bm_copy_of(map1); cmc_assert_not_equals(ptr, NULL, map2); cmc_assert(bm_equals(map1, map2)); - bm_free(map1, NULL); - bm_free(map2, NULL); + bm_free(map1); + bm_free(map2); }); }); diff --git a/tests/main/unt/list.c b/tests/main/unt/list.c index 8cc30da..6611381 100644 --- a/tests/main/unt/list.c +++ b/tests/main/unt/list.c @@ -31,36 +31,6 @@ CMC_CREATE_UNIT(list_test, true, { cmc_assert_equals(ptr, NULL, l); }); - CMC_CREATE_TEST(new_from[count and item preservation], { - size_t v[5]; - - for (size_t i = 0; i < 5; i++) - { - v[i] = i; - } - - struct list *l = l_new_from(v, 5); - - cmc_assert_not_equals(ptr, NULL, l); - - for (size_t i = 0; i < 5; i++) - cmc_assert_equals(size_t, i, l_get(l, i)); - - l_free(l, NULL); - }); - - CMC_CREATE_TEST(new_from[size = 1], { - size_t a = 10; - - size_t *values = &a; - - struct list *l = l_new_from(values, 1); - - cmc_assert_not_equals(ptr, NULL, l); - - l_free(l, NULL); - }); - CMC_CREATE_TEST(clear[count capacity], { struct list *l = l_new(100); diff --git a/tests/main/unt/utl.c b/tests/main/unt/utl.c index 5844154..d7a7bf2 100644 --- a/tests/main/unt/utl.c +++ b/tests/main/unt/utl.c @@ -3,6 +3,7 @@ #define CMC_UNIT_TEST_UTL__ #include +#include #include int cmp(size_t a, size_t b) @@ -10,6 +11,22 @@ int cmp(size_t a, size_t b) return (a > b) - (a < b); } +size_t copy(size_t a) +{ + return a; +} + +bool to_string(FILE *fptr, size_t a) +{ + return fprintf(fptr, "%" PRIuMAX " ", a) > 0; +} + +void custom_free(size_t a) +{ + // blank + // Free any resources if necessary +} + size_t hash(size_t a) { a += ~(a << 15); @@ -21,6 +38,12 @@ size_t hash(size_t a) return a; } +int priority(size_t a, size_t b) +{ + // Could contain different logic + return cmp(a, b); +} + size_t numhash(size_t a) { return a; diff --git a/tests/sep/Makefile b/tests/sep/Makefile new file mode 100644 index 0000000..089d7b8 --- /dev/null +++ b/tests/sep/Makefile @@ -0,0 +1,15 @@ +CC = gcc +CFLAGS = -std=c11 -Wall -Wextra +CFLAGS += -Wno-unused -Wno-missing-braces + +main: + $(CC) -c collections.c -o collections.o $(CFLAGS) + $(CC) -c main.c -o main.o $(CFLAGS) + $(CC) collections.o main.o -o sep.exe + ./sep.exe + +clean: + rm *.o + +clear: + rm *.o *.exe diff --git a/tests/sep/main.c b/tests/sep/main.c index 4b86695..350a863 100644 --- a/tests/sep/main.c +++ b/tests/sep/main.c @@ -20,7 +20,9 @@ size_t inthash(int t) int main(void) { - struct bmap *bm = bm_new_custom(100, 0.7, NULL, NULL, NULL, NULL, NULL, NULL); + struct bmap *bm = + bm_new_custom(100, 0.7, &(struct bmap_ftab_key){ 0 }, + &(struct bmap_ftab_val){ 0 }, NULL, NULL); struct deque *d = d_new_custom(100, NULL, NULL); struct hmap *hm = hm_new_custom(100, 0.6, NULL, NULL, NULL, NULL); struct hset *hs = hs_new_custom(100, 0.6, NULL, NULL, NULL, NULL); @@ -40,7 +42,7 @@ int main(void) printf("| Separate Header and Source is Working |\n"); printf("+--------------------------------------------------+\n"); - bm_free(bm, NULL); + bm_free(bm); d_free(d, NULL); hm_free(hm, NULL); hs_free(hs, NULL); diff --git a/tests/to_string.c b/tests/to_string.c index a5df4a1..db1148b 100644 --- a/tests/to_string.c +++ b/tests/to_string.c @@ -20,7 +20,7 @@ CMC_COLLECTION_GENERATE( TREEMAP, tm, tmap, int, int) int main(void) { - struct bmap *bm = bm_new_custom(100, 0.7, NULL, NULL, NULL, NULL, NULL, NULL); + struct bmap *bm = bm_new_custom(100, 0.7, NULL, NULL, NULL, NULL); struct deque *d = d_new_custom(100, NULL, NULL); struct hmap *hm = hm_new_custom(100, 0.6, NULL, NULL, NULL, NULL); struct hset *hs = hs_new_custom(100, 0.6, NULL, NULL, NULL, NULL);