diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index cc66251..1b653bb 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -1021,8 +1021,6 @@ struct cmc_callbacks_bidimap _map_->alloc->free(tmp_val_buf); \ _map_->alloc->free(_new_map_); \ \ - _map_->flag = cmc_flags.OK; \ - \ return true; \ } \ \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 012257f..ccf8ef9 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -518,6 +518,8 @@ struct cmc_callbacks_heap \ bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ { \ + _heap_->flag = cmc_flags.OK; \ + \ if (_heap_->capacity == capacity) \ return true; \ \ @@ -541,8 +543,6 @@ struct cmc_callbacks_heap _heap_->buffer = new_buffer; \ _heap_->capacity = capacity; \ \ - _heap_->flag = cmc_flags.OK; \ - \ return true; \ } \ \ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index 8169e6f..5b42e7b 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -317,6 +317,7 @@ struct cmc_callbacks_multiset size_t PFX##_cardinality(struct SNAME *_set_); \ size_t PFX##_capacity(struct SNAME *_set_); \ double PFX##_load(struct SNAME *_set_); \ + int PFX##_flag(struct SNAME *_set_); \ /* Collection Utility */ \ bool PFX##_resize(struct SNAME *_set_, size_t capacity); \ struct SNAME *PFX##_copy_of(struct SNAME *_set_); \ @@ -486,6 +487,7 @@ struct cmc_callbacks_multiset sizeof(struct SNAME##_entry) * _set_->capacity); \ \ _set_->count = 0; \ + _set_->flag = cmc_flags.OK; \ } \ \ void PFX##_free(struct SNAME *_set_) \ @@ -515,6 +517,8 @@ struct cmc_callbacks_multiset \ if (callbacks) \ _set_->callbacks = callbacks; \ + \ + _set_->flag = cmc_flags.OK; \ } \ \ bool PFX##_insert(struct SNAME *_set_, V element) \ @@ -525,12 +529,16 @@ struct cmc_callbacks_multiset PFX##_impl_insert_and_return(_set_, element, &new_node); \ \ if (!entry) \ + { \ + _set_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (!new_node) \ entry->multiplicity++; \ \ _set_->cardinality++; \ + _set_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -538,7 +546,10 @@ struct cmc_callbacks_multiset bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count) \ { \ if (count == 0) \ + { \ + _set_->flag = cmc_flags.OK; \ return true; \ + } \ \ bool new_node; \ \ @@ -546,7 +557,10 @@ struct cmc_callbacks_multiset PFX##_impl_insert_and_return(_set_, element, &new_node); \ \ if (!entry) \ + { \ + _set_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ if (new_node) \ entry->multiplicity = count; \ @@ -554,6 +568,7 @@ struct cmc_callbacks_multiset entry->multiplicity += count; \ \ _set_->cardinality += count; \ + _set_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -561,7 +576,27 @@ struct cmc_callbacks_multiset bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity) \ { \ if (multiplicity == 0) \ - return PFX##_remove_all(_set_, element); \ + { \ + /* Effectively delete the entry */ \ + struct SNAME##_entry *result = \ + PFX##_impl_get_entry(_set_, element); \ + \ + _set_->flag = cmc_flags.OK; \ + \ + if (!result) \ + /* If no entry was found then its multiplicity is already 0 */ \ + return true; \ + \ + _set_->count--; \ + _set_->cardinality -= result->multiplicity; \ + \ + result->value = (V){ 0 }; \ + result->multiplicity = 0; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + return true; \ + } \ \ bool new_node; \ \ @@ -579,15 +614,26 @@ struct cmc_callbacks_multiset \ entry->multiplicity = multiplicity; \ \ + _set_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_remove(struct SNAME *_set_, V element) \ { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ + \ struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ - if (result == NULL) \ + if (!result) \ + { \ + _set_->flag = cmc_flags.NOT_FOUND; \ return false; \ + } \ \ if (result->multiplicity > 1) \ result->multiplicity--; \ @@ -602,16 +648,26 @@ struct cmc_callbacks_multiset } \ \ _set_->cardinality--; \ + _set_->flag = cmc_flags.OK; \ \ return true; \ } \ \ size_t PFX##_remove_all(struct SNAME *_set_, V element) \ { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ + \ struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ - if (result == NULL) \ + if (!result) \ + { \ + _set_->flag = cmc_flags.NOT_FOUND; \ return 0; \ + } \ \ size_t removed = result->multiplicity; \ \ @@ -622,6 +678,7 @@ struct cmc_callbacks_multiset \ _set_->count--; \ _set_->cardinality -= removed; \ + _set_->flag = cmc_flags.OK; \ \ return removed; \ } \ @@ -629,10 +686,15 @@ struct cmc_callbacks_multiset bool PFX##_max(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ + { \ + _set_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ + V max_val; \ struct SNAME##_iter iter; \ \ + /* TODO transform this into a normal loop */ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -640,21 +702,31 @@ struct cmc_callbacks_multiset size_t index = PFX##_iter_index(&iter); \ \ if (index == 0) \ - *value = result; \ - else if (_set_->f_val->cmp(result, *value) > 0) \ - *value = result; \ + max_val = result; \ + else if (_set_->f_val->cmp(result, max_val) > 0) \ + max_val = result; \ } \ \ + if (value) \ + *value = max_val; \ + \ + _set_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_min(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ + { \ + _set_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ + V min_val; \ struct SNAME##_iter iter; \ \ + /* TODO transform this into a normal loop */ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -662,11 +734,16 @@ struct cmc_callbacks_multiset size_t index = PFX##_iter_index(&iter); \ \ if (index == 0) \ - *value = result; \ - else if (_set_->f_val->cmp(result, *value) < 0) \ - *value = result; \ + min_val = result; \ + else if (_set_->f_val->cmp(result, min_val) < 0) \ + min_val = result; \ } \ \ + if (value) \ + *value = min_val; \ + \ + _set_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ @@ -674,6 +751,8 @@ struct cmc_callbacks_multiset { \ struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ \ + _set_->flag = cmc_flags.OK; \ + \ if (!entry) \ return 0; \ \ @@ -682,6 +761,8 @@ struct cmc_callbacks_multiset \ bool PFX##_contains(struct SNAME *_set_, V element) \ { \ + _set_->flag = cmc_flags.OK; \ + \ return PFX##_impl_get_entry(_set_, element) != NULL; \ } \ \ @@ -715,8 +796,15 @@ struct cmc_callbacks_multiset return _set_->load; \ } \ \ + int PFX##_flag(struct SNAME *_set_) \ + { \ + return _set_->flag; \ + } \ + \ bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ { \ + _set_->flag = cmc_flags.OK; \ + \ if (_set_->capacity == capacity) \ return true; \ \ @@ -725,21 +813,30 @@ struct cmc_callbacks_multiset \ /* Prevent integer overflow */ \ if (capacity >= UINTMAX_MAX * _set_->load) \ + { \ + _set_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ /* Calculate required capacity based on the prime numbers */ \ size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ \ /* Not possible to shrink with current available prime numbers */ \ if (theoretical_size < _set_->count / _set_->load) \ + { \ + _set_->flag = cmc_flags.INVALID; \ return false; \ + } \ \ struct SNAME *_new_set_ = \ PFX##_new_custom(capacity, _set_->load, _set_->f_val, \ _set_->alloc, _set_->callbacks); \ \ if (!_new_set_) \ + { \ + _set_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ struct SNAME##_iter iter; \ \ @@ -776,7 +873,10 @@ struct cmc_callbacks_multiset _set_->f_val, _set_->alloc, _set_->callbacks); \ \ if (!result) \ + { \ + _set_->flag = cmc_flags.ERROR; \ return NULL; \ + } \ \ if (_set_->f_val->cpy) \ { \ @@ -808,11 +908,16 @@ struct cmc_callbacks_multiset result->count = _set_->count; \ result->cardinality = _set_->cardinality; \ \ + _set_->flag = cmc_flags.OK; \ + \ return result; \ } \ \ bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + _set1_->flag = cmc_flags.OK; \ + _set2_->flag = cmc_flags.OK; \ + \ if (_set1_->count != _set2_->count) \ return false; \ \ diff --git a/tests/main/unt/multiset.c b/tests/main/unt/multiset.c index 7bf25db..bba7da1 100644 --- a/tests/main/unt/multiset.c +++ b/tests/main/unt/multiset.c @@ -159,4 +159,107 @@ CMC_CREATE_UNIT(multiset_test, true, { ms_free(set); }); + + CMC_CREATE_TEST(flags, { + struct multiset *set = ms_new(100, 0.6, ms_ftab_val); + + cmc_assert_not_equals(ptr, NULL, set); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // clear + set->flag = cmc_flags.ERROR; + ms_clear(set); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // customize + set->flag = cmc_flags.ERROR; + ms_customize(set, NULL, NULL); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // insert + set->flag = cmc_flags.ERROR; + cmc_assert(ms_insert(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(ms_insert(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // insert_many + set->flag = cmc_flags.ERROR; + cmc_assert(ms_insert_many(set, 1, 0)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(ms_insert_many(set, 1, 2)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // update + set->flag = cmc_flags.ERROR; + cmc_assert(ms_update(set, 1, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(ms_update(set, 10, 0)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // remove + cmc_assert(!ms_remove(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, ms_flag(set)); + + cmc_assert(ms_remove(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // remove_all + cmc_assert_equals(size_t, 0, ms_remove_all(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); + + cmc_assert(ms_insert_many(set, 1, 10)); + cmc_assert_equals(size_t, 0, ms_remove_all(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, ms_flag(set)); + + cmc_assert_equals(size_t, 10, ms_remove_all(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // max min + cmc_assert(!ms_max(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); + set->flag = cmc_flags.ERROR; + cmc_assert(!ms_min(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); + + cmc_assert(ms_insert(set, 1)); + set->flag = cmc_flags.ERROR; + cmc_assert(ms_max(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + set->flag = cmc_flags.ERROR; + cmc_assert(ms_min(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // multiplicity_of + set->flag = cmc_flags.ERROR; + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // contains + set->flag = cmc_flags.ERROR; + cmc_assert(!ms_contains(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + + // copy_of + set->flag = cmc_flags.ERROR; + struct multiset *set2 = ms_copy_of(set); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set2)); + + // equals + set->flag = cmc_flags.ERROR; + set2->flag = cmc_flags.ERROR; + cmc_assert(ms_equals(set, set2)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); + cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set2)); + + ms_free(set); + ms_free(set2); + }); });