Fast forward codecov
This commit is contained in:
1 parent
616327f054
commit
122d012ffd
32 files changed
+6944
-2101
No files matched your search
+21
-6
@@ -1,35 +1,50 @@
|
||||
#include <utl/timer.h>
|
||||
|
||||
#include "unt/bidimap.c"
|
||||
#include "unt/deque.c"
|
||||
#include "unt/hashmap.c"
|
||||
#include "unt/hashset.c"
|
||||
#include "unt/heap.c"
|
||||
#include "unt/intervalheap.c"
|
||||
#include "unt/linkedlist.c"
|
||||
#include "unt/list.c"
|
||||
#include "unt/multimap.c"
|
||||
#include "unt/multiset.c"
|
||||
#include "unt/queue.c"
|
||||
#include "unt/sortedlist.c"
|
||||
#include "unt/stack.c"
|
||||
#include "unt/treemap.c"
|
||||
#include "unt/treeset.c"
|
||||
|
||||
#include "unt/multimap.c"
|
||||
#include "unt/multiset.c"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
cmc_timer timer;
|
||||
|
||||
cmc_timer_start(timer);
|
||||
uintmax_t failed = 0;
|
||||
|
||||
failed += bidimap_test();
|
||||
failed += deque_test();
|
||||
failed += hashmap_test();
|
||||
failed += hashset_test();
|
||||
failed += heap_test();
|
||||
failed += intervalheap_test();
|
||||
failed += linkedlist_test();
|
||||
failed += list_test();
|
||||
failed += multimap_test();
|
||||
failed += multiset_test();
|
||||
failed += queue_test();
|
||||
failed += sortedlist_test();
|
||||
failed += stack_test();
|
||||
failed += treemap_test();
|
||||
failed += treeset_test();
|
||||
|
||||
/* ext */
|
||||
failed += multimap_test();
|
||||
failed += multiset_test();
|
||||
cmc_timer_stop(timer);
|
||||
cmc_timer_calc(timer);
|
||||
|
||||
printf("+--------------------------------------------------+\n");
|
||||
printf("| Total running time : %14.0lf milliseconds |\n", timer.result);
|
||||
printf("+--------------------------------------------------+\n");
|
||||
|
||||
return failed;
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
#include <cmc/bidimap.h>
|
||||
|
||||
//CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t)
|
||||
|
||||
typedef struct bidimap_s
|
||||
{
|
||||
struct bidimap_entry_s **key_buffer;
|
||||
struct bidimap_entry_s **val_buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
double load;
|
||||
int (*key_cmp)(size_t, size_t);
|
||||
int (*val_cmp)(size_t, size_t);
|
||||
size_t (*key_hash)(size_t);
|
||||
size_t (*val_hash)(size_t);
|
||||
struct bidimap_iter_s (*it_start)(struct bidimap_s *);
|
||||
struct bidimap_iter_s (*it_end)(struct bidimap_s *);
|
||||
} bidimap, *bidimap_ptr;
|
||||
typedef struct bidimap_entry_s
|
||||
{
|
||||
size_t key;
|
||||
size_t value;
|
||||
size_t key_dist;
|
||||
size_t val_dist;
|
||||
} bidimap_entry, *bidimap_entry_ptr;
|
||||
typedef struct bidimap_iter_s
|
||||
{
|
||||
struct bidimap_s *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} bidimap_iter, *bidimap_iter_ptr;
|
||||
bidimap *bm_new(size_t capacity, double load, int (*key_cmp)(size_t, size_t), size_t (*key_hash)(size_t), int (*val_cmp)(size_t, size_t), size_t (*val_hash)(size_t));
|
||||
void bm_clear(bidimap *_map_, void (*deallocator)(size_t, size_t));
|
||||
void bm_free(bidimap *_map_, void (*deallocator)(size_t, size_t));
|
||||
_Bool bm_insert(bidimap *_map_, size_t key, size_t value);
|
||||
_Bool bm_update_key(bidimap *_map_, size_t key, size_t *old_key);
|
||||
_Bool bm_update_val(bidimap *_map_, size_t val, size_t *old_val);
|
||||
_Bool bm_remove_by_key(bidimap *_map_, size_t key, size_t *out_value);
|
||||
_Bool bm_remove_by_val(bidimap *_map_, size_t value, size_t *out_key);
|
||||
size_t bm_get_key(bidimap *_map_, size_t val);
|
||||
size_t bm_get_val(bidimap *_map_, size_t key);
|
||||
_Bool bm_contains_key(bidimap *_map_, size_t key);
|
||||
_Bool bm_contains_val(bidimap *_map_, size_t val);
|
||||
_Bool bm_empty(bidimap *_map_);
|
||||
_Bool bm_full(bidimap *_map_);
|
||||
size_t bm_count(bidimap *_map_);
|
||||
size_t bm_capacity(bidimap *_map_);
|
||||
double bm_load(bidimap *_map_);
|
||||
bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t));
|
||||
_Bool bm_equals(bidimap *_map1_, bidimap *_map2_);
|
||||
cmc_string bm_to_string(bidimap *_map_);
|
||||
bidimap_iter *bm_iter_new(bidimap *target);
|
||||
void bm_iter_free(bidimap_iter *iter);
|
||||
void bm_iter_init(bidimap_iter *iter, bidimap *target);
|
||||
_Bool bm_iter_start(bidimap_iter *iter);
|
||||
_Bool bm_iter_end(bidimap_iter *iter);
|
||||
void bm_iter_to_start(bidimap_iter *iter);
|
||||
void bm_iter_to_end(bidimap_iter *iter);
|
||||
_Bool bm_iter_next(bidimap_iter *iter);
|
||||
_Bool bm_iter_prev(bidimap_iter *iter);
|
||||
_Bool bm_iter_advance(bidimap_iter *iter, size_t steps);
|
||||
_Bool bm_iter_rewind(bidimap_iter *iter, size_t steps);
|
||||
_Bool bm_iter_go_to(bidimap_iter *iter, size_t index);
|
||||
size_t bm_iter_key(bidimap_iter *iter);
|
||||
size_t bm_iter_value(bidimap_iter *iter);
|
||||
size_t bm_iter_index(bidimap_iter *iter);
|
||||
static _Bool bm_impl_grow(bidimap *_map_);
|
||||
static bidimap_entry *bm_impl_new_entry(size_t key, size_t value);
|
||||
static bidimap_entry **bm_impl_get_entry_by_key(bidimap *_map_, size_t key);
|
||||
static bidimap_entry **bm_impl_get_entry_by_val(bidimap *_map_, size_t val);
|
||||
static bidimap_entry **bm_impl_add_entry_to_key(bidimap *_map_, bidimap_entry *entry);
|
||||
static bidimap_entry **bm_impl_add_entry_to_val(bidimap *_map_, bidimap_entry *entry);
|
||||
static size_t bm_impl_calculate_size(size_t required);
|
||||
static bidimap_iter bm_impl_it_start(bidimap *_map_);
|
||||
static bidimap_iter bm_impl_it_end(bidimap *_map_);
|
||||
bidimap *bm_new(size_t capacity, double load, int (*key_cmp)(size_t, size_t), size_t (*key_hash)(size_t), int (*val_cmp)(size_t, size_t), size_t (*val_hash)(size_t))
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
return ((void *)0);
|
||||
size_t real_capacity = bm_impl_calculate_size(capacity / load);
|
||||
bidimap *_map_ = malloc(sizeof(bidimap));
|
||||
if (!_map_)
|
||||
return ((void *)0);
|
||||
_map_->key_buffer = calloc(real_capacity, sizeof(bidimap_entry *));
|
||||
_map_->val_buffer = calloc(real_capacity, sizeof(bidimap_entry *));
|
||||
if (!_map_->key_buffer || !_map_->val_buffer)
|
||||
{
|
||||
free(_map_->key_buffer);
|
||||
free(_map_->val_buffer);
|
||||
free(_map_);
|
||||
return ((void *)0);
|
||||
}
|
||||
_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 = bm_impl_it_start;
|
||||
_map_->it_end = bm_impl_it_end;
|
||||
return _map_;
|
||||
}
|
||||
void bm_clear(bidimap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
bidimap_entry *entry = _map_->key_buffer[i];
|
||||
if (entry != ((void *)0) && entry != ((void *)1))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(entry->key, entry->value);
|
||||
free(entry);
|
||||
}
|
||||
_map_->key_buffer[i] = ((void *)0);
|
||||
_map_->val_buffer[i] = ((void *)0);
|
||||
}
|
||||
_map_->count = 0;
|
||||
}
|
||||
void bm_free(bidimap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
bm_clear(_map_, deallocator);
|
||||
free(_map_->key_buffer);
|
||||
free(_map_->val_buffer);
|
||||
free(_map_);
|
||||
}
|
||||
_Bool bm_insert(bidimap *_map_, size_t key, size_t value)
|
||||
{
|
||||
if (bm_full(_map_))
|
||||
{
|
||||
if (!bm_impl_grow(_map_))
|
||||
return 0;
|
||||
}
|
||||
if (bm_impl_get_entry_by_key(_map_, key) != ((void *)0) || bm_impl_get_entry_by_val(_map_, value) != ((void *)0))
|
||||
return 0;
|
||||
bidimap_entry *entry = bm_impl_new_entry(key, value);
|
||||
bidimap_entry **key_entry = bm_impl_add_entry_to_key(_map_, entry);
|
||||
bidimap_entry **val_entry = bm_impl_add_entry_to_val(_map_, entry);
|
||||
if (!key_entry || !val_entry)
|
||||
{
|
||||
if (key_entry)
|
||||
*key_entry = ((void *)1);
|
||||
if (val_entry)
|
||||
*val_entry = ((void *)1);
|
||||
free(entry);
|
||||
return 0;
|
||||
}
|
||||
_map_->count++;
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_update_key(bidimap *_map_, size_t key, size_t *old_key)
|
||||
{
|
||||
if (bm_empty(_map_))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_update_val(bidimap *_map_, size_t val, size_t *old_val)
|
||||
{
|
||||
if (bm_empty(_map_))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_remove_by_key(bidimap *_map_, size_t key, size_t *out_value)
|
||||
{
|
||||
if (bm_empty(_map_))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_remove_by_val(bidimap *_map_, size_t value, size_t *out_key)
|
||||
{
|
||||
if (bm_empty(_map_))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
size_t bm_get_key(bidimap *_map_, size_t val)
|
||||
{
|
||||
bidimap_entry **entry = bm_impl_get_entry_by_val(_map_, val);
|
||||
if (!entry)
|
||||
return (size_t){0};
|
||||
return (*entry)->key;
|
||||
}
|
||||
size_t bm_get_val(bidimap *_map_, size_t key)
|
||||
{
|
||||
bidimap_entry **entry = bm_impl_get_entry_by_key(_map_, key);
|
||||
if (!entry)
|
||||
return (size_t){0};
|
||||
return (*entry)->value;
|
||||
}
|
||||
_Bool bm_contains_key(bidimap *_map_, size_t key) { return bm_impl_get_entry_by_key(_map_, key) != ((void *)0); }
|
||||
_Bool bm_contains_val(bidimap *_map_, size_t val) { return bm_impl_get_entry_by_val(_map_, val) != ((void *)0); }
|
||||
_Bool bm_empty(bidimap *_map_) { return _map_->count == 0; }
|
||||
_Bool bm_full(bidimap *_map_) { return (double)bm_capacity(_map_) * bm_load(_map_) <= (double)bm_count(_map_); }
|
||||
size_t bm_count(bidimap *_map_) { return _map_->count; }
|
||||
size_t bm_capacity(bidimap *_map_) { return _map_->capacity; }
|
||||
double bm_load(bidimap *_map_) { return _map_->load; }
|
||||
bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) { return ((void *)0); }
|
||||
_Bool bm_equals(bidimap *_map1_, bidimap *_map2_) { return 0; }
|
||||
cmc_string bm_to_string(bidimap *_map_)
|
||||
{
|
||||
cmc_string str;
|
||||
bidimap *m_ = _map_;
|
||||
const char *name = "bidimap";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, name, 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);
|
||||
return str;
|
||||
}
|
||||
bidimap_iter *bm_iter_new(bidimap *target)
|
||||
{
|
||||
bidimap_iter *iter = malloc(sizeof(bidimap_iter));
|
||||
if (!iter)
|
||||
return ((void *)0);
|
||||
bm_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void bm_iter_free(bidimap_iter *iter) { free(iter); }
|
||||
void bm_iter_init(bidimap_iter *iter, bidimap *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(bidimap_iter));
|
||||
iter->target = target;
|
||||
iter->start = 1;
|
||||
iter->end = bm_empty(target);
|
||||
if (!bm_empty(target))
|
||||
{
|
||||
for (size_t i = 0; i < target->capacity; i++)
|
||||
{
|
||||
bidimap_entry *tmp = target->key_buffer[i];
|
||||
if (tmp != ((void *)0) && tmp != ((void *)1))
|
||||
{
|
||||
iter->first = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iter->cursor = iter->first;
|
||||
for (size_t i = target->capacity; i > 0; i--)
|
||||
{
|
||||
bidimap_entry *tmp = target->key_buffer[i - 1];
|
||||
if (tmp != ((void *)0) && tmp != ((void *)1))
|
||||
{
|
||||
iter->last = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_Bool bm_iter_start(bidimap_iter *iter) { return bm_empty(iter->target) || iter->start; }
|
||||
_Bool bm_iter_end(bidimap_iter *iter) { return bm_empty(iter->target) || iter->end; }
|
||||
void bm_iter_to_start(bidimap_iter *iter)
|
||||
{
|
||||
if (!bm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = 0;
|
||||
}
|
||||
}
|
||||
void bm_iter_to_end(bidimap_iter *iter)
|
||||
{
|
||||
if (!bm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = bm_count(iter->target) - 1;
|
||||
iter->start = 0;
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
_Bool bm_iter_next(bidimap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == bm_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = bm_empty(iter->target);
|
||||
bidimap_entry *scan = iter->target->key_buffer[iter->cursor];
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor++;
|
||||
scan = iter->target->key_buffer[iter->cursor];
|
||||
if (scan != ((void *)0) && scan != ((void *)1))
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_iter_prev(bidimap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = bm_empty(iter->target);
|
||||
bidimap_entry *scan = iter->target->key_buffer[iter->cursor];
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor--;
|
||||
scan = iter->target->key_buffer[iter->cursor];
|
||||
if (scan != ((void *)0) && scan != ((void *)1))
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_iter_advance(bidimap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == bm_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= bm_count(iter->target))
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
bm_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_iter_rewind(bidimap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
bm_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool bm_iter_go_to(bidimap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= bm_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return bm_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return bm_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t bm_iter_key(bidimap_iter *iter)
|
||||
{
|
||||
if (bm_empty(iter->target))
|
||||
return (size_t){0};
|
||||
return iter->target->key_buffer[iter->cursor]->key;
|
||||
}
|
||||
size_t bm_iter_value(bidimap_iter *iter)
|
||||
{
|
||||
if (bm_empty(iter->target))
|
||||
return (size_t){0};
|
||||
return iter->target->key_buffer[iter->cursor]->value;
|
||||
}
|
||||
size_t bm_iter_index(bidimap_iter *iter) { return iter->index; }
|
||||
static _Bool bm_impl_grow(bidimap *_map_) { return 0; }
|
||||
static bidimap_entry *bm_impl_new_entry(size_t key, size_t value)
|
||||
{
|
||||
bidimap_entry *entry = malloc(sizeof(bidimap_entry));
|
||||
if (!entry)
|
||||
return ((void *)0);
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
entry->key_dist = 0;
|
||||
entry->val_dist = 0;
|
||||
return entry;
|
||||
}
|
||||
static bidimap_entry **bm_impl_get_entry_by_key(bidimap *_map_, size_t key)
|
||||
{
|
||||
size_t hash = _map_->key_hash(key);
|
||||
size_t pos = hash % _map_->capacity;
|
||||
bidimap_entry *target = _map_->key_buffer[pos];
|
||||
while (target != ((void *)0))
|
||||
{
|
||||
if (target != ((void *)1) && _map_->key_cmp(target->key, key) == 0)
|
||||
return &(_map_->key_buffer[pos % _map_->capacity]);
|
||||
pos++;
|
||||
target = _map_->key_buffer[pos % _map_->capacity];
|
||||
}
|
||||
return ((void *)0);
|
||||
}
|
||||
static bidimap_entry **bm_impl_get_entry_by_val(bidimap *_map_, size_t val)
|
||||
{
|
||||
size_t hash = _map_->val_hash(val);
|
||||
size_t pos = hash % _map_->capacity;
|
||||
bidimap_entry *target = _map_->val_buffer[pos];
|
||||
while (target != ((void *)0))
|
||||
{
|
||||
if (target != ((void *)1) && _map_->val_cmp(target->value, val) == 0)
|
||||
return &(_map_->val_buffer[pos % _map_->capacity]);
|
||||
pos++;
|
||||
target = _map_->val_buffer[pos % _map_->capacity];
|
||||
}
|
||||
return ((void *)0);
|
||||
}
|
||||
static bidimap_entry **bm_impl_add_entry_to_key(bidimap *_map_, bidimap_entry *entry)
|
||||
{
|
||||
bidimap_entry **to_return = ((void *)0);
|
||||
size_t hash = _map_->key_hash(entry->key);
|
||||
size_t original_pos = hash % _map_->capacity;
|
||||
size_t pos = original_pos;
|
||||
bidimap_entry **scan = &(_map_->key_buffer[hash % _map_->capacity]);
|
||||
if (*scan == ((void *)0))
|
||||
{
|
||||
*scan = entry;
|
||||
return scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
pos++;
|
||||
scan = &(_map_->key_buffer[pos % _map_->capacity]);
|
||||
if (*scan == ((void *)0) || *scan == ((void *)1))
|
||||
{
|
||||
if (!to_return)
|
||||
to_return = scan;
|
||||
*scan = entry;
|
||||
entry->key_dist = pos - original_pos;
|
||||
return to_return;
|
||||
}
|
||||
else if ((*scan)->key_dist < pos - original_pos)
|
||||
{
|
||||
if (!to_return)
|
||||
to_return = scan;
|
||||
size_t tmp_dist = (*scan)->key_dist;
|
||||
entry->key_dist = pos - original_pos;
|
||||
original_pos = pos - tmp_dist;
|
||||
bidimap_entry *_tmp_ = *scan;
|
||||
*scan = entry;
|
||||
entry = _tmp_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((void *)0);
|
||||
}
|
||||
static bidimap_entry **bm_impl_add_entry_to_val(bidimap *_map_, bidimap_entry *entry)
|
||||
{
|
||||
bidimap_entry **to_return = ((void *)0);
|
||||
size_t hash = _map_->val_hash(entry->value);
|
||||
size_t original_pos = hash % _map_->capacity;
|
||||
size_t pos = original_pos;
|
||||
bidimap_entry **scan = &(_map_->val_buffer[hash % _map_->capacity]);
|
||||
if (*scan == ((void *)0))
|
||||
{
|
||||
*scan = entry;
|
||||
return scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
pos++;
|
||||
scan = &(_map_->val_buffer[pos % _map_->capacity]);
|
||||
if (*scan == ((void *)0) || *scan == ((void *)1))
|
||||
{
|
||||
if (!to_return)
|
||||
to_return = scan;
|
||||
*scan = entry;
|
||||
entry->val_dist = pos - original_pos;
|
||||
return to_return;
|
||||
}
|
||||
else if ((*scan)->val_dist < pos - original_pos)
|
||||
{
|
||||
if (!to_return)
|
||||
to_return = scan;
|
||||
size_t tmp_dist = (*scan)->val_dist;
|
||||
entry->val_dist = pos - original_pos;
|
||||
original_pos = pos - tmp_dist;
|
||||
bidimap_entry *_tmp_ = *scan;
|
||||
*scan = entry;
|
||||
entry = _tmp_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((void *)0);
|
||||
}
|
||||
static size_t bm_impl_calculate_size(size_t required)
|
||||
{
|
||||
const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]);
|
||||
if (cmc_hashtable_primes[count - 1] < required)
|
||||
return required;
|
||||
size_t i = 0;
|
||||
while (cmc_hashtable_primes[i] < required)
|
||||
i++;
|
||||
return cmc_hashtable_primes[i];
|
||||
}
|
||||
static bidimap_iter bm_impl_it_start(bidimap *_map_)
|
||||
{
|
||||
bidimap_iter iter;
|
||||
bm_iter_init(&iter, _map_);
|
||||
return iter;
|
||||
}
|
||||
static bidimap_iter bm_impl_it_end(bidimap *_map_)
|
||||
{
|
||||
bidimap_iter iter;
|
||||
bm_iter_init(&iter, _map_);
|
||||
bm_iter_to_end(&iter);
|
||||
return iter;
|
||||
}
|
||||
+216
-125
@@ -1,6 +1,6 @@
|
||||
#include "cmc/deque.h"
|
||||
#include <cmc/deque.h>
|
||||
|
||||
//DEQUE_GENERATE(d, deque, , size_t)
|
||||
//CMC_GENERATE_DEQUE(d, deque, size_t)
|
||||
|
||||
typedef struct deque_s
|
||||
{
|
||||
@@ -17,60 +17,56 @@ typedef struct deque_iter_s
|
||||
struct deque_s *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} deque_iter, *deque_iter_ptr;
|
||||
deque *d_new(size_t capacity);
|
||||
void d_clear(deque *_deque_);
|
||||
void d_free(deque *_deque_);
|
||||
bool d_push_front(deque *_deque_, size_t element);
|
||||
bool d_push_back(deque *_deque_, size_t element);
|
||||
bool d_pop_front(deque *_deque_);
|
||||
bool d_pop_back(deque *_deque_);
|
||||
bool d_push_front_if(deque *_deque_, size_t element, bool condition);
|
||||
bool d_push_back_if(deque *_deque_, size_t element, bool condition);
|
||||
bool d_pop_front_if(deque *_deque_, bool condition);
|
||||
bool d_pop_back_if(deque *_deque_, bool condition);
|
||||
void d_clear(deque *_deque_, void (*deallocator)(size_t));
|
||||
void d_free(deque *_deque_, void (*deallocator)(size_t));
|
||||
_Bool d_push_front(deque *_deque_, size_t element);
|
||||
_Bool d_push_back(deque *_deque_, size_t element);
|
||||
_Bool d_pop_front(deque *_deque_);
|
||||
_Bool d_pop_back(deque *_deque_);
|
||||
size_t d_front(deque *_deque_);
|
||||
size_t d_back(deque *_deque_);
|
||||
bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t));
|
||||
bool d_empty(deque *_deque_);
|
||||
bool d_full(deque *_deque_);
|
||||
_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t));
|
||||
_Bool d_empty(deque *_deque_);
|
||||
_Bool d_full(deque *_deque_);
|
||||
size_t d_count(deque *_deque_);
|
||||
size_t d_capacity(deque *_deque_);
|
||||
_Bool d_resize(deque *_deque_, size_t capacity);
|
||||
deque *d_copy_of(deque *_deque_, size_t (*copy_func)(size_t));
|
||||
_Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_t));
|
||||
cmc_string d_to_string(deque *_deque_);
|
||||
deque_iter *d_iter_new(deque *target);
|
||||
void d_iter_free(deque_iter *iter);
|
||||
void d_iter_init(deque_iter *iter, deque *target);
|
||||
bool d_iter_start(deque_iter *iter);
|
||||
bool d_iter_end(deque_iter *iter);
|
||||
_Bool d_iter_start(deque_iter *iter);
|
||||
_Bool d_iter_end(deque_iter *iter);
|
||||
void d_iter_to_start(deque_iter *iter);
|
||||
void d_iter_to_end(deque_iter *iter);
|
||||
bool d_iter_next(deque_iter *iter);
|
||||
bool d_iter_prev(deque_iter *iter);
|
||||
_Bool d_iter_next(deque_iter *iter);
|
||||
_Bool d_iter_prev(deque_iter *iter);
|
||||
_Bool d_iter_advance(deque_iter *iter, size_t steps);
|
||||
_Bool d_iter_rewind(deque_iter *iter, size_t steps);
|
||||
_Bool d_iter_go_to(deque_iter *iter, size_t index);
|
||||
size_t d_iter_value(deque_iter *iter);
|
||||
size_t *d_iter_rvalue(deque_iter *iter);
|
||||
size_t d_iter_index(deque_iter *iter);
|
||||
static inline size_t d_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool d_impl_grow(deque *_deque_);
|
||||
static deque_iter d_impl_it_start(deque *_deque_);
|
||||
static deque_iter d_impl_it_end(deque *_deque_);
|
||||
deque *d_new(size_t capacity)
|
||||
{
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
deque *_deque_ = malloc(sizeof(deque));
|
||||
if (!_deque_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_deque_->buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!_deque_->buffer)
|
||||
{
|
||||
free(_deque_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_deque_->buffer, 0, sizeof(size_t) * capacity);
|
||||
_deque_->capacity = capacity;
|
||||
@@ -81,114 +77,174 @@ deque *d_new(size_t capacity)
|
||||
_deque_->it_end = d_impl_it_end;
|
||||
return _deque_;
|
||||
}
|
||||
void d_clear(deque *_deque_)
|
||||
void d_clear(deque *_deque_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
deallocator(_deque_->buffer[i]);
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
}
|
||||
memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity);
|
||||
_deque_->count = 0;
|
||||
_deque_->front = 0;
|
||||
_deque_->back = 0;
|
||||
}
|
||||
void d_free(deque *_deque_)
|
||||
void d_free(deque *_deque_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
deallocator(_deque_->buffer[i]);
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
}
|
||||
free(_deque_->buffer);
|
||||
free(_deque_);
|
||||
}
|
||||
bool d_push_front(deque *_deque_, size_t element)
|
||||
_Bool d_push_front(deque *_deque_, size_t element)
|
||||
{
|
||||
if (d_full(_deque_))
|
||||
{
|
||||
if (!d_impl_grow(_deque_))
|
||||
return false;
|
||||
if (!d_resize(_deque_, d_capacity(_deque_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1;
|
||||
_deque_->buffer[_deque_->front] = element;
|
||||
_deque_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool d_push_back(deque *_deque_, size_t element)
|
||||
_Bool d_push_back(deque *_deque_, size_t element)
|
||||
{
|
||||
if (d_full(_deque_))
|
||||
{
|
||||
if (!d_impl_grow(_deque_))
|
||||
return false;
|
||||
if (!d_resize(_deque_, d_capacity(_deque_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_deque_->buffer[_deque_->back] = element;
|
||||
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1;
|
||||
_deque_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool d_pop_front(deque *_deque_)
|
||||
_Bool d_pop_front(deque *_deque_)
|
||||
{
|
||||
if (d_empty(_deque_))
|
||||
return false;
|
||||
_deque_->buffer[_deque_->front] = d_impl_default_value();
|
||||
return 0;
|
||||
_deque_->buffer[_deque_->front] = (size_t){0};
|
||||
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1;
|
||||
_deque_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool d_pop_back(deque *_deque_)
|
||||
_Bool d_pop_back(deque *_deque_)
|
||||
{
|
||||
if (d_empty(_deque_))
|
||||
return false;
|
||||
return 0;
|
||||
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1;
|
||||
_deque_->buffer[_deque_->back] = d_impl_default_value();
|
||||
_deque_->buffer[_deque_->back] = (size_t){0};
|
||||
_deque_->count--;
|
||||
return true;
|
||||
}
|
||||
bool d_push_front_if(deque *_deque_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return d_push_front(_deque_, element);
|
||||
return false;
|
||||
}
|
||||
bool d_push_back_if(deque *_deque_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return d_push_back(_deque_, element);
|
||||
return false;
|
||||
}
|
||||
bool d_pop_front_if(deque *_deque_, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return d_pop_front(_deque_);
|
||||
return false;
|
||||
}
|
||||
bool d_pop_back_if(deque *_deque_, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return d_pop_back(_deque_);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
size_t d_front(deque *_deque_)
|
||||
{
|
||||
if (d_empty(_deque_))
|
||||
return d_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _deque_->buffer[_deque_->front];
|
||||
}
|
||||
size_t d_back(deque *_deque_)
|
||||
{
|
||||
if (d_empty(_deque_))
|
||||
return d_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1];
|
||||
}
|
||||
bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t))
|
||||
_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++)
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
if (comparator(_deque_->buffer[i], element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool d_empty(deque *_deque_) { return _deque_->count == 0; }
|
||||
bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; }
|
||||
_Bool d_empty(deque *_deque_) { return _deque_->count == 0; }
|
||||
_Bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; }
|
||||
size_t d_count(deque *_deque_) { return _deque_->count; }
|
||||
size_t d_capacity(deque *_deque_) { return _deque_->capacity; }
|
||||
_Bool d_resize(deque *_deque_, size_t capacity)
|
||||
{
|
||||
if (d_capacity(_deque_) == capacity)
|
||||
return 1;
|
||||
if (capacity < d_count(_deque_))
|
||||
return 0;
|
||||
size_t *new_buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
new_buffer[j] = _deque_->buffer[i];
|
||||
i = (i + 1) % d_capacity(_deque_);
|
||||
}
|
||||
free(_deque_->buffer);
|
||||
_deque_->buffer = new_buffer;
|
||||
_deque_->capacity = capacity;
|
||||
_deque_->front = 0;
|
||||
_deque_->back = _deque_->count;
|
||||
return 1;
|
||||
}
|
||||
deque *d_copy_of(deque *_deque_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
deque *result = d_new(_deque_->capacity);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
result->buffer[j] = copy_func(_deque_->buffer[i]);
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
result->buffer[j] = _deque_->buffer[i];
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
}
|
||||
result->count = _deque_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
if (d_count(_deque1_) != d_count(_deque2_))
|
||||
return 0;
|
||||
size_t i, j, k;
|
||||
for (i = _deque1_->front, j = _deque2_->front, k = 0; k < d_count(_deque1_); k++)
|
||||
{
|
||||
if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) != 0)
|
||||
return 0;
|
||||
i = (i + 1) % _deque1_->capacity;
|
||||
j = (j + 1) % _deque2_->capacity;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string d_to_string(deque *_deque_)
|
||||
{
|
||||
cmc_string str;
|
||||
deque *d_ = _deque_;
|
||||
const char *name = "deque";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back);
|
||||
return str;
|
||||
}
|
||||
deque_iter *d_iter_new(deque *target)
|
||||
{
|
||||
deque_iter *iter = malloc(sizeof(deque_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
d_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -198,86 +254,121 @@ void d_iter_init(deque_iter *iter, deque *target)
|
||||
iter->target = target;
|
||||
iter->cursor = target->front;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = d_empty(target);
|
||||
}
|
||||
bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; }
|
||||
bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; }
|
||||
_Bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; }
|
||||
_Bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; }
|
||||
void d_iter_to_start(deque_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->front;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = d_empty(iter->target);
|
||||
}
|
||||
void d_iter_to_end(deque_iter *iter)
|
||||
{
|
||||
if (d_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->index = 0;
|
||||
}
|
||||
else
|
||||
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1;
|
||||
iter->index = iter->target->count - 1;
|
||||
{
|
||||
if (iter->target->back == 0)
|
||||
iter->cursor = iter->target->capacity - 1;
|
||||
else
|
||||
iter->cursor = iter->target->back - 1;
|
||||
iter->index = d_count(iter->target) - 1;
|
||||
}
|
||||
iter->start = d_empty(iter->target);
|
||||
iter->end = true;
|
||||
iter->end = 1;
|
||||
}
|
||||
bool d_iter_next(deque_iter *iter)
|
||||
_Bool d_iter_next(deque_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = d_empty(iter->target);
|
||||
if (iter->index == iter->target->count - 1)
|
||||
iter->end = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index + 1 == d_count(iter->target))
|
||||
{
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
|
||||
iter->index++;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->start = d_empty(iter->target);
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
|
||||
iter->index++;
|
||||
return 1;
|
||||
}
|
||||
bool d_iter_prev(deque_iter *iter)
|
||||
_Bool d_iter_prev(deque_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = d_empty(iter->target);
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
iter->start = true;
|
||||
else
|
||||
{
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
|
||||
iter->index--;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->end = d_empty(iter->target);
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
|
||||
iter->index--;
|
||||
return 1;
|
||||
}
|
||||
_Bool d_iter_advance(deque_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == d_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= d_count(iter->target))
|
||||
return 0;
|
||||
iter->start = d_empty(iter->target);
|
||||
iter->index += steps;
|
||||
iter->cursor = (iter->cursor + steps) % iter->target->capacity;
|
||||
return 1;
|
||||
}
|
||||
_Bool d_iter_rewind(deque_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
iter->end = d_empty(iter->target);
|
||||
iter->index -= steps;
|
||||
if (iter->cursor < steps)
|
||||
iter->cursor += d_capacity(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool d_iter_go_to(deque_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= d_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return d_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return d_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t d_iter_value(deque_iter *iter)
|
||||
{
|
||||
if (d_empty(iter->target))
|
||||
return d_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t *d_iter_rvalue(deque_iter *iter)
|
||||
{
|
||||
if (d_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->target->buffer[iter->cursor]);
|
||||
}
|
||||
size_t d_iter_index(deque_iter *iter) { return iter->index; }
|
||||
static bool d_impl_grow(deque *_deque_)
|
||||
{
|
||||
size_t new_capacity = _deque_->capacity * 2;
|
||||
size_t *new_buffer = malloc(sizeof(size_t) * new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++)
|
||||
{
|
||||
new_buffer[j] = _deque_->buffer[i];
|
||||
}
|
||||
free(_deque_->buffer);
|
||||
_deque_->buffer = new_buffer;
|
||||
_deque_->capacity = new_capacity;
|
||||
_deque_->front = 0;
|
||||
_deque_->back = _deque_->count;
|
||||
return true;
|
||||
}
|
||||
static deque_iter d_impl_it_start(deque *_deque_)
|
||||
{
|
||||
deque_iter iter;
|
||||
|
||||
+291
-160
@@ -1,6 +1,6 @@
|
||||
#include "cmc/hashmap.h"
|
||||
#include <cmc/hashmap.h>
|
||||
|
||||
//HASHMAP_GENERATE(hm, hashmap, , size_t, size_t)
|
||||
//CMC_GENERATE_HASHMAP(hm, hashmap, size_t, size_t)
|
||||
|
||||
typedef struct hashmap_s
|
||||
{
|
||||
@@ -27,51 +27,45 @@ typedef struct hashmap_iter_s
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} hashmap_iter, *hashmap_iter_ptr;
|
||||
hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
|
||||
void hm_clear(hashmap *_map_);
|
||||
void hm_free(hashmap *_map_);
|
||||
bool hm_insert(hashmap *_map_, size_t key, size_t value);
|
||||
bool hm_remove(hashmap *_map_, size_t key, size_t *value);
|
||||
bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition);
|
||||
bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition);
|
||||
bool hm_max(hashmap *_map_, size_t *key, size_t *value);
|
||||
bool hm_min(hashmap *_map_, size_t *key, size_t *value);
|
||||
void hm_clear(hashmap *_map_, void (*deallocator)(size_t, size_t));
|
||||
void hm_free(hashmap *_map_, void (*deallocator)(size_t, size_t));
|
||||
_Bool hm_insert(hashmap *_map_, size_t key, size_t value);
|
||||
_Bool hm_update(hashmap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
_Bool hm_remove(hashmap *_map_, size_t key, size_t *out_value);
|
||||
_Bool hm_max(hashmap *_map_, size_t *key, size_t *value);
|
||||
_Bool hm_min(hashmap *_map_, size_t *key, size_t *value);
|
||||
size_t hm_get(hashmap *_map_, size_t key);
|
||||
size_t *hm_get_ref(hashmap *_map_, size_t key);
|
||||
bool hm_contains(hashmap *_map_, size_t key);
|
||||
bool hm_empty(hashmap *_map_);
|
||||
_Bool hm_contains(hashmap *_map_, size_t key);
|
||||
_Bool hm_empty(hashmap *_map_);
|
||||
_Bool hm_full(hashmap *_map_);
|
||||
size_t hm_count(hashmap *_map_);
|
||||
size_t hm_capacity(hashmap *_map_);
|
||||
double hm_load(hashmap *_map_);
|
||||
_Bool hm_resize(hashmap *_map_, size_t capacity);
|
||||
hashmap *hm_copy_of(hashmap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t));
|
||||
_Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t, size_t));
|
||||
cmc_string hm_to_string(hashmap *_map_);
|
||||
hashmap_iter *hm_iter_new(hashmap *target);
|
||||
void hm_iter_free(hashmap_iter *iter);
|
||||
void hm_iter_init(hashmap_iter *iter, hashmap *target);
|
||||
bool hm_iter_start(hashmap_iter *iter);
|
||||
bool hm_iter_end(hashmap_iter *iter);
|
||||
_Bool hm_iter_start(hashmap_iter *iter);
|
||||
_Bool hm_iter_end(hashmap_iter *iter);
|
||||
void hm_iter_to_start(hashmap_iter *iter);
|
||||
void hm_iter_to_end(hashmap_iter *iter);
|
||||
bool hm_iter_next(hashmap_iter *iter);
|
||||
bool hm_iter_prev(hashmap_iter *iter);
|
||||
_Bool hm_iter_next(hashmap_iter *iter);
|
||||
_Bool hm_iter_prev(hashmap_iter *iter);
|
||||
_Bool hm_iter_advance(hashmap_iter *iter, size_t steps);
|
||||
_Bool hm_iter_rewind(hashmap_iter *iter, size_t steps);
|
||||
_Bool hm_iter_go_to(hashmap_iter *iter, size_t index);
|
||||
size_t hm_iter_key(hashmap_iter *iter);
|
||||
size_t hm_iter_value(hashmap_iter *iter);
|
||||
size_t *hm_iter_rvalue(hashmap_iter *iter);
|
||||
size_t hm_iter_index(hashmap_iter *iter);
|
||||
static inline size_t hm_impl_default_key(void)
|
||||
{
|
||||
size_t _empty_key_;
|
||||
memset(&_empty_key_, 0, sizeof(size_t));
|
||||
return _empty_key_;
|
||||
}
|
||||
static inline size_t hm_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool hm_impl_grow(hashmap *_map_);
|
||||
static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key);
|
||||
static size_t hm_impl_calculate_size(size_t required);
|
||||
static hashmap_iter hm_impl_it_start(hashmap *_map_);
|
||||
@@ -79,18 +73,18 @@ static hashmap_iter hm_impl_it_end(hashmap *_map_);
|
||||
hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return NULL;
|
||||
if (capacity >= UINTMAX_MAX * load)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
return ((void *)0);
|
||||
size_t real_capacity = hm_impl_calculate_size(capacity / load);
|
||||
hashmap *_map_ = malloc(sizeof(hashmap));
|
||||
if (!_map_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_map_->buffer = malloc(sizeof(hashmap_entry) * real_capacity);
|
||||
if (!_map_->buffer)
|
||||
{
|
||||
free(_map_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_map_->buffer, 0, sizeof(hashmap_entry) * real_capacity);
|
||||
_map_->count = 0;
|
||||
@@ -102,39 +96,61 @@ hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), si
|
||||
_map_->it_end = hm_impl_it_end;
|
||||
return _map_;
|
||||
}
|
||||
void hm_clear(hashmap *_map_)
|
||||
void hm_clear(hashmap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
hashmap_entry *entry = &(_map_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->key, entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(_map_->buffer, 0, sizeof(hashmap_entry) * _map_->capacity);
|
||||
_map_->count = 0;
|
||||
}
|
||||
void hm_free(hashmap *_map_)
|
||||
void hm_free(hashmap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
hashmap_entry *entry = &(_map_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->key, entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(_map_->buffer);
|
||||
free(_map_);
|
||||
}
|
||||
bool hm_insert(hashmap *_map_, size_t key, size_t value)
|
||||
_Bool hm_insert(hashmap *_map_, size_t key, size_t value)
|
||||
{
|
||||
if ((double)_map_->capacity * _map_->load <= (double)_map_->count)
|
||||
if (hm_full(_map_))
|
||||
{
|
||||
if (!hm_impl_grow(_map_))
|
||||
return false;
|
||||
if (!hm_resize(_map_, hm_capacity(_map_) + 1))
|
||||
return 0;
|
||||
}
|
||||
size_t hash = _map_->hash(key);
|
||||
size_t original_pos = hash % _map_->capacity;
|
||||
size_t pos = original_pos;
|
||||
hashmap_entry *target = &(_map_->buffer[pos]);
|
||||
if (hm_impl_get_entry(_map_, key) != NULL)
|
||||
return false;
|
||||
if (hm_impl_get_entry(_map_, key) != ((void *)0))
|
||||
return 0;
|
||||
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
|
||||
{
|
||||
target->key = key;
|
||||
target->value = value;
|
||||
target->dist = original_pos - pos;
|
||||
target->dist = 0;
|
||||
target->state = CMC_ES_FILLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
pos++;
|
||||
target = &(_map_->buffer[pos % _map_->capacity]);
|
||||
@@ -146,7 +162,7 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value)
|
||||
target->state = CMC_ES_FILLED;
|
||||
break;
|
||||
}
|
||||
else if (target->dist < original_pos - pos)
|
||||
else if (target->dist < pos - original_pos)
|
||||
{
|
||||
size_t tmp_k = target->key;
|
||||
size_t tmp_v = target->value;
|
||||
@@ -161,97 +177,192 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value)
|
||||
}
|
||||
}
|
||||
_map_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hm_remove(hashmap *_map_, size_t key, size_t *value)
|
||||
_Bool hm_update(hashmap *_map_, size_t key, size_t new_value, size_t *old_value)
|
||||
{
|
||||
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return 0;
|
||||
if (old_value)
|
||||
*old_value = entry->value;
|
||||
entry->value = new_value;
|
||||
return 1;
|
||||
}
|
||||
_Bool hm_remove(hashmap *_map_, size_t key, size_t *out_value)
|
||||
{
|
||||
hashmap_entry *result = hm_impl_get_entry(_map_, key);
|
||||
if (result == NULL)
|
||||
return false;
|
||||
*value = result->value;
|
||||
result->key = hm_impl_default_key();
|
||||
result->value = hm_impl_default_value();
|
||||
if (result == ((void *)0))
|
||||
return 0;
|
||||
if (out_value)
|
||||
*out_value = result->value;
|
||||
result->key = (size_t){0};
|
||||
result->value = (size_t){0};
|
||||
result->dist = 0;
|
||||
result->state = CMC_ES_DELETED;
|
||||
_map_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return hm_insert(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return hm_remove(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool hm_max(hashmap *_map_, size_t *key, size_t *value)
|
||||
_Bool hm_max(hashmap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (hm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
hashmap_iter iter;
|
||||
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
hm_iter_init(&iter, _map_);
|
||||
size_t max_key = hm_iter_key(&iter);
|
||||
size_t max_val = hm_iter_value(&iter);
|
||||
hm_iter_next(&iter);
|
||||
for (; !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
{
|
||||
size_t result_key = hm_iter_key(&iter);
|
||||
size_t result_value = hm_iter_value(&iter);
|
||||
size_t index = hm_iter_index(&iter);
|
||||
if (index == 0)
|
||||
size_t iter_key = hm_iter_key(&iter);
|
||||
size_t iter_val = hm_iter_value(&iter);
|
||||
if (_map_->cmp(iter_key, max_key) > 0)
|
||||
{
|
||||
*key = result_key;
|
||||
*value = result_value;
|
||||
}
|
||||
else if (_map_->cmp(result_key, *key) > 0)
|
||||
{
|
||||
*key = result_key;
|
||||
*value = result_value;
|
||||
max_key = iter_key;
|
||||
max_val = iter_val;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (key)
|
||||
*key = max_key;
|
||||
if (value)
|
||||
*value = max_val;
|
||||
return 1;
|
||||
}
|
||||
bool hm_min(hashmap *_map_, size_t *key, size_t *value)
|
||||
_Bool hm_min(hashmap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (hm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
hashmap_iter iter;
|
||||
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
hm_iter_init(&iter, _map_);
|
||||
size_t min_key = hm_iter_key(&iter);
|
||||
size_t min_val = hm_iter_value(&iter);
|
||||
hm_iter_next(&iter);
|
||||
for (; !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
{
|
||||
size_t result_key = hm_iter_key(&iter);
|
||||
size_t result_value = hm_iter_value(&iter);
|
||||
size_t index = hm_iter_index(&iter);
|
||||
if (index == 0)
|
||||
size_t iter_key = hm_iter_key(&iter);
|
||||
size_t iter_val = hm_iter_value(&iter);
|
||||
if (_map_->cmp(iter_key, min_key) < 0)
|
||||
{
|
||||
*key = result_key;
|
||||
*value = result_value;
|
||||
}
|
||||
else if (_map_->cmp(result_key, *key) < 0)
|
||||
{
|
||||
*key = result_key;
|
||||
*value = result_value;
|
||||
min_key = iter_key;
|
||||
min_val = iter_val;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (key)
|
||||
*key = min_key;
|
||||
if (value)
|
||||
*value = min_val;
|
||||
return 1;
|
||||
}
|
||||
size_t hm_get(hashmap *_map_, size_t key)
|
||||
{
|
||||
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return hm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return entry->value;
|
||||
}
|
||||
size_t *hm_get_ref(hashmap *_map_, size_t key)
|
||||
{
|
||||
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(entry->value);
|
||||
}
|
||||
bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != NULL; }
|
||||
bool hm_empty(hashmap *_map_) { return _map_->count == 0; }
|
||||
_Bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != ((void *)0); }
|
||||
_Bool hm_empty(hashmap *_map_) { return _map_->count == 0; }
|
||||
_Bool hm_full(hashmap *_map_) { return (double)hm_capacity(_map_) * hm_load(_map_) <= (double)hm_count(_map_); }
|
||||
size_t hm_count(hashmap *_map_) { return _map_->count; }
|
||||
size_t hm_capacity(hashmap *_map_) { return _map_->capacity; }
|
||||
double hm_load(hashmap *_map_) { return _map_->load; }
|
||||
_Bool hm_resize(hashmap *_map_, size_t capacity)
|
||||
{
|
||||
if (hm_capacity(_map_) == capacity)
|
||||
return 1;
|
||||
if (hm_capacity(_map_) > capacity / hm_load(_map_))
|
||||
return 1;
|
||||
if (capacity >= 0xffffffffffffffff * hm_load(_map_))
|
||||
return 0;
|
||||
size_t theoretical_size = hm_impl_calculate_size(capacity);
|
||||
if (theoretical_size < hm_count(_map_) / hm_load(_map_))
|
||||
return 0;
|
||||
hashmap *_new_map_ = hm_new(capacity, hm_load(_map_), _map_->cmp, _map_->hash);
|
||||
if (!_new_map_)
|
||||
return 0;
|
||||
hashmap_iter iter;
|
||||
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
{
|
||||
size_t key = hm_iter_key(&iter);
|
||||
size_t value = hm_iter_value(&iter);
|
||||
hm_insert(_new_map_, key, value);
|
||||
}
|
||||
if (hm_count(_map_) != hm_count(_new_map_))
|
||||
{
|
||||
hm_free(_new_map_, ((void *)0));
|
||||
return 0;
|
||||
}
|
||||
hashmap_entry *tmp_b = _map_->buffer;
|
||||
_map_->buffer = _new_map_->buffer;
|
||||
_new_map_->buffer = tmp_b;
|
||||
size_t tmp_c = _map_->capacity;
|
||||
_map_->capacity = _new_map_->capacity;
|
||||
_new_map_->capacity = tmp_c;
|
||||
hm_free(_new_map_, ((void *)0));
|
||||
return 1;
|
||||
}
|
||||
hashmap *hm_copy_of(hashmap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t))
|
||||
{
|
||||
hashmap *result = hm_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (key_copy_func || value_copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
hashmap_entry *scan = &(_map_->buffer[i]);
|
||||
if (scan->state != CMC_ES_EMPTY)
|
||||
{
|
||||
hashmap_entry *target = &(result->buffer[i]);
|
||||
if (scan->state == CMC_ES_DELETED)
|
||||
target->state = CMC_ES_DELETED;
|
||||
else
|
||||
{
|
||||
target->state = scan->state;
|
||||
target->dist = scan->dist;
|
||||
if (key_copy_func)
|
||||
target->key = key_copy_func(scan->key);
|
||||
else
|
||||
target->key = scan->key;
|
||||
if (value_copy_func)
|
||||
target->value = value_copy_func(scan->value);
|
||||
else
|
||||
target->value = scan->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _map_->buffer, sizeof(hashmap_entry) * _map_->capacity);
|
||||
result->count = _map_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t, size_t))
|
||||
{
|
||||
if (hm_count(_map1_) != hm_count(_map2_))
|
||||
return 0;
|
||||
hashmap_iter iter;
|
||||
hm_iter_init(&iter, _map1_);
|
||||
for (hm_iter_to_start(&iter); !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
{
|
||||
hashmap_entry *entry = hm_impl_get_entry(_map2_, hm_iter_key(&iter));
|
||||
if (entry == ((void *)0))
|
||||
return 0;
|
||||
if (value_comparator)
|
||||
{
|
||||
if (value_comparator(entry->value, hm_iter_value(&iter)) != 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string hm_to_string(hashmap *_map_)
|
||||
{
|
||||
cmc_string str;
|
||||
@@ -264,17 +375,16 @@ hashmap_iter *hm_iter_new(hashmap *target)
|
||||
{
|
||||
hashmap_iter *iter = malloc(sizeof(hashmap_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hm_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void hm_iter_free(hashmap_iter *iter) { free(iter); }
|
||||
void hm_iter_init(hashmap_iter *iter, hashmap *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(hashmap_iter));
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = hm_empty(target);
|
||||
if (!hm_empty(target))
|
||||
{
|
||||
@@ -297,32 +407,39 @@ void hm_iter_init(hashmap_iter *iter, hashmap *target)
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hm_iter_start(hashmap_iter *iter) { return hm_empty(iter->target) || iter->start; }
|
||||
bool hm_iter_end(hashmap_iter *iter) { return hm_empty(iter->target) || iter->end; }
|
||||
_Bool hm_iter_start(hashmap_iter *iter) { return hm_empty(iter->target) || iter->start; }
|
||||
_Bool hm_iter_end(hashmap_iter *iter) { return hm_empty(iter->target) || iter->end; }
|
||||
void hm_iter_to_start(hashmap_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = hm_empty(iter->target);
|
||||
if (!hm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = hm_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void hm_iter_to_end(hashmap_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = hm_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!hm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = hm_count(iter->target) - 1;
|
||||
iter->start = hm_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool hm_iter_next(hashmap_iter *iter)
|
||||
_Bool hm_iter_next(hashmap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->last)
|
||||
return 0;
|
||||
if (iter->index + 1 == hm_count(iter->target))
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = hm_empty(iter->target);
|
||||
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
@@ -331,19 +448,19 @@ bool hm_iter_next(hashmap_iter *iter)
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->start = hm_empty(iter->target);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hm_iter_prev(hashmap_iter *iter)
|
||||
_Bool hm_iter_prev(hashmap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->first)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = hm_empty(iter->target);
|
||||
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
@@ -352,53 +469,67 @@ bool hm_iter_prev(hashmap_iter *iter)
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->end = hm_empty(iter->target);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
_Bool hm_iter_advance(hashmap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == hm_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= hm_count(iter->target))
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
hm_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool hm_iter_rewind(hashmap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
hm_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool hm_iter_go_to(hashmap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= hm_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return hm_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return hm_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t hm_iter_key(hashmap_iter *iter)
|
||||
{
|
||||
if (hm_empty(iter->target))
|
||||
return hm_impl_default_key();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor].key;
|
||||
}
|
||||
size_t hm_iter_value(hashmap_iter *iter)
|
||||
{
|
||||
if (hm_empty(iter->target))
|
||||
return hm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor].value;
|
||||
}
|
||||
size_t *hm_iter_rvalue(hashmap_iter *iter)
|
||||
{
|
||||
if (hm_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->target->buffer[iter->cursor].value);
|
||||
}
|
||||
size_t hm_iter_index(hashmap_iter *iter) { return iter->index; }
|
||||
static bool hm_impl_grow(hashmap *_map_)
|
||||
{
|
||||
size_t new_size = hm_impl_calculate_size(_map_->capacity + _map_->capacity / 2);
|
||||
hashmap *_new_map_ = hm_new(new_size, _map_->load, _map_->cmp, _map_->hash);
|
||||
if (!_new_map_)
|
||||
return false;
|
||||
hashmap_iter iter;
|
||||
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
|
||||
{
|
||||
size_t key = hm_iter_key(&iter);
|
||||
size_t value = hm_iter_value(&iter);
|
||||
hm_insert(_new_map_, key, value);
|
||||
}
|
||||
if (_map_->count != _new_map_->count)
|
||||
{
|
||||
hm_free(_new_map_);
|
||||
return false;
|
||||
}
|
||||
hashmap_entry *tmp = _map_->buffer;
|
||||
_map_->buffer = _new_map_->buffer;
|
||||
_new_map_->buffer = tmp;
|
||||
_map_->capacity = _new_map_->capacity;
|
||||
hm_free(_new_map_);
|
||||
return true;
|
||||
}
|
||||
static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key)
|
||||
{
|
||||
size_t hash = _map_->hash(key);
|
||||
@@ -411,7 +542,7 @@ static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key)
|
||||
pos++;
|
||||
target = &(_map_->buffer[pos % _map_->capacity]);
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
static size_t hm_impl_calculate_size(size_t required)
|
||||
{
|
||||
|
||||
+276
-165
@@ -1,6 +1,6 @@
|
||||
#include "cmc/hashset.h"
|
||||
#include <cmc/hashset.h>
|
||||
|
||||
//HASHSET_GENERATE(hs, hashset, , size_t)
|
||||
//CMC_GENERATE_HASHSET(hs, hashset, size_t)
|
||||
|
||||
typedef struct hashset_s
|
||||
{
|
||||
@@ -26,50 +26,49 @@ typedef struct hashset_iter_s
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} hashset_iter, *hashset_iter_ptr;
|
||||
hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
|
||||
void hs_clear(hashset *_set_);
|
||||
void hs_free(hashset *_set_);
|
||||
bool hs_insert(hashset *_set_, size_t element);
|
||||
bool hs_remove(hashset *_set_, size_t element);
|
||||
bool hs_insert_if(hashset *_set_, size_t element, bool condition);
|
||||
bool hs_remove_if(hashset *_set_, size_t element, bool condition);
|
||||
bool hs_max(hashset *_set_, size_t *value);
|
||||
bool hs_min(hashset *_set_, size_t *value);
|
||||
bool hs_contains(hashset *_set_, size_t element);
|
||||
bool hs_empty(hashset *_set_);
|
||||
void hs_clear(hashset *_set_, void (*deallocator)(size_t));
|
||||
void hs_free(hashset *_set_, void (*deallocator)(size_t));
|
||||
_Bool hs_insert(hashset *_set_, size_t element);
|
||||
_Bool hs_remove(hashset *_set_, size_t element);
|
||||
_Bool hs_max(hashset *_set_, size_t *value);
|
||||
_Bool hs_min(hashset *_set_, size_t *value);
|
||||
_Bool hs_contains(hashset *_set_, size_t element);
|
||||
_Bool hs_empty(hashset *_set_);
|
||||
_Bool hs_full(hashset *_set_);
|
||||
size_t hs_count(hashset *_set_);
|
||||
size_t hs_capacity(hashset *_set_);
|
||||
double hs_load(hashset *_set_);
|
||||
_Bool hs_resize(hashset *_set_, size_t capacity);
|
||||
hashset *hs_copy_of(hashset *_set_, size_t (*copy_func)(size_t));
|
||||
_Bool hs_equals(hashset *_set1_, hashset *_set2_);
|
||||
cmc_string hs_to_string(hashset *_set_);
|
||||
hashset *hs_union(hashset *_set1_, hashset *_set2_);
|
||||
hashset *hs_intersection(hashset *_set1_, hashset *_set2_);
|
||||
hashset *hs_difference(hashset *_set1_, hashset *_set2_);
|
||||
hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_);
|
||||
bool hs_is_subset(hashset *_set1_, hashset *_set2_);
|
||||
bool hs_is_superset(hashset *_set1_, hashset *_set2_);
|
||||
bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_);
|
||||
bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_);
|
||||
bool hs_is_disjointset(hashset *_set1_, hashset *_set2_);
|
||||
_Bool hs_is_subset(hashset *_set1_, hashset *_set2_);
|
||||
_Bool hs_is_superset(hashset *_set1_, hashset *_set2_);
|
||||
_Bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_);
|
||||
_Bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_);
|
||||
_Bool hs_is_disjointset(hashset *_set1_, hashset *_set2_);
|
||||
hashset_iter *hs_iter_new(hashset *target);
|
||||
void hs_iter_free(hashset_iter *iter);
|
||||
void hs_iter_init(hashset_iter *iter, hashset *target);
|
||||
bool hs_iter_start(hashset_iter *iter);
|
||||
bool hs_iter_end(hashset_iter *iter);
|
||||
_Bool hs_iter_start(hashset_iter *iter);
|
||||
_Bool hs_iter_end(hashset_iter *iter);
|
||||
void hs_iter_to_start(hashset_iter *iter);
|
||||
void hs_iter_to_end(hashset_iter *iter);
|
||||
bool hs_iter_next(hashset_iter *iter);
|
||||
bool hs_iter_prev(hashset_iter *iter);
|
||||
_Bool hs_iter_next(hashset_iter *iter);
|
||||
_Bool hs_iter_prev(hashset_iter *iter);
|
||||
_Bool hs_iter_advance(hashset_iter *iter, size_t steps);
|
||||
_Bool hs_iter_rewind(hashset_iter *iter, size_t steps);
|
||||
_Bool hs_iter_go_to(hashset_iter *iter, size_t index);
|
||||
size_t hs_iter_value(hashset_iter *iter);
|
||||
size_t hs_iter_index(hashset_iter *iter);
|
||||
static inline size_t hs_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool hs_impl_grow(hashset *_set_);
|
||||
static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element);
|
||||
static size_t hs_impl_calculate_size(size_t required);
|
||||
static hashset_iter hs_impl_it_start(hashset *_set_);
|
||||
@@ -77,18 +76,18 @@ static hashset_iter hs_impl_it_end(hashset *_set_);
|
||||
hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return NULL;
|
||||
if (capacity >= UINTMAX_MAX * load)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
return ((void *)0);
|
||||
size_t real_capacity = hs_impl_calculate_size(capacity / load);
|
||||
hashset *_set_ = malloc(sizeof(hashset));
|
||||
if (!_set_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_set_->buffer = malloc(sizeof(hashset_entry) * real_capacity);
|
||||
if (!_set_->buffer)
|
||||
{
|
||||
free(_set_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_set_->buffer, 0, sizeof(hashset_entry) * real_capacity);
|
||||
_set_->count = 0;
|
||||
@@ -100,38 +99,60 @@ hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), si
|
||||
_set_->it_end = hs_impl_it_end;
|
||||
return _set_;
|
||||
}
|
||||
void hs_clear(hashset *_set_)
|
||||
void hs_clear(hashset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
hashset_entry *entry = &(_set_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(_set_->buffer, 0, sizeof(hashset_entry) * _set_->capacity);
|
||||
_set_->count = 0;
|
||||
}
|
||||
void hs_free(hashset *_set_)
|
||||
void hs_free(hashset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
hashset_entry *entry = &(_set_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(_set_->buffer);
|
||||
free(_set_);
|
||||
}
|
||||
bool hs_insert(hashset *_set_, size_t element)
|
||||
_Bool hs_insert(hashset *_set_, size_t element)
|
||||
{
|
||||
if ((double)_set_->capacity * _set_->load <= (double)_set_->count)
|
||||
if (hs_full(_set_))
|
||||
{
|
||||
if (!hs_impl_grow(_set_))
|
||||
return false;
|
||||
if (!hs_resize(_set_, hs_capacity(_set_) + 1))
|
||||
return 0;
|
||||
}
|
||||
size_t hash = _set_->hash(element);
|
||||
size_t original_pos = hash % _set_->capacity;
|
||||
size_t pos = original_pos;
|
||||
hashset_entry *target = &(_set_->buffer[pos]);
|
||||
if (hs_impl_get_entry(_set_, element) != NULL)
|
||||
return false;
|
||||
if (hs_impl_get_entry(_set_, element) != ((void *)0))
|
||||
return 0;
|
||||
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
|
||||
{
|
||||
target->value = element;
|
||||
target->dist = pos - original_pos;
|
||||
target->dist = 0;
|
||||
target->state = CMC_ES_FILLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
pos++;
|
||||
target = &(_set_->buffer[pos % _set_->capacity]);
|
||||
@@ -154,35 +175,23 @@ bool hs_insert(hashset *_set_, size_t element)
|
||||
}
|
||||
}
|
||||
_set_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_remove(hashset *_set_, size_t element)
|
||||
_Bool hs_remove(hashset *_set_, size_t element)
|
||||
{
|
||||
hashset_entry *result = hs_impl_get_entry(_set_, element);
|
||||
if (result == NULL)
|
||||
return false;
|
||||
result->value = hs_impl_default_value();
|
||||
if (result == ((void *)0))
|
||||
return 0;
|
||||
result->value = (size_t){0};
|
||||
result->dist = 0;
|
||||
result->state = CMC_ES_DELETED;
|
||||
_set_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_insert_if(hashset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return hs_insert(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool hs_remove_if(hashset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return hs_remove(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool hs_max(hashset *_set_, size_t *value)
|
||||
_Bool hs_max(hashset *_set_, size_t *value)
|
||||
{
|
||||
if (hs_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
hashset_iter iter;
|
||||
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
@@ -193,12 +202,12 @@ bool hs_max(hashset *_set_, size_t *value)
|
||||
else if (_set_->cmp(result, *value) > 0)
|
||||
*value = result;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_min(hashset *_set_, size_t *value)
|
||||
_Bool hs_min(hashset *_set_, size_t *value)
|
||||
{
|
||||
if (hs_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
hashset_iter iter;
|
||||
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
@@ -209,12 +218,92 @@ bool hs_min(hashset *_set_, size_t *value)
|
||||
else if (_set_->cmp(result, *value) < 0)
|
||||
*value = result;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_contains(hashset *_set_, size_t element) { return hs_impl_get_entry(_set_, element) != NULL; }
|
||||
bool hs_empty(hashset *_set_) { return _set_->count == 0; }
|
||||
_Bool hs_contains(hashset *_set_, size_t element) { return hs_impl_get_entry(_set_, element) != ((void *)0); }
|
||||
_Bool hs_empty(hashset *_set_) { return _set_->count == 0; }
|
||||
_Bool hs_full(hashset *_set_) { return (double)hs_capacity(_set_) * hs_load(_set_) <= (double)hs_count(_set_); }
|
||||
size_t hs_count(hashset *_set_) { return _set_->count; }
|
||||
size_t hs_capacity(hashset *_set_) { return _set_->capacity; }
|
||||
double hs_load(hashset *_set_) { return _set_->load; }
|
||||
_Bool hs_resize(hashset *_set_, size_t capacity)
|
||||
{
|
||||
if (hs_capacity(_set_) == capacity)
|
||||
return 1;
|
||||
if (hs_capacity(_set_) > capacity / hs_load(_set_))
|
||||
return 1;
|
||||
if (capacity >= 0xffffffffffffffff * hs_load(_set_))
|
||||
return 0;
|
||||
size_t theoretical_size = hs_impl_calculate_size(capacity);
|
||||
if (theoretical_size < hs_count(_set_) / hs_load(_set_))
|
||||
return 0;
|
||||
hashset *_new_set_ = hs_new(capacity, hs_load(_set_), _set_->cmp, _set_->hash);
|
||||
if (!_new_set_)
|
||||
return 0;
|
||||
hashset_iter iter;
|
||||
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
hs_insert(_new_set_, value);
|
||||
}
|
||||
if (hs_count(_set_) != hs_count(_new_set_))
|
||||
{
|
||||
hs_free(_new_set_, ((void *)0));
|
||||
return 0;
|
||||
}
|
||||
hashset_entry *tmp_b = _set_->buffer;
|
||||
_set_->buffer = _new_set_->buffer;
|
||||
_new_set_->buffer = tmp_b;
|
||||
size_t tmp_c = _set_->capacity;
|
||||
_set_->capacity = _new_set_->capacity;
|
||||
_new_set_->capacity = tmp_c;
|
||||
hs_free(_new_set_, ((void *)0));
|
||||
return 1;
|
||||
}
|
||||
hashset *hs_copy_of(hashset *_set_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
hashset *result = hs_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
hashset_entry *scan = &(_set_->buffer[i]);
|
||||
if (scan->state != CMC_ES_EMPTY)
|
||||
{
|
||||
hashset_entry *target = &(result->buffer[i]);
|
||||
if (scan->state == CMC_ES_DELETED)
|
||||
target->state = CMC_ES_DELETED;
|
||||
else
|
||||
{
|
||||
target->state = scan->state;
|
||||
target->dist = scan->dist;
|
||||
target->value = copy_func(scan->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _set_->buffer, sizeof(hashset_entry) * _set_->capacity);
|
||||
result->count = _set_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool hs_equals(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
if (hs_count(_set1_) != hs_count(_set2_))
|
||||
return 0;
|
||||
if (hs_count(_set1_) == 0)
|
||||
return 1;
|
||||
hashset_iter iter;
|
||||
hs_iter_init(&iter, _set1_);
|
||||
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
if (hs_impl_get_entry(_set2_, hs_iter_value(&iter)) == ((void *)0))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string hs_to_string(hashset *_set_)
|
||||
{
|
||||
cmc_string str;
|
||||
@@ -227,7 +316,7 @@ hashset *hs_union(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hashset_iter iter1, iter2;
|
||||
hs_iter_init(&iter1, _set1_);
|
||||
hs_iter_init(&iter2, _set2_);
|
||||
@@ -245,7 +334,7 @@ hashset *hs_intersection(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
|
||||
hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
|
||||
hashset_iter iter;
|
||||
@@ -253,7 +342,7 @@ hashset *hs_intersection(hashset *_set1_, hashset *_set2_)
|
||||
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
if (hs_impl_get_entry(_set_B_, value) != NULL)
|
||||
if (hs_impl_get_entry(_set_B_, value) != ((void *)0))
|
||||
hs_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
@@ -262,13 +351,13 @@ hashset *hs_difference(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hashset_iter iter;
|
||||
hs_iter_init(&iter, _set1_);
|
||||
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
if (hs_impl_get_entry(_set2_, value) == NULL)
|
||||
if (hs_impl_get_entry(_set2_, value) == ((void *)0))
|
||||
hs_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
@@ -278,50 +367,50 @@ hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_)
|
||||
hashset_iter iter1, iter2;
|
||||
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hs_iter_init(&iter1, _set1_);
|
||||
hs_iter_init(&iter2, _set2_);
|
||||
for (hs_iter_to_start(&iter1); !hs_iter_end(&iter1); hs_iter_next(&iter1))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter1);
|
||||
if (hs_impl_get_entry(_set2_, value) == NULL)
|
||||
if (hs_impl_get_entry(_set2_, value) == ((void *)0))
|
||||
hs_insert(_set_r_, value);
|
||||
}
|
||||
for (hs_iter_to_start(&iter2); !hs_iter_end(&iter2); hs_iter_next(&iter2))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter2);
|
||||
if (hs_impl_get_entry(_set1_, value) == NULL)
|
||||
if (hs_impl_get_entry(_set1_, value) == ((void *)0))
|
||||
hs_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
}
|
||||
bool hs_is_subset(hashset *_set1_, hashset *_set2_)
|
||||
_Bool hs_is_subset(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
if (hs_count(_set1_) > hs_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (hs_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
hashset_iter iter;
|
||||
hs_iter_init(&iter, _set1_);
|
||||
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
if (!hs_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_is_superset(hashset *_set1_, hashset *_set2_) { return hs_is_subset(_set2_, _set1_); }
|
||||
bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_)
|
||||
_Bool hs_is_superset(hashset *_set1_, hashset *_set2_) { return hs_is_subset(_set2_, _set1_); }
|
||||
_Bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
if (hs_count(_set1_) >= hs_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (hs_empty(_set1_))
|
||||
{
|
||||
if (!hs_empty(_set2_))
|
||||
return true;
|
||||
return 1;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
hashset_iter iter;
|
||||
hs_iter_init(&iter, _set1_);
|
||||
@@ -329,40 +418,39 @@ bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
if (!hs_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_) { return hs_is_proper_subset(_set2_, _set1_); }
|
||||
bool hs_is_disjointset(hashset *_set1_, hashset *_set2_)
|
||||
_Bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_) { return hs_is_proper_subset(_set2_, _set1_); }
|
||||
_Bool hs_is_disjointset(hashset *_set1_, hashset *_set2_)
|
||||
{
|
||||
if (hs_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
hashset_iter iter;
|
||||
hs_iter_init(&iter, _set1_);
|
||||
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
size_t value = hs_iter_value(&iter);
|
||||
if (hs_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
hashset_iter *hs_iter_new(hashset *target)
|
||||
{
|
||||
hashset_iter *iter = malloc(sizeof(hashset_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
hs_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void hs_iter_free(hashset_iter *iter) { free(iter); }
|
||||
void hs_iter_init(hashset_iter *iter, hashset *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(hashset_iter));
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = hs_empty(target);
|
||||
if (!hs_empty(target))
|
||||
{
|
||||
@@ -385,94 +473,117 @@ void hs_iter_init(hashset_iter *iter, hashset *target)
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hs_iter_start(hashset_iter *iter) { return hs_empty(iter->target) || iter->start; }
|
||||
bool hs_iter_end(hashset_iter *iter) { return hs_empty(iter->target) || iter->end; }
|
||||
_Bool hs_iter_start(hashset_iter *iter) { return hs_empty(iter->target) || iter->start; }
|
||||
_Bool hs_iter_end(hashset_iter *iter) { return hs_empty(iter->target) || iter->end; }
|
||||
void hs_iter_to_start(hashset_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = hs_empty(iter->target);
|
||||
if (!hs_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = hs_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void hs_iter_to_end(hashset_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = hs_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!hs_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = hs_count(iter->target) - 1;
|
||||
iter->start = hs_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool hs_iter_next(hashset_iter *iter)
|
||||
_Bool hs_iter_next(hashset_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->last)
|
||||
iter->end = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index + 1 == hs_count(iter->target))
|
||||
{
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor++;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = hs_empty(iter->target);
|
||||
return true;
|
||||
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor++;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool hs_iter_prev(hashset_iter *iter)
|
||||
_Bool hs_iter_prev(hashset_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->first)
|
||||
iter->start = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor--;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = hs_empty(iter->target);
|
||||
return true;
|
||||
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor--;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool hs_iter_advance(hashset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == hs_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= hs_count(iter->target))
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
hs_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool hs_iter_rewind(hashset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
hs_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool hs_iter_go_to(hashset_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= hs_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return hs_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return hs_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t hs_iter_value(hashset_iter *iter)
|
||||
{
|
||||
if (hs_empty(iter->target))
|
||||
return hs_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor].value;
|
||||
}
|
||||
size_t hs_iter_index(hashset_iter *iter) { return iter->index; }
|
||||
static bool hs_impl_grow(hashset *_set_)
|
||||
{
|
||||
size_t new_size = hs_impl_calculate_size(_set_->capacity + _set_->capacity / 2);
|
||||
hashset *_new_set_ = hs_new(new_size, _set_->load, _set_->cmp, _set_->hash);
|
||||
if (!_new_set_)
|
||||
return false;
|
||||
hashset_iter iter;
|
||||
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
|
||||
{
|
||||
hs_insert(_new_set_, hs_iter_value(&iter));
|
||||
}
|
||||
if (_set_->count != _new_set_->count)
|
||||
{
|
||||
hs_free(_new_set_);
|
||||
return false;
|
||||
}
|
||||
hashset_entry *tmp = _set_->buffer;
|
||||
_set_->buffer = _new_set_->buffer;
|
||||
_new_set_->buffer = tmp;
|
||||
_set_->capacity = _new_set_->capacity;
|
||||
hs_free(_new_set_);
|
||||
return true;
|
||||
}
|
||||
static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element)
|
||||
{
|
||||
size_t hash = _set_->hash(element);
|
||||
@@ -485,7 +596,7 @@ static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element)
|
||||
pos++;
|
||||
target = &(_set_->buffer[pos % _set_->capacity]);
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
static size_t hs_impl_calculate_size(size_t required)
|
||||
{
|
||||
|
||||
+196
-113
@@ -1,6 +1,6 @@
|
||||
#include "cmc/heap.h"
|
||||
#include <cmc/heap.h>
|
||||
|
||||
//HEAP_GENERATE(h, heap, , size_t)
|
||||
//CMC_GENERATE_HEAP(h, heap, size_t)
|
||||
|
||||
typedef struct heap_s
|
||||
{
|
||||
@@ -16,59 +16,56 @@ typedef struct heap_iter_s
|
||||
{
|
||||
struct heap_s *target;
|
||||
size_t cursor;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} heap_iter, *heap_iter_ptr;
|
||||
heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t));
|
||||
void h_clear(heap *_heap_);
|
||||
void h_free(heap *_heap_);
|
||||
bool h_insert(heap *_heap_, size_t element);
|
||||
bool h_remove(heap *_heap_, size_t *result);
|
||||
bool h_insert_if(heap *_heap_, size_t element, bool condition);
|
||||
bool h_remove_if(heap *_heap_, size_t *result, bool condition);
|
||||
void h_clear(heap *_heap_, void (*deallocator)(size_t));
|
||||
void h_free(heap *_heap_, void (*deallocator)(size_t));
|
||||
_Bool h_insert(heap *_heap_, size_t element);
|
||||
_Bool h_remove(heap *_heap_, size_t *result);
|
||||
size_t h_peek(heap *_heap_);
|
||||
size_t *h_peek_ref(heap *_heap_);
|
||||
bool h_contains(heap *_heap_, size_t element);
|
||||
bool h_empty(heap *_heap_);
|
||||
bool h_full(heap *_heap_);
|
||||
_Bool h_contains(heap *_heap_, size_t element);
|
||||
_Bool h_empty(heap *_heap_);
|
||||
_Bool h_full(heap *_heap_);
|
||||
size_t h_count(heap *_heap_);
|
||||
size_t h_capacity(heap *_heap_);
|
||||
_Bool h_resize(heap *_heap_, size_t capacity);
|
||||
heap *h_copy_of(heap *_heap_, size_t (*copy_func)(size_t));
|
||||
_Bool h_equals(heap *_heap1_, heap *_heap2_);
|
||||
cmc_string h_to_string(heap *_heap_);
|
||||
heap_iter *h_iter_new(heap *target);
|
||||
void h_iter_free(heap_iter *iter);
|
||||
void h_iter_init(heap_iter *iter, heap *target);
|
||||
bool h_iter_start(heap_iter *iter);
|
||||
bool h_iter_end(heap_iter *iter);
|
||||
_Bool h_iter_start(heap_iter *iter);
|
||||
_Bool h_iter_end(heap_iter *iter);
|
||||
void h_iter_to_start(heap_iter *iter);
|
||||
void h_iter_to_end(heap_iter *iter);
|
||||
bool h_iter_next(heap_iter *iter);
|
||||
bool h_iter_prev(heap_iter *iter);
|
||||
_Bool h_iter_next(heap_iter *iter);
|
||||
_Bool h_iter_prev(heap_iter *iter);
|
||||
_Bool h_iter_advance(heap_iter *iter, size_t steps);
|
||||
_Bool h_iter_rewind(heap_iter *iter, size_t steps);
|
||||
_Bool h_iter_go_to(heap_iter *iter, size_t index);
|
||||
size_t h_iter_value(heap_iter *iter);
|
||||
size_t h_iter_index(heap_iter *iter);
|
||||
static inline size_t h_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool h_impl_grow(heap *_heap_);
|
||||
static bool h_impl_float_up(heap *_heap_, size_t index);
|
||||
static bool h_impl_float_down(heap *_heap_, size_t index);
|
||||
static _Bool h_impl_float_up(heap *_heap_, size_t index);
|
||||
static _Bool h_impl_float_down(heap *_heap_, size_t index);
|
||||
static heap_iter h_impl_it_start(heap *_heap_);
|
||||
static heap_iter h_impl_it_end(heap *_heap_);
|
||||
heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t))
|
||||
{
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (HO != cmc_min_heap && HO != cmc_max_heap)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
heap *_heap_ = malloc(sizeof(heap));
|
||||
if (!_heap_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_heap_->buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!_heap_->buffer)
|
||||
{
|
||||
free(_heap_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_heap_->buffer, 0, sizeof(size_t) * capacity);
|
||||
_heap_->capacity = capacity;
|
||||
@@ -79,87 +76,131 @@ heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t))
|
||||
_heap_->it_end = h_impl_it_end;
|
||||
return _heap_;
|
||||
}
|
||||
void h_clear(heap *_heap_)
|
||||
void h_clear(heap *_heap_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
deallocator(_heap_->buffer[i]);
|
||||
}
|
||||
}
|
||||
memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity);
|
||||
_heap_->count = 0;
|
||||
}
|
||||
void h_free(heap *_heap_)
|
||||
void h_free(heap *_heap_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
deallocator(_heap_->buffer[i]);
|
||||
}
|
||||
}
|
||||
free(_heap_->buffer);
|
||||
free(_heap_);
|
||||
}
|
||||
bool h_insert(heap *_heap_, size_t element)
|
||||
_Bool h_insert(heap *_heap_, size_t element)
|
||||
{
|
||||
if (h_full(_heap_))
|
||||
{
|
||||
if (!h_impl_grow(_heap_))
|
||||
return false;
|
||||
if (!h_resize(_heap_, h_count(_heap_) * 2))
|
||||
return 0;
|
||||
}
|
||||
if (_heap_->count == 0)
|
||||
if (h_empty(_heap_))
|
||||
{
|
||||
_heap_->buffer[_heap_->count++] = element;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
_heap_->buffer[_heap_->count++] = element;
|
||||
if (!h_impl_float_up(_heap_, _heap_->count - 1))
|
||||
return false;
|
||||
return true;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
bool h_remove(heap *_heap_, size_t *result)
|
||||
_Bool h_remove(heap *_heap_, size_t *result)
|
||||
{
|
||||
if (h_empty(_heap_))
|
||||
return false;
|
||||
return 0;
|
||||
*result = _heap_->buffer[0];
|
||||
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1];
|
||||
_heap_->buffer[_heap_->count - 1] = h_impl_default_value();
|
||||
_heap_->buffer[_heap_->count - 1] = (size_t){0};
|
||||
_heap_->count--;
|
||||
if (!h_impl_float_down(_heap_, 0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool h_insert_if(heap *_heap_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return h_insert(_heap_, element);
|
||||
return false;
|
||||
}
|
||||
bool h_remove_if(heap *_heap_, size_t *result, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return h_remove(_heap_, result);
|
||||
return false;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
size_t h_peek(heap *_heap_)
|
||||
{
|
||||
if (h_empty(_heap_))
|
||||
return h_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _heap_->buffer[0];
|
||||
}
|
||||
size_t *h_peek_ref(heap *_heap_)
|
||||
{
|
||||
if (h_empty(_heap_))
|
||||
return NULL;
|
||||
return &(_heap_->buffer[0]);
|
||||
}
|
||||
bool h_contains(heap *_heap_, size_t element)
|
||||
_Bool h_contains(heap *_heap_, size_t element)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (_heap_->cmp(_heap_->buffer[i], element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool h_empty(heap *_heap_) { return _heap_->count == 0; }
|
||||
bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; }
|
||||
_Bool h_empty(heap *_heap_) { return _heap_->count == 0; }
|
||||
_Bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; }
|
||||
size_t h_count(heap *_heap_) { return _heap_->count; }
|
||||
size_t h_capacity(heap *_heap_) { return _heap_->capacity; }
|
||||
_Bool h_resize(heap *_heap_, size_t capacity)
|
||||
{
|
||||
if (h_capacity(_heap_) == capacity)
|
||||
return 1;
|
||||
if (capacity < h_count(_heap_))
|
||||
return 0;
|
||||
size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
_heap_->buffer = new_buffer;
|
||||
_heap_->capacity = capacity;
|
||||
return 1;
|
||||
}
|
||||
heap *h_copy_of(heap *_heap_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
heap *result = h_new(_heap_->capacity, _heap_->HO, _heap_->cmp);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
result->buffer[i] = copy_func(_heap_->buffer[i]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _heap_->buffer, sizeof(size_t) * _heap_->count);
|
||||
result->count = _heap_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool h_equals(heap *_heap1_, heap *_heap2_)
|
||||
{
|
||||
if (h_count(_heap1_) != h_count(_heap2_))
|
||||
return 0;
|
||||
for (size_t i = 0; i < h_count(_heap1_); i++)
|
||||
{
|
||||
if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string h_to_string(heap *_heap_)
|
||||
{
|
||||
cmc_string str;
|
||||
heap *h_ = _heap_;
|
||||
const char *name = "heap";
|
||||
const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, name, h_, h_->buffer, h_->capacity, h_->count, t, h_->cmp);
|
||||
return str;
|
||||
}
|
||||
heap_iter *h_iter_new(heap *target)
|
||||
{
|
||||
heap_iter *iter = malloc(sizeof(heap_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
h_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -168,63 +209,105 @@ void h_iter_init(heap_iter *iter, heap *target)
|
||||
{
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = h_empty(target);
|
||||
}
|
||||
bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; }
|
||||
bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; }
|
||||
_Bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; }
|
||||
_Bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; }
|
||||
void h_iter_to_start(heap_iter *iter)
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->end = h_empty(iter->target);
|
||||
if (!h_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = h_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void h_iter_to_end(heap_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = h_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!h_empty(iter->target))
|
||||
{
|
||||
iter->cursor = h_count(iter->target) - 1;
|
||||
iter->start = h_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool h_iter_next(heap_iter *iter)
|
||||
_Bool h_iter_next(heap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = false;
|
||||
if (iter->cursor == iter->target->count - 1)
|
||||
iter->end = true;
|
||||
else
|
||||
iter->cursor++;
|
||||
return true;
|
||||
return 0;
|
||||
if (iter->cursor + 1 == h_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = h_empty(iter->target);
|
||||
iter->cursor++;
|
||||
return 1;
|
||||
}
|
||||
bool h_iter_prev(heap_iter *iter)
|
||||
_Bool h_iter_prev(heap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = false;
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
iter->start = true;
|
||||
else
|
||||
iter->cursor--;
|
||||
return true;
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = h_empty(iter->target);
|
||||
iter->cursor--;
|
||||
return 1;
|
||||
}
|
||||
_Bool h_iter_advance(heap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == h_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor + steps >= h_count(iter->target))
|
||||
return 0;
|
||||
iter->start = h_empty(iter->target);
|
||||
if (iter->end)
|
||||
return 0;
|
||||
iter->cursor += steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool h_iter_rewind(heap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return 0;
|
||||
iter->end = h_empty(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool h_iter_go_to(heap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= h_count(iter->target))
|
||||
return 0;
|
||||
if (iter->cursor > index)
|
||||
return h_iter_rewind(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return h_iter_advance(iter, index - iter->cursor);
|
||||
return 1;
|
||||
}
|
||||
size_t h_iter_value(heap_iter *iter)
|
||||
{
|
||||
if (h_empty(iter->target))
|
||||
return h_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t h_iter_index(heap_iter *iter) { return iter->cursor; }
|
||||
static bool h_impl_grow(heap *_heap_)
|
||||
{
|
||||
size_t new_capacity = _heap_->capacity * 2;
|
||||
size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
_heap_->buffer = new_buffer;
|
||||
_heap_->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
static bool h_impl_float_up(heap *_heap_, size_t index)
|
||||
static _Bool h_impl_float_up(heap *_heap_, size_t index)
|
||||
{
|
||||
size_t C = index;
|
||||
size_t child = _heap_->buffer[C];
|
||||
@@ -233,15 +316,15 @@ static bool h_impl_float_up(heap *_heap_, size_t index)
|
||||
while (C > 0 && _heap_->cmp(child, parent) * mod > 0)
|
||||
{
|
||||
size_t tmp = _heap_->buffer[C];
|
||||
_heap_->buffer[C] = _heap_->buffer[(index - 1) / 2];
|
||||
_heap_->buffer[(index - 1) / 2] = tmp;
|
||||
C = (index - 1) / 2;
|
||||
_heap_->buffer[C] = _heap_->buffer[(C - 1) / 2];
|
||||
_heap_->buffer[(C - 1) / 2] = tmp;
|
||||
C = (C - 1) / 2;
|
||||
child = _heap_->buffer[C];
|
||||
parent = _heap_->buffer[(index - 1) / 2];
|
||||
parent = _heap_->buffer[(C - 1) / 2];
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
static bool h_impl_float_down(heap *_heap_, size_t index)
|
||||
static _Bool h_impl_float_down(heap *_heap_, size_t index)
|
||||
{
|
||||
int mod = _heap_->HO;
|
||||
while (index < _heap_->count)
|
||||
@@ -267,7 +350,7 @@ static bool h_impl_float_down(heap *_heap_, size_t index)
|
||||
else
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
static heap_iter h_impl_it_start(heap *_heap_)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,588 @@
|
||||
#include <cmc/intervalheap.h>
|
||||
|
||||
//CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t)
|
||||
|
||||
typedef struct intervalheap_s
|
||||
{
|
||||
struct intervalheap_node_s *buffer;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
size_t count;
|
||||
int (*cmp)(size_t, size_t);
|
||||
struct intervalheap_iter_s (*it_start)(struct intervalheap_s *);
|
||||
struct intervalheap_iter_s (*it_end)(struct intervalheap_s *);
|
||||
} intervalheap, *intervalheap_ptr;
|
||||
typedef struct intervalheap_node_s
|
||||
{
|
||||
size_t data[2];
|
||||
} intervalheap_node, *intervalheap_node_ptr;
|
||||
typedef struct intervalheap_iter_s
|
||||
{
|
||||
struct intervalheap_s *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} intervalheap_iter, *intervalheap_iter_ptr;
|
||||
intervalheap *ih_new(size_t capacity, int (*compare)(size_t, size_t));
|
||||
void ih_clear(intervalheap *_heap_, void (*deallocator)(size_t));
|
||||
void ih_free(intervalheap *_heap_, void (*deallocator)(size_t));
|
||||
_Bool ih_insert(intervalheap *_heap_, size_t element);
|
||||
_Bool ih_remove_max(intervalheap *_heap_, size_t *result);
|
||||
_Bool ih_remove_min(intervalheap *_heap_, size_t *result);
|
||||
_Bool ih_update_max(intervalheap *_heap_, size_t element);
|
||||
_Bool ih_update_min(intervalheap *_heap_, size_t element);
|
||||
_Bool ih_max(intervalheap *_heap_, size_t *value);
|
||||
_Bool ih_min(intervalheap *_heap_, size_t *value);
|
||||
_Bool ih_contains(intervalheap *_heap_, size_t element);
|
||||
_Bool ih_empty(intervalheap *_heap_);
|
||||
_Bool ih_full(intervalheap *_heap_);
|
||||
size_t ih_count(intervalheap *_heap_);
|
||||
size_t ih_capacity(intervalheap *_heap_);
|
||||
_Bool ih_resize(intervalheap *_heap_, size_t capacity);
|
||||
intervalheap *ih_copy_of(intervalheap *_set_, size_t (*copy_func)(size_t));
|
||||
_Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_);
|
||||
cmc_string ih_to_string(intervalheap *_heap_);
|
||||
intervalheap_iter *ih_iter_new(intervalheap *target);
|
||||
void ih_iter_free(intervalheap_iter *iter);
|
||||
void ih_iter_init(intervalheap_iter *iter, intervalheap *target);
|
||||
_Bool ih_iter_start(intervalheap_iter *iter);
|
||||
_Bool ih_iter_end(intervalheap_iter *iter);
|
||||
void ih_iter_to_start(intervalheap_iter *iter);
|
||||
void ih_iter_to_end(intervalheap_iter *iter);
|
||||
_Bool ih_iter_next(intervalheap_iter *iter);
|
||||
_Bool ih_iter_prev(intervalheap_iter *iter);
|
||||
_Bool ih_iter_advance(intervalheap_iter *iter, size_t steps);
|
||||
_Bool ih_iter_rewind(intervalheap_iter *iter, size_t steps);
|
||||
_Bool ih_iter_go_to(intervalheap_iter *iter, size_t index);
|
||||
size_t ih_iter_value(intervalheap_iter *iter);
|
||||
size_t ih_iter_index(intervalheap_iter *iter);
|
||||
static void ih_impl_float_up_max(intervalheap *_heap_);
|
||||
static void ih_impl_float_up_min(intervalheap *_heap_);
|
||||
static void ih_impl_float_down_max(intervalheap *_heap_);
|
||||
static void ih_impl_float_down_min(intervalheap *_heap_);
|
||||
static intervalheap_iter ih_impl_it_start(intervalheap *_heap_);
|
||||
static intervalheap_iter ih_impl_it_end(intervalheap *_heap_);
|
||||
intervalheap *ih_new(size_t capacity, int (*compare)(size_t, size_t))
|
||||
{
|
||||
if (capacity == 0 || capacity == 0xffffffffffffffff)
|
||||
return ((void *)0);
|
||||
intervalheap *_heap_ = malloc(sizeof(intervalheap));
|
||||
if (!_heap_)
|
||||
return ((void *)0);
|
||||
capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2;
|
||||
_heap_->buffer = malloc(sizeof(intervalheap_node) * capacity);
|
||||
if (!_heap_->buffer)
|
||||
{
|
||||
free(_heap_);
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_heap_->buffer, 0, sizeof(intervalheap_node) * capacity);
|
||||
_heap_->capacity = capacity;
|
||||
_heap_->size = 0;
|
||||
_heap_->count = 0;
|
||||
_heap_->cmp = compare;
|
||||
_heap_->it_start = ih_impl_it_start;
|
||||
_heap_->it_end = ih_impl_it_end;
|
||||
return _heap_;
|
||||
}
|
||||
void ih_clear(intervalheap *_heap_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
deallocator(_heap_->buffer[i / 2].data[i % 2]);
|
||||
}
|
||||
}
|
||||
memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity);
|
||||
_heap_->size = 0;
|
||||
_heap_->count = 0;
|
||||
}
|
||||
void ih_free(intervalheap *_heap_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
deallocator(_heap_->buffer[i / 2].data[i % 2]);
|
||||
}
|
||||
}
|
||||
free(_heap_->buffer);
|
||||
free(_heap_);
|
||||
}
|
||||
_Bool ih_insert(intervalheap *_heap_, size_t element)
|
||||
{
|
||||
if (ih_full(_heap_))
|
||||
{
|
||||
if (!ih_resize(_heap_, ih_capacity(_heap_) * 4))
|
||||
return 0;
|
||||
}
|
||||
if (ih_count(_heap_) % 2 == 0)
|
||||
{
|
||||
_heap_->buffer[_heap_->size].data[0] = element;
|
||||
_heap_->buffer[_heap_->size].data[1] = (size_t){0};
|
||||
_heap_->size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
intervalheap_node *curr_node = &(_heap_->buffer[_heap_->size - 1]);
|
||||
if (_heap_->cmp(curr_node->data[0], element) > 0)
|
||||
{
|
||||
curr_node->data[1] = curr_node->data[0];
|
||||
curr_node->data[0] = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_node->data[1] = element;
|
||||
}
|
||||
}
|
||||
_heap_->count++;
|
||||
if (ih_count(_heap_) <= 2)
|
||||
return 1;
|
||||
intervalheap_node *parent = &(_heap_->buffer[(_heap_->size - 1) / 2]);
|
||||
if (_heap_->cmp(parent->data[0], element) > 0)
|
||||
ih_impl_float_up_min(_heap_);
|
||||
else if (_heap_->cmp(parent->data[1], element) < 0)
|
||||
ih_impl_float_up_max(_heap_);
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_remove_max(intervalheap *_heap_, size_t *result)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
if (ih_count(_heap_) == 1)
|
||||
{
|
||||
*result = _heap_->buffer[0].data[0];
|
||||
_heap_->buffer[0].data[0] = (size_t){0};
|
||||
_heap_->count--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
*result = _heap_->buffer[0].data[1];
|
||||
intervalheap_node *last_node = &(_heap_->buffer[_heap_->size - 1]);
|
||||
if (ih_count(_heap_) % 2 == 1)
|
||||
{
|
||||
_heap_->buffer[0].data[1] = last_node->data[0];
|
||||
last_node->data[0] = (size_t){0};
|
||||
_heap_->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
_heap_->buffer[0].data[1] = last_node->data[1];
|
||||
last_node->data[1] = (size_t){0};
|
||||
}
|
||||
_heap_->count--;
|
||||
ih_impl_float_down_max(_heap_);
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_remove_min(intervalheap *_heap_, size_t *result)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
*result = _heap_->buffer[0].data[0];
|
||||
if (ih_count(_heap_) == 1)
|
||||
{
|
||||
_heap_->buffer[0].data[0] = (size_t){0};
|
||||
_heap_->count--;
|
||||
return 1;
|
||||
}
|
||||
intervalheap_node *last_node = &(_heap_->buffer[_heap_->size - 1]);
|
||||
_heap_->buffer[0].data[0] = last_node->data[0];
|
||||
if (ih_count(_heap_) % 2 == 1)
|
||||
{
|
||||
last_node->data[0] = (size_t){0};
|
||||
_heap_->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_node->data[0] = last_node->data[1];
|
||||
last_node->data[1] = (size_t){0};
|
||||
}
|
||||
_heap_->count--;
|
||||
ih_impl_float_down_min(_heap_);
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_update_max(intervalheap *_heap_, size_t element)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
if (ih_count(_heap_) == 1)
|
||||
{
|
||||
_heap_->buffer[0].data[0] = element;
|
||||
}
|
||||
else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0)
|
||||
{
|
||||
_heap_->buffer[0].data[1] = _heap_->buffer[0].data[0];
|
||||
_heap_->buffer[0].data[0] = element;
|
||||
ih_impl_float_down_max(_heap_);
|
||||
}
|
||||
else
|
||||
{
|
||||
_heap_->buffer[0].data[1] = element;
|
||||
ih_impl_float_down_max(_heap_);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_update_min(intervalheap *_heap_, size_t element)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
if (ih_count(_heap_) == 1)
|
||||
{
|
||||
_heap_->buffer[0].data[0] = element;
|
||||
}
|
||||
else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0)
|
||||
{
|
||||
_heap_->buffer[0].data[0] = _heap_->buffer[0].data[1];
|
||||
_heap_->buffer[0].data[1] = element;
|
||||
ih_impl_float_down_min(_heap_);
|
||||
}
|
||||
else
|
||||
{
|
||||
_heap_->buffer[0].data[0] = element;
|
||||
ih_impl_float_down_min(_heap_);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_max(intervalheap *_heap_, size_t *value)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
if (ih_count(_heap_) == 1)
|
||||
*value = _heap_->buffer[0].data[0];
|
||||
else
|
||||
*value = _heap_->buffer[0].data[1];
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_min(intervalheap *_heap_, size_t *value)
|
||||
{
|
||||
if (ih_empty(_heap_))
|
||||
return 0;
|
||||
*value = _heap_->buffer[0].data[0];
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_contains(intervalheap *_heap_, size_t element)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
{
|
||||
if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_Bool ih_empty(intervalheap *_heap_) { return _heap_->count == 0; }
|
||||
_Bool ih_full(intervalheap *_heap_) { return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; }
|
||||
size_t ih_count(intervalheap *_heap_) { return _heap_->count; }
|
||||
size_t ih_capacity(intervalheap *_heap_) { return _heap_->capacity; }
|
||||
_Bool ih_resize(intervalheap *_heap_, size_t capacity)
|
||||
{
|
||||
if (ih_capacity(_heap_) == capacity)
|
||||
return 1;
|
||||
if (capacity < ih_count(_heap_))
|
||||
return 0;
|
||||
capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2;
|
||||
intervalheap_node *new_buffer = realloc(_heap_->buffer, sizeof(intervalheap_node) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
memset(new_buffer + _heap_->capacity, 0, sizeof(intervalheap_node) * _heap_->capacity);
|
||||
_heap_->buffer = new_buffer;
|
||||
_heap_->capacity = capacity;
|
||||
return 1;
|
||||
}
|
||||
intervalheap *ih_copy_of(intervalheap *_heap_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
intervalheap *result = malloc(sizeof(intervalheap));
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
memcpy(result, _heap_, sizeof(intervalheap));
|
||||
result->buffer = malloc(sizeof(intervalheap_node) * _heap_->capacity);
|
||||
if (!result->buffer)
|
||||
{
|
||||
free(result);
|
||||
return ((void *)0);
|
||||
}
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _heap_->count; i++)
|
||||
result->buffer[i / 2].data[i % 2] = copy_func(_heap_->buffer[i / 2].data[i % 2]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _heap_->buffer, sizeof(intervalheap_node) * _heap_->capacity);
|
||||
return result;
|
||||
}
|
||||
_Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_)
|
||||
{
|
||||
if (ih_count(_heap1_) != ih_count(_heap2_))
|
||||
return 0;
|
||||
for (size_t i = 0; i < _heap1_->count; i++)
|
||||
{
|
||||
size_t element1 = _heap1_->buffer[i / 2].data[i % 2];
|
||||
size_t element2 = _heap2_->buffer[i / 2].data[i % 2];
|
||||
if (_heap1_->cmp(element1, element2) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cmc_string ih_to_string(intervalheap *_heap_)
|
||||
{
|
||||
cmc_string str;
|
||||
intervalheap *h_ = _heap_;
|
||||
const char *name = "intervalheap";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp);
|
||||
return str;
|
||||
}
|
||||
intervalheap_iter *ih_iter_new(intervalheap *target)
|
||||
{
|
||||
intervalheap_iter *iter = malloc(sizeof(intervalheap_iter));
|
||||
if (!iter)
|
||||
return ((void *)0);
|
||||
ih_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void ih_iter_free(intervalheap_iter *iter) { free(iter); }
|
||||
void ih_iter_init(intervalheap_iter *iter, intervalheap *target)
|
||||
{
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = ih_empty(target);
|
||||
}
|
||||
_Bool ih_iter_start(intervalheap_iter *iter) { return ih_empty(iter->target) || iter->start; }
|
||||
_Bool ih_iter_end(intervalheap_iter *iter) { return ih_empty(iter->target) || iter->end; }
|
||||
void ih_iter_to_start(intervalheap_iter *iter)
|
||||
{
|
||||
if (!ih_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = ih_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void ih_iter_to_end(intervalheap_iter *iter)
|
||||
{
|
||||
if (!ih_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = ih_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
_Bool ih_iter_next(intervalheap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == ih_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = ih_empty(iter->target);
|
||||
iter->cursor++;
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_iter_prev(intervalheap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = ih_empty(iter->target);
|
||||
iter->cursor--;
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_iter_advance(intervalheap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor + steps >= ih_count(iter->target))
|
||||
return 0;
|
||||
iter->start = ih_empty(iter->target);
|
||||
iter->cursor += steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_iter_rewind(intervalheap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return 0;
|
||||
iter->end = ih_empty(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool ih_iter_go_to(intervalheap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= ih_count(iter->target))
|
||||
return 0;
|
||||
if (iter->cursor > index)
|
||||
return ih_iter_rewind(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return ih_iter_advance(iter, index - iter->cursor);
|
||||
return 1;
|
||||
}
|
||||
size_t ih_iter_value(intervalheap_iter *iter)
|
||||
{
|
||||
if (ih_empty(iter->target))
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2];
|
||||
}
|
||||
size_t ih_iter_index(intervalheap_iter *iter) { return iter->cursor; }
|
||||
static void ih_impl_float_up_max(intervalheap *_heap_)
|
||||
{
|
||||
size_t index = _heap_->size - 1;
|
||||
intervalheap_node *curr_node = &(_heap_->buffer[index]);
|
||||
while (index > 0)
|
||||
{
|
||||
size_t P_index = (index - 1) / 2;
|
||||
intervalheap_node *parent = &(_heap_->buffer[P_index]);
|
||||
if (index == _heap_->size - 1 && ih_count(_heap_) % 2 != 0)
|
||||
{
|
||||
if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0)
|
||||
break;
|
||||
size_t tmp = curr_node->data[0];
|
||||
curr_node->data[0] = parent->data[1];
|
||||
parent->data[1] = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0)
|
||||
break;
|
||||
size_t tmp = curr_node->data[1];
|
||||
curr_node->data[1] = parent->data[1];
|
||||
parent->data[1] = tmp;
|
||||
}
|
||||
index = P_index;
|
||||
curr_node = parent;
|
||||
}
|
||||
}
|
||||
static void ih_impl_float_up_min(intervalheap *_heap_)
|
||||
{
|
||||
size_t index = _heap_->size - 1;
|
||||
intervalheap_node *curr_node = &(_heap_->buffer[index]);
|
||||
while (index > 0)
|
||||
{
|
||||
size_t P_index = (index - 1) / 2;
|
||||
intervalheap_node *parent = &(_heap_->buffer[P_index]);
|
||||
if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0)
|
||||
break;
|
||||
size_t tmp = curr_node->data[0];
|
||||
curr_node->data[0] = parent->data[0];
|
||||
parent->data[0] = tmp;
|
||||
index = P_index;
|
||||
curr_node = parent;
|
||||
}
|
||||
}
|
||||
static void ih_impl_float_down_max(intervalheap *_heap_)
|
||||
{
|
||||
size_t index = 0;
|
||||
intervalheap_node *curr_node = &(_heap_->buffer[index]);
|
||||
while (1)
|
||||
{
|
||||
if (2 * index + 1 >= _heap_->size)
|
||||
break;
|
||||
size_t child;
|
||||
size_t L_index = index * 2 + 1;
|
||||
size_t R_index = index * 2 + 2;
|
||||
if (R_index < _heap_->size)
|
||||
{
|
||||
intervalheap_node *L = &(_heap_->buffer[L_index]);
|
||||
intervalheap_node *R = &(_heap_->buffer[R_index]);
|
||||
if (R_index == _heap_->size - 1 && ih_count(_heap_) % 2 != 0)
|
||||
child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index : R_index;
|
||||
else
|
||||
child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index : R_index;
|
||||
}
|
||||
else
|
||||
child = L_index;
|
||||
intervalheap_node *child_node = &(_heap_->buffer[child]);
|
||||
if (child == _heap_->size - 1 && ih_count(_heap_) % 2 != 0)
|
||||
{
|
||||
if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0)
|
||||
break;
|
||||
size_t tmp = child_node->data[0];
|
||||
child_node->data[0] = curr_node->data[1];
|
||||
curr_node->data[1] = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0)
|
||||
break;
|
||||
size_t tmp = child_node->data[1];
|
||||
child_node->data[1] = curr_node->data[1];
|
||||
curr_node->data[1] = tmp;
|
||||
if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0)
|
||||
{
|
||||
tmp = child_node->data[0];
|
||||
child_node->data[0] = child_node->data[1];
|
||||
child_node->data[1] = tmp;
|
||||
}
|
||||
}
|
||||
index = child;
|
||||
curr_node = child_node;
|
||||
}
|
||||
}
|
||||
static void ih_impl_float_down_min(intervalheap *_heap_)
|
||||
{
|
||||
size_t index = 0;
|
||||
intervalheap_node *curr_node = &(_heap_->buffer[index]);
|
||||
while (1)
|
||||
{
|
||||
if (2 * index + 1 >= _heap_->size)
|
||||
break;
|
||||
size_t child;
|
||||
size_t L_index = index * 2 + 1;
|
||||
size_t R_index = index * 2 + 2;
|
||||
if (R_index < _heap_->size)
|
||||
{
|
||||
intervalheap_node *L = &(_heap_->buffer[L_index]);
|
||||
intervalheap_node *R = &(_heap_->buffer[R_index]);
|
||||
child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index : R_index;
|
||||
}
|
||||
else
|
||||
child = L_index;
|
||||
intervalheap_node *child_node = &(_heap_->buffer[child]);
|
||||
if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0)
|
||||
break;
|
||||
size_t tmp = child_node->data[0];
|
||||
child_node->data[0] = curr_node->data[0];
|
||||
curr_node->data[0] = tmp;
|
||||
if (child != _heap_->size - 1 || ih_count(_heap_) % 2 == 0)
|
||||
{
|
||||
if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0)
|
||||
{
|
||||
tmp = child_node->data[0];
|
||||
child_node->data[0] = child_node->data[1];
|
||||
child_node->data[1] = tmp;
|
||||
}
|
||||
}
|
||||
index = child;
|
||||
curr_node = child_node;
|
||||
}
|
||||
}
|
||||
static intervalheap_iter ih_impl_it_start(intervalheap *_heap_)
|
||||
{
|
||||
intervalheap_iter iter;
|
||||
ih_iter_init(&iter, _heap_);
|
||||
ih_iter_to_start(&iter);
|
||||
return iter;
|
||||
}
|
||||
static intervalheap_iter ih_impl_it_end(intervalheap *_heap_)
|
||||
{
|
||||
intervalheap_iter iter;
|
||||
ih_iter_init(&iter, _heap_);
|
||||
ih_iter_to_end(&iter);
|
||||
return iter;
|
||||
}
|
||||
+245
-153
@@ -1,6 +1,6 @@
|
||||
#include "cmc/linkedlist.h"
|
||||
#include <cmc/linkedlist.h>
|
||||
|
||||
//LINKEDLIST_GENERATE(ll, linkedlist, , size_t)
|
||||
//CMC_GENERATE_LINKEDLIST(ll, linkedlist, size_t)
|
||||
|
||||
typedef struct linkedlist_s
|
||||
{
|
||||
@@ -21,95 +21,97 @@ typedef struct linkedlist_iter_s
|
||||
struct linkedlist_s *target;
|
||||
struct linkedlist_node_s *cursor;
|
||||
size_t index;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} linkedlist_iter, *linkedlist_iter_ptr;
|
||||
linkedlist *ll_new(void);
|
||||
void ll_clear(linkedlist *_list_);
|
||||
void ll_free(linkedlist *_list_);
|
||||
bool ll_push_front(linkedlist *_list_, size_t element);
|
||||
bool ll_push(linkedlist *_list_, size_t element, size_t index);
|
||||
bool ll_push_back(linkedlist *_list_, size_t element);
|
||||
bool ll_pop_front(linkedlist *_list_);
|
||||
bool ll_pop(linkedlist *_list_, size_t index);
|
||||
bool ll_pop_back(linkedlist *_list_);
|
||||
bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition);
|
||||
bool ll_pop_if(linkedlist *_list_, size_t index, bool condition);
|
||||
void ll_clear(linkedlist *_list_, void (*deallocator)(size_t));
|
||||
void ll_free(linkedlist *_list_, void (*deallocator)(size_t));
|
||||
_Bool ll_push_front(linkedlist *_list_, size_t element);
|
||||
_Bool ll_push_at(linkedlist *_list_, size_t element, size_t index);
|
||||
_Bool ll_push_back(linkedlist *_list_, size_t element);
|
||||
_Bool ll_pop_front(linkedlist *_list_);
|
||||
_Bool ll_pop_at(linkedlist *_list_, size_t index);
|
||||
_Bool ll_pop_back(linkedlist *_list_);
|
||||
size_t ll_front(linkedlist *_list_);
|
||||
size_t ll_get(linkedlist *_list_, size_t index);
|
||||
size_t *ll_get_ref(linkedlist *_list_, size_t index);
|
||||
size_t ll_back(linkedlist *_list_);
|
||||
bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t));
|
||||
bool ll_empty(linkedlist *_list_);
|
||||
_Bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t));
|
||||
_Bool ll_empty(linkedlist *_list_);
|
||||
size_t ll_count(linkedlist *_list_);
|
||||
linkedlist *ll_copy_of(linkedlist *_list_, size_t (*copy_func)(size_t));
|
||||
_Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size_t, size_t));
|
||||
cmc_string ll_to_string(linkedlist *_list_);
|
||||
linkedlist_node *ll_new_node(size_t element);
|
||||
void ll_free_node(linkedlist_node *_node_);
|
||||
linkedlist_node *ll_head(linkedlist *_list_);
|
||||
linkedlist_node *ll_get_node(linkedlist *_list_, size_t index);
|
||||
linkedlist_node *ll_tail(linkedlist *_list_);
|
||||
bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
|
||||
bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
|
||||
bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
_Bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
|
||||
_Bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
|
||||
_Bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
_Bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
_Bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_);
|
||||
linkedlist_node *ll_next_node(linkedlist_node *_node_);
|
||||
linkedlist_node *ll_prev_node(linkedlist_node *_node_);
|
||||
linkedlist_iter *ll_iter_new(linkedlist *target);
|
||||
void ll_iter_free(linkedlist_iter *iter);
|
||||
void ll_iter_init(linkedlist_iter *iter, linkedlist *target);
|
||||
bool ll_iter_start(linkedlist_iter *iter);
|
||||
bool ll_iter_end(linkedlist_iter *iter);
|
||||
_Bool ll_iter_start(linkedlist_iter *iter);
|
||||
_Bool ll_iter_end(linkedlist_iter *iter);
|
||||
void ll_iter_to_start(linkedlist_iter *iter);
|
||||
void ll_iter_to_end(linkedlist_iter *iter);
|
||||
bool ll_iter_next(linkedlist_iter *iter);
|
||||
bool ll_iter_prev(linkedlist_iter *iter);
|
||||
_Bool ll_iter_next(linkedlist_iter *iter);
|
||||
_Bool ll_iter_prev(linkedlist_iter *iter);
|
||||
_Bool ll_iter_advance(linkedlist_iter *iter, size_t steps);
|
||||
_Bool ll_iter_rewind(linkedlist_iter *iter, size_t steps);
|
||||
_Bool ll_iter_go_to(linkedlist_iter *iter, size_t index);
|
||||
size_t ll_iter_value(linkedlist_iter *iter);
|
||||
size_t *ll_iter_rvalue(linkedlist_iter *iter);
|
||||
size_t ll_iter_index(linkedlist_iter *iter);
|
||||
linkedlist_node *ll_iter_node(linkedlist_iter *iter);
|
||||
static inline size_t ll_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static linkedlist_iter ll_impl_it_start(linkedlist *_list_);
|
||||
static linkedlist_iter ll_impl_it_end(linkedlist *_list_);
|
||||
linkedlist *ll_new(void)
|
||||
{
|
||||
linkedlist *_list_ = malloc(sizeof(linkedlist));
|
||||
if (!_list_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_list_->count = 0;
|
||||
_list_->head = NULL;
|
||||
_list_->tail = NULL;
|
||||
_list_->head = ((void *)0);
|
||||
_list_->tail = ((void *)0);
|
||||
_list_->it_start = ll_impl_it_start;
|
||||
_list_->it_end = ll_impl_it_end;
|
||||
return _list_;
|
||||
}
|
||||
void ll_clear(linkedlist *_list_)
|
||||
void ll_clear(linkedlist *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
linkedlist_node *scan = _list_->head;
|
||||
while (_list_->head != NULL)
|
||||
while (_list_->head != ((void *)0))
|
||||
{
|
||||
_list_->head = _list_->head->next;
|
||||
if (deallocator)
|
||||
{
|
||||
deallocator(scan->data);
|
||||
}
|
||||
free(scan);
|
||||
scan = _list_->head;
|
||||
}
|
||||
_list_->count = 0;
|
||||
_list_->head = NULL;
|
||||
_list_->tail = NULL;
|
||||
_list_->head = ((void *)0);
|
||||
_list_->tail = ((void *)0);
|
||||
}
|
||||
void ll_free(linkedlist *_list_)
|
||||
void ll_free(linkedlist *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
ll_clear(_list_);
|
||||
ll_clear(_list_, deallocator);
|
||||
free(_list_);
|
||||
}
|
||||
bool ll_push_front(linkedlist *_list_, size_t element)
|
||||
_Bool ll_push_front(linkedlist *_list_, size_t element)
|
||||
{
|
||||
linkedlist_node *_node_ = ll_new_node(element);
|
||||
if (!_node_)
|
||||
return false;
|
||||
return 0;
|
||||
if (ll_empty(_list_))
|
||||
{
|
||||
_list_->head = _node_;
|
||||
@@ -122,12 +124,12 @@ bool ll_push_front(linkedlist *_list_, size_t element)
|
||||
_list_->head = _node_;
|
||||
}
|
||||
_list_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_push(linkedlist *_list_, size_t element, size_t index)
|
||||
_Bool ll_push_at(linkedlist *_list_, size_t element, size_t index)
|
||||
{
|
||||
if (index > _list_->count)
|
||||
return false;
|
||||
return 0;
|
||||
if (index == 0)
|
||||
{
|
||||
return ll_push_front(_list_, element);
|
||||
@@ -138,20 +140,20 @@ bool ll_push(linkedlist *_list_, size_t element, size_t index)
|
||||
}
|
||||
linkedlist_node *_node_ = ll_new_node(element);
|
||||
if (!_node_)
|
||||
return false;
|
||||
return 0;
|
||||
linkedlist_node *scan = ll_get_node(_list_, index - 1);
|
||||
_node_->next = scan->next;
|
||||
_node_->prev = scan;
|
||||
_node_->next->prev = _node_;
|
||||
_node_->prev->next = _node_;
|
||||
_list_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_push_back(linkedlist *_list_, size_t element)
|
||||
_Bool ll_push_back(linkedlist *_list_, size_t element)
|
||||
{
|
||||
linkedlist_node *_node_ = ll_new_node(element);
|
||||
if (!_node_)
|
||||
return false;
|
||||
return 0;
|
||||
if (ll_empty(_list_))
|
||||
{
|
||||
_list_->head = _node_;
|
||||
@@ -164,28 +166,28 @@ bool ll_push_back(linkedlist *_list_, size_t element)
|
||||
_list_->tail = _node_;
|
||||
}
|
||||
_list_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_pop_front(linkedlist *_list_)
|
||||
_Bool ll_pop_front(linkedlist *_list_)
|
||||
{
|
||||
if (ll_empty(_list_))
|
||||
return false;
|
||||
return 0;
|
||||
linkedlist_node *_node_ = _list_->head;
|
||||
_list_->head = _list_->head->next;
|
||||
free(_node_);
|
||||
if (_list_->head == NULL)
|
||||
_list_->tail = NULL;
|
||||
if (_list_->head == ((void *)0))
|
||||
_list_->tail = ((void *)0);
|
||||
else
|
||||
_list_->head->prev = NULL;
|
||||
_list_->head->prev = ((void *)0);
|
||||
_list_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_pop(linkedlist *_list_, size_t index)
|
||||
_Bool ll_pop_at(linkedlist *_list_, size_t index)
|
||||
{
|
||||
if (ll_empty(_list_))
|
||||
return false;
|
||||
return 0;
|
||||
if (index >= _list_->count)
|
||||
return false;
|
||||
return 0;
|
||||
if (index == 0)
|
||||
{
|
||||
return ll_pop_front(_list_);
|
||||
@@ -196,92 +198,132 @@ bool ll_pop(linkedlist *_list_, size_t index)
|
||||
}
|
||||
linkedlist_node *_node_ = ll_get_node(_list_, index);
|
||||
if (!_node_)
|
||||
return false;
|
||||
return 0;
|
||||
_node_->next->prev = _node_->prev;
|
||||
_node_->prev->next = _node_->next;
|
||||
free(_node_);
|
||||
_list_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_pop_back(linkedlist *_list_)
|
||||
_Bool ll_pop_back(linkedlist *_list_)
|
||||
{
|
||||
if (ll_empty(_list_))
|
||||
return false;
|
||||
return 0;
|
||||
linkedlist_node *_node_ = _list_->tail;
|
||||
_list_->tail = _list_->tail->prev;
|
||||
free(_node_);
|
||||
if (_list_->tail == NULL)
|
||||
_list_->head = NULL;
|
||||
if (_list_->tail == ((void *)0))
|
||||
_list_->head = ((void *)0);
|
||||
else
|
||||
_list_->tail->next = NULL;
|
||||
_list_->tail->next = ((void *)0);
|
||||
_list_->count--;
|
||||
return true;
|
||||
}
|
||||
bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ll_push(_list_, element, index);
|
||||
return false;
|
||||
}
|
||||
bool ll_pop_if(linkedlist *_list_, size_t index, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ll_pop(_list_, index);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
size_t ll_front(linkedlist *_list_)
|
||||
{
|
||||
if (ll_empty(_list_))
|
||||
return ll_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _list_->head->data;
|
||||
}
|
||||
size_t ll_get(linkedlist *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count || ll_empty(_list_))
|
||||
return ll_impl_default_value();
|
||||
return (size_t){0};
|
||||
linkedlist_node *scan = ll_get_node(_list_, index);
|
||||
if (scan == NULL)
|
||||
return ll_impl_default_value();
|
||||
if (scan == ((void *)0))
|
||||
return (size_t){0};
|
||||
return scan->data;
|
||||
}
|
||||
size_t *ll_get_ref(linkedlist *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (ll_empty(_list_))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
linkedlist_node *scan = ll_get_node(_list_, index);
|
||||
if (scan == NULL)
|
||||
return NULL;
|
||||
if (scan == ((void *)0))
|
||||
return ((void *)0);
|
||||
return &(scan->data);
|
||||
}
|
||||
size_t ll_back(linkedlist *_list_)
|
||||
{
|
||||
if (ll_empty(_list_))
|
||||
return ll_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _list_->tail->data;
|
||||
}
|
||||
bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t))
|
||||
_Bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
linkedlist_node *scan = _list_->head;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (comparator(scan->data, element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
scan = scan->next;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool ll_empty(linkedlist *_list_) { return _list_->count == 0; }
|
||||
_Bool ll_empty(linkedlist *_list_) { return _list_->count == 0; }
|
||||
size_t ll_count(linkedlist *_list_) { return _list_->count; }
|
||||
linkedlist *ll_copy_of(linkedlist *_list_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
linkedlist *result = ll_new();
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
linkedlist_node *scan = _list_->head;
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
linkedlist_node *new_node;
|
||||
if (copy_func)
|
||||
new_node = ll_new_node(copy_func(scan->data));
|
||||
else
|
||||
new_node = ll_new_node(scan->data);
|
||||
if (!result->head)
|
||||
{
|
||||
result->head = new_node;
|
||||
result->tail = new_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_node->prev = result->tail;
|
||||
result->tail->next = new_node;
|
||||
result->tail = new_node;
|
||||
}
|
||||
scan = scan->next;
|
||||
}
|
||||
result->count = _list_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
if (ll_count(_list1_) != ll_count(_list2_))
|
||||
return 0;
|
||||
linkedlist_node *scan1 = _list1_->head;
|
||||
linkedlist_node *scan2 = _list2_->head;
|
||||
while (scan1 != ((void *)0) && scan2 != ((void *)0))
|
||||
{
|
||||
if (comparator(scan1->data, scan2->data) != 0)
|
||||
return 0;
|
||||
scan1 = scan1->next;
|
||||
scan2 = scan2->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string ll_to_string(linkedlist *_list_)
|
||||
{
|
||||
cmc_string str;
|
||||
linkedlist *l_ = _list_;
|
||||
const char *name = "linkedlist";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, name, l_, l_->count, l_->head, l_->tail);
|
||||
return str;
|
||||
}
|
||||
linkedlist_node *ll_new_node(size_t element)
|
||||
{
|
||||
linkedlist_node *_node_ = malloc(sizeof(linkedlist_node));
|
||||
if (!_node_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_node_->data = element;
|
||||
_node_->next = NULL;
|
||||
_node_->prev = NULL;
|
||||
_node_->next = ((void *)0);
|
||||
_node_->prev = ((void *)0);
|
||||
return _node_;
|
||||
}
|
||||
void ll_free_node(linkedlist_node *_node_) { free(_node_); }
|
||||
@@ -289,10 +331,10 @@ linkedlist_node *ll_head(linkedlist *_list_) { return _list_->head; }
|
||||
linkedlist_node *ll_get_node(linkedlist *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (ll_empty(_list_))
|
||||
return NULL;
|
||||
linkedlist_node *_node_ = NULL;
|
||||
return ((void *)0);
|
||||
linkedlist_node *_node_ = ((void *)0);
|
||||
if (index <= _list_->count / 2)
|
||||
{
|
||||
_node_ = _list_->head;
|
||||
@@ -312,42 +354,42 @@ linkedlist_node *ll_get_node(linkedlist *_list_, size_t index)
|
||||
return _node_;
|
||||
}
|
||||
linkedlist_node *ll_tail(linkedlist *_list_) { return _list_->tail; }
|
||||
bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
|
||||
_Bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
|
||||
{
|
||||
linkedlist_node *new_node = ll_new_node(element);
|
||||
if (!new_node)
|
||||
return false;
|
||||
return 0;
|
||||
new_node->next = _node_->next;
|
||||
if (_node_->next != NULL)
|
||||
if (_node_->next != ((void *)0))
|
||||
_node_->next->prev = new_node;
|
||||
else
|
||||
_owner_->tail = new_node;
|
||||
new_node->prev = _node_;
|
||||
_node_->next = new_node;
|
||||
_owner_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
|
||||
_Bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
|
||||
{
|
||||
linkedlist_node *new_node = ll_new_node(element);
|
||||
if (!new_node)
|
||||
return false;
|
||||
return 0;
|
||||
new_node->prev = _node_->prev;
|
||||
if (_node_->prev != NULL)
|
||||
if (_node_->prev != ((void *)0))
|
||||
_node_->prev->next = new_node;
|
||||
else
|
||||
_owner_->head = new_node;
|
||||
new_node->next = _node_;
|
||||
_node_->prev = new_node;
|
||||
_owner_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
_Bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
{
|
||||
if (_node_->next == NULL)
|
||||
return false;
|
||||
if (_node_->next == ((void *)0))
|
||||
return 0;
|
||||
linkedlist_node *tmp = _node_->next;
|
||||
if (tmp->next != NULL)
|
||||
if (tmp->next != ((void *)0))
|
||||
{
|
||||
_node_->next = _node_->next->next;
|
||||
_node_->next->prev = _node_;
|
||||
@@ -356,28 +398,28 @@ bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
_owner_->tail = _node_;
|
||||
free(tmp);
|
||||
_owner_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
_Bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
{
|
||||
if (_node_->prev != NULL)
|
||||
if (_node_->prev != ((void *)0))
|
||||
_node_->prev->next = _node_->next;
|
||||
else
|
||||
_owner_->head = _node_->next;
|
||||
if (_node_->next != NULL)
|
||||
if (_node_->next != ((void *)0))
|
||||
_node_->next->prev = _node_->prev;
|
||||
else
|
||||
_owner_->tail = _node_->prev;
|
||||
free(_node_);
|
||||
_owner_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
_Bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
{
|
||||
if (_node_->prev == NULL)
|
||||
return false;
|
||||
if (_node_->prev == ((void *)0))
|
||||
return 0;
|
||||
linkedlist_node *tmp = _node_->prev;
|
||||
if (tmp->prev != NULL)
|
||||
if (tmp->prev != ((void *)0))
|
||||
{
|
||||
_node_->prev = _node_->prev->prev;
|
||||
_node_->prev->next = _node_;
|
||||
@@ -386,7 +428,7 @@ bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_)
|
||||
_owner_->head = _node_;
|
||||
free(tmp);
|
||||
_owner_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
linkedlist_node *ll_next_node(linkedlist_node *_node_) { return _node_->next; }
|
||||
linkedlist_node *ll_prev_node(linkedlist_node *_node_) { return _node_->prev; }
|
||||
@@ -394,7 +436,7 @@ linkedlist_iter *ll_iter_new(linkedlist *target)
|
||||
{
|
||||
linkedlist_iter *iter = malloc(sizeof(linkedlist_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
ll_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -404,63 +446,113 @@ void ll_iter_init(linkedlist_iter *iter, linkedlist *target)
|
||||
iter->target = target;
|
||||
iter->cursor = target->head;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = ll_empty(target);
|
||||
}
|
||||
bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; }
|
||||
bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; }
|
||||
_Bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; }
|
||||
_Bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; }
|
||||
void ll_iter_to_start(linkedlist_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->head;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = ll_empty(iter->target);
|
||||
if (!ll_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->head;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = ll_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void ll_iter_to_end(linkedlist_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->tail;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ll_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!ll_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->tail;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ll_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool ll_iter_next(linkedlist_iter *iter)
|
||||
_Bool ll_iter_next(linkedlist_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = ll_empty(iter->target);
|
||||
if (iter->cursor->next == NULL)
|
||||
iter->end = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->cursor->next == ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->next;
|
||||
iter->index++;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->start = ll_empty(iter->target);
|
||||
iter->cursor = iter->cursor->next;
|
||||
iter->index++;
|
||||
return 1;
|
||||
}
|
||||
bool ll_iter_prev(linkedlist_iter *iter)
|
||||
_Bool ll_iter_prev(linkedlist_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = ll_empty(iter->target);
|
||||
if (iter->cursor->prev == NULL)
|
||||
iter->start = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->cursor->prev == ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->prev;
|
||||
iter->index--;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->end = ll_empty(iter->target);
|
||||
iter->cursor = iter->cursor->prev;
|
||||
iter->index--;
|
||||
return 1;
|
||||
}
|
||||
_Bool ll_iter_advance(linkedlist_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor->next == ((void *)0))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= ll_count(iter->target))
|
||||
return 0;
|
||||
iter->start = ll_empty(iter->target);
|
||||
iter->index += steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
iter->cursor = iter->cursor->next;
|
||||
return 1;
|
||||
}
|
||||
_Bool ll_iter_rewind(linkedlist_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor->prev == ((void *)0))
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
iter->end = ll_empty(iter->target);
|
||||
iter->index -= steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
iter->cursor = iter->cursor->prev;
|
||||
return 1;
|
||||
}
|
||||
_Bool ll_iter_go_to(linkedlist_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= ll_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return ll_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return ll_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t ll_iter_value(linkedlist_iter *iter)
|
||||
{
|
||||
if (ll_empty(iter->target))
|
||||
return ll_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->cursor->data;
|
||||
}
|
||||
size_t *ll_iter_rvalue(linkedlist_iter *iter)
|
||||
{
|
||||
if (ll_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->cursor->data);
|
||||
}
|
||||
size_t ll_iter_index(linkedlist_iter *iter) { return iter->index; }
|
||||
|
||||
+236
-172
@@ -1,6 +1,6 @@
|
||||
#include "cmc/list.h"
|
||||
#include <cmc/list.h>
|
||||
|
||||
//LIST_GENERATE(l, list, , size_t)
|
||||
//CMC_GENERATE_LIST(l, list, size_t)
|
||||
|
||||
typedef struct list_s
|
||||
{
|
||||
@@ -14,71 +14,68 @@ typedef struct list_iter_s
|
||||
{
|
||||
struct list_s *target;
|
||||
size_t cursor;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} list_iter, *list_iter_ptr;
|
||||
list *l_new(size_t capacity);
|
||||
list *l_new_from(size_t *elements, size_t size);
|
||||
void l_clear(list *_list_);
|
||||
void l_free(list *_list_);
|
||||
bool l_push_front(list *_list_, size_t element);
|
||||
bool l_push(list *_list_, size_t element, size_t index);
|
||||
bool l_push_back(list *_list_, size_t element);
|
||||
bool l_pop_front(list *_list_);
|
||||
bool l_pop(list *_list_, size_t index);
|
||||
bool l_pop_back(list *_list_);
|
||||
bool l_push_if(list *_list_, size_t element, size_t index, bool condition);
|
||||
bool l_pop_if(list *_list_, size_t index, bool condition);
|
||||
bool l_prepend(list *_list_, size_t *elements, size_t size);
|
||||
bool l_insert(list *_list_, size_t *elements, size_t size, size_t index);
|
||||
bool l_append(list *_list_, size_t *elements, size_t size);
|
||||
bool l_remove(list *_list_, size_t from, size_t to);
|
||||
list *l_extract(list *_list_, size_t from, size_t to);
|
||||
void l_clear(list *_list_, void (*deallocator)(size_t));
|
||||
void l_free(list *_list_, void (*deallocator)(size_t));
|
||||
_Bool l_push_front(list *_list_, size_t element);
|
||||
_Bool l_push_at(list *_list_, size_t element, size_t index);
|
||||
_Bool l_push_back(list *_list_, size_t element);
|
||||
_Bool l_pop_front(list *_list_);
|
||||
_Bool l_pop_at(list *_list_, size_t index);
|
||||
_Bool l_pop_back(list *_list_);
|
||||
_Bool l_seq_push_front(list *_list_, size_t *elements, size_t size);
|
||||
_Bool l_seq_push_at(list *_list_, size_t *elements, size_t size, size_t index);
|
||||
_Bool l_seq_push_back(list *_list_, size_t *elements, size_t size);
|
||||
_Bool l_seq_pop_at(list *_list_, size_t from, size_t to);
|
||||
list *l_seq_sublist(list *_list_, size_t from, size_t to);
|
||||
size_t l_front(list *_list_);
|
||||
size_t l_get(list *_list_, size_t index);
|
||||
size_t *l_get_ref(list *_list_, size_t index);
|
||||
size_t l_back(list *_list_);
|
||||
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start);
|
||||
bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t));
|
||||
bool l_empty(list *_list_);
|
||||
bool l_full(list *_list_);
|
||||
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), _Bool from_start);
|
||||
_Bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t));
|
||||
_Bool l_empty(list *_list_);
|
||||
_Bool l_full(list *_list_);
|
||||
size_t l_count(list *_list_);
|
||||
bool l_fits(list *_list_, size_t size);
|
||||
_Bool l_fits(list *_list_, size_t size);
|
||||
size_t l_capacity(list *_list_);
|
||||
_Bool l_resize(list *_list_, size_t capacity);
|
||||
list *l_copy_of(list *_list_, size_t (*copy_func)(size_t));
|
||||
_Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t));
|
||||
cmc_string l_to_string(list *_list_);
|
||||
list_iter *l_iter_new(list *target);
|
||||
void l_iter_free(list_iter *iter);
|
||||
void l_iter_init(list_iter *iter, list *target);
|
||||
bool l_iter_start(list_iter *iter);
|
||||
bool l_iter_end(list_iter *iter);
|
||||
_Bool l_iter_start(list_iter *iter);
|
||||
_Bool l_iter_end(list_iter *iter);
|
||||
void l_iter_to_start(list_iter *iter);
|
||||
void l_iter_to_end(list_iter *iter);
|
||||
bool l_iter_next(list_iter *iter);
|
||||
bool l_iter_prev(list_iter *iter);
|
||||
_Bool l_iter_next(list_iter *iter);
|
||||
_Bool l_iter_prev(list_iter *iter);
|
||||
_Bool l_iter_advance(list_iter *iter, size_t steps);
|
||||
_Bool l_iter_rewind(list_iter *iter, size_t steps);
|
||||
_Bool l_iter_go_to(list_iter *iter, size_t index);
|
||||
size_t l_iter_value(list_iter *iter);
|
||||
size_t *l_iter_rvalue(list_iter *iter);
|
||||
size_t l_iter_index(list_iter *iter);
|
||||
static inline size_t l_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
|
||||
static bool l_impl_grow(list *_list_, size_t required);
|
||||
static list_iter l_impl_it_start(list *_list_);
|
||||
static list_iter l_impl_it_end(list *_list_);
|
||||
list *l_new(size_t capacity)
|
||||
{
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
list *_list_ = malloc(sizeof(list));
|
||||
if (!_list_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_list_->buffer = malloc(capacity * sizeof(size_t));
|
||||
if (!_list_->buffer)
|
||||
{
|
||||
free(_list_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_list_->buffer, 0, capacity * sizeof(size_t));
|
||||
_list_->capacity = capacity;
|
||||
@@ -90,30 +87,40 @@ list *l_new(size_t capacity)
|
||||
list *l_new_from(size_t *elements, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
list *_list_ = l_new(size + size / 2);
|
||||
if (!_list_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
memcpy(_list_->buffer, elements, size * sizeof(size_t));
|
||||
_list_->count = size;
|
||||
return _list_;
|
||||
}
|
||||
void l_clear(list *_list_)
|
||||
void l_clear(list *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
deallocator(_list_->buffer[i]);
|
||||
}
|
||||
memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity);
|
||||
_list_->count = 0;
|
||||
}
|
||||
void l_free(list *_list_)
|
||||
void l_free(list *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
deallocator(_list_->buffer[i]);
|
||||
}
|
||||
free(_list_->buffer);
|
||||
free(_list_);
|
||||
}
|
||||
bool l_push_front(list *_list_, size_t element)
|
||||
_Bool l_push_front(list *_list_, size_t element)
|
||||
{
|
||||
if (l_full(_list_))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + 1))
|
||||
return false;
|
||||
if (!l_resize(_list_, l_count(_list_) * 2))
|
||||
return 0;
|
||||
}
|
||||
if (!l_empty(_list_))
|
||||
{
|
||||
@@ -121,183 +128,155 @@ bool l_push_front(list *_list_, size_t element)
|
||||
}
|
||||
_list_->buffer[0] = element;
|
||||
_list_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_push(list *_list_, size_t element, size_t index)
|
||||
_Bool l_push_at(list *_list_, size_t element, size_t index)
|
||||
{
|
||||
if (index > _list_->count)
|
||||
return false;
|
||||
if (index == 0)
|
||||
{
|
||||
return l_push_front(_list_, element);
|
||||
}
|
||||
else if (index == _list_->count)
|
||||
{
|
||||
return l_push_back(_list_, element);
|
||||
}
|
||||
return 0;
|
||||
if (l_full(_list_))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + 1))
|
||||
return false;
|
||||
if (!l_resize(_list_, l_count(_list_) * 2))
|
||||
return 0;
|
||||
}
|
||||
memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t));
|
||||
_list_->buffer[index] = element;
|
||||
_list_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_push_back(list *_list_, size_t element)
|
||||
_Bool l_push_back(list *_list_, size_t element)
|
||||
{
|
||||
if (l_full(_list_))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + 1))
|
||||
return false;
|
||||
if (!l_resize(_list_, l_count(_list_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_list_->buffer[_list_->count++] = element;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_pop_front(list *_list_)
|
||||
_Bool l_pop_front(list *_list_)
|
||||
{
|
||||
if (l_empty(_list_))
|
||||
return false;
|
||||
return 0;
|
||||
memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(size_t));
|
||||
_list_->buffer[--_list_->count] = l_impl_default_value();
|
||||
return true;
|
||||
_list_->buffer[--_list_->count] = (size_t){0};
|
||||
return 1;
|
||||
}
|
||||
bool l_pop(list *_list_, size_t index)
|
||||
_Bool l_pop_at(list *_list_, size_t index)
|
||||
{
|
||||
if (l_empty(_list_))
|
||||
return false;
|
||||
if (index >= _list_->count)
|
||||
return false;
|
||||
if (index == 0)
|
||||
{
|
||||
return l_pop_front(_list_);
|
||||
}
|
||||
else if (index == _list_->count - 1)
|
||||
{
|
||||
return l_pop_back(_list_);
|
||||
}
|
||||
return 0;
|
||||
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t));
|
||||
_list_->buffer[--_list_->count] = l_impl_default_value();
|
||||
return true;
|
||||
_list_->buffer[--_list_->count] = (size_t){0};
|
||||
return 1;
|
||||
}
|
||||
bool l_pop_back(list *_list_)
|
||||
_Bool l_pop_back(list *_list_)
|
||||
{
|
||||
if (l_empty(_list_))
|
||||
return false;
|
||||
_list_->buffer[--_list_->count] = l_impl_default_value();
|
||||
return true;
|
||||
return 0;
|
||||
_list_->buffer[--_list_->count] = (size_t){0};
|
||||
return 1;
|
||||
}
|
||||
bool l_push_if(list *_list_, size_t element, size_t index, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return l_push(_list_, element, index);
|
||||
return false;
|
||||
}
|
||||
bool l_pop_if(list *_list_, size_t index, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return l_pop(_list_, index);
|
||||
return false;
|
||||
}
|
||||
bool l_prepend(list *_list_, size_t *elements, size_t size)
|
||||
_Bool l_seq_push_front(list *_list_, size_t *elements, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return false;
|
||||
return 0;
|
||||
if (!l_fits(_list_, size))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + size))
|
||||
return false;
|
||||
if (!l_resize(_list_, l_count(_list_) + size))
|
||||
return 0;
|
||||
}
|
||||
memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t));
|
||||
memcpy(_list_->buffer, elements, size * sizeof(size_t));
|
||||
_list_->count += size;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_insert(list *_list_, size_t *elements, size_t size, size_t index)
|
||||
_Bool l_seq_push_at(list *_list_, size_t *elements, size_t size, size_t index)
|
||||
{
|
||||
if (size == 0 || index > _list_->count)
|
||||
return false;
|
||||
return 0;
|
||||
if (index == 0)
|
||||
return l_prepend(_list_, elements, size);
|
||||
return l_seq_push_front(_list_, elements, size);
|
||||
else if (index == _list_->count)
|
||||
return l_append(_list_, elements, size);
|
||||
return l_seq_push_back(_list_, elements, size);
|
||||
else
|
||||
{
|
||||
if (!l_fits(_list_, size))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + size))
|
||||
return false;
|
||||
if (!l_resize(_list_, l_count(_list_) + size))
|
||||
return 0;
|
||||
}
|
||||
memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t));
|
||||
memcpy(_list_->buffer + index, elements, size * sizeof(size_t));
|
||||
_list_->count += size;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_append(list *_list_, size_t *elements, size_t size)
|
||||
_Bool l_seq_push_back(list *_list_, size_t *elements, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return false;
|
||||
return 0;
|
||||
if (!l_fits(_list_, size))
|
||||
{
|
||||
if (!l_impl_grow(_list_, _list_->count + size))
|
||||
return false;
|
||||
if (!l_resize(_list_, _list_->count + size))
|
||||
return 0;
|
||||
}
|
||||
memcpy(_list_->buffer + _list_->count, elements, size * sizeof(size_t));
|
||||
_list_->count += size;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool l_remove(list *_list_, size_t from, size_t to)
|
||||
_Bool l_seq_pop_at(list *_list_, size_t from, size_t to)
|
||||
{
|
||||
if (from > to || to >= _list_->count)
|
||||
return false;
|
||||
return 0;
|
||||
size_t length = (to - from + 1);
|
||||
memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t));
|
||||
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t));
|
||||
_list_->count -= to - from + 1;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
list *l_extract(list *_list_, size_t from, size_t to)
|
||||
list *l_seq_sublist(list *_list_, size_t from, size_t to)
|
||||
{
|
||||
if (from > to || to >= _list_->count)
|
||||
return false;
|
||||
return 0;
|
||||
size_t length = to - from + 1;
|
||||
list *result = l_new_from(_list_->buffer + from, length);
|
||||
list *result = l_new(length);
|
||||
if (!result)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
memcpy(result->buffer, _list_->buffer, _list_->count * sizeof(size_t));
|
||||
memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t));
|
||||
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t));
|
||||
_list_->count -= length;
|
||||
result->count = length;
|
||||
return result;
|
||||
}
|
||||
size_t l_front(list *_list_)
|
||||
{
|
||||
if (l_empty(_list_))
|
||||
return l_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _list_->buffer[0];
|
||||
}
|
||||
size_t l_get(list *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count || l_empty(_list_))
|
||||
return l_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _list_->buffer[index];
|
||||
}
|
||||
size_t *l_get_ref(list *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (l_empty(_list_))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(_list_->buffer[index]);
|
||||
}
|
||||
size_t l_back(list *_list_)
|
||||
{
|
||||
if (l_empty(_list_))
|
||||
return l_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _list_->buffer[_list_->count - 1];
|
||||
}
|
||||
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start)
|
||||
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), _Bool from_start)
|
||||
{
|
||||
if (from_start)
|
||||
{
|
||||
@@ -317,25 +296,72 @@ size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t)
|
||||
}
|
||||
return _list_->count;
|
||||
}
|
||||
bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t))
|
||||
_Bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
{
|
||||
if (comparator(_list_->buffer[i], element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool l_empty(list *_list_) { return _list_->count == 0; }
|
||||
bool l_full(list *_list_) { return _list_->count >= _list_->capacity; }
|
||||
_Bool l_empty(list *_list_) { return _list_->count == 0; }
|
||||
_Bool l_full(list *_list_) { return _list_->count >= _list_->capacity; }
|
||||
size_t l_count(list *_list_) { return _list_->count; }
|
||||
bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; }
|
||||
_Bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; }
|
||||
size_t l_capacity(list *_list_) { return _list_->capacity; }
|
||||
_Bool l_resize(list *_list_, size_t capacity)
|
||||
{
|
||||
if (l_capacity(_list_) == capacity)
|
||||
return 1;
|
||||
if (capacity < l_count(_list_))
|
||||
return 0;
|
||||
size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
_list_->buffer = new_buffer;
|
||||
_list_->capacity = capacity;
|
||||
return 1;
|
||||
}
|
||||
list *l_copy_of(list *_list_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
list *result = l_new(_list_->capacity);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
result->buffer[i] = copy_func(_list_->buffer[i]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count);
|
||||
result->count = _list_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
if (l_count(_list1_) != l_count(_list2_))
|
||||
return 0;
|
||||
for (size_t i = 0; i < l_count(_list1_); i++)
|
||||
{
|
||||
if (comparator(_list1_->buffer[i], _list2_->buffer[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cmc_string l_to_string(list *_list_)
|
||||
{
|
||||
cmc_string str;
|
||||
list *l_ = _list_;
|
||||
const char *name = "list";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_list, name, l_, l_->buffer, l_->capacity, l_->count);
|
||||
return str;
|
||||
}
|
||||
list_iter *l_iter_new(list *target)
|
||||
{
|
||||
list_iter *iter = malloc(sizeof(list_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
l_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -344,70 +370,108 @@ void l_iter_init(list_iter *iter, list *target)
|
||||
{
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = l_empty(target);
|
||||
}
|
||||
bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; }
|
||||
bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; }
|
||||
_Bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; }
|
||||
_Bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; }
|
||||
void l_iter_to_start(list_iter *iter)
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = true;
|
||||
iter->end = l_empty(iter->target);
|
||||
if (!l_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = l_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void l_iter_to_end(list_iter *iter)
|
||||
{
|
||||
iter->start = l_empty(iter->target);
|
||||
iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1;
|
||||
iter->end = true;
|
||||
if (!l_empty(iter->target))
|
||||
{
|
||||
iter->start = l_empty(iter->target);
|
||||
iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1;
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool l_iter_next(list_iter *iter)
|
||||
_Bool l_iter_next(list_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
return 0;
|
||||
if (iter->cursor + 1 == l_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = l_empty(iter->target);
|
||||
if (iter->cursor == iter->target->count - 1)
|
||||
iter->end = true;
|
||||
else
|
||||
iter->cursor++;
|
||||
return true;
|
||||
iter->cursor++;
|
||||
return 1;
|
||||
}
|
||||
bool l_iter_prev(list_iter *iter)
|
||||
_Bool l_iter_prev(list_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = l_empty(iter->target);
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
iter->start = true;
|
||||
else
|
||||
iter->cursor--;
|
||||
return true;
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = l_empty(iter->target);
|
||||
iter->cursor--;
|
||||
return 1;
|
||||
}
|
||||
_Bool l_iter_advance(list_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor + steps >= l_count(iter->target))
|
||||
return 0;
|
||||
iter->start = l_empty(iter->target);
|
||||
iter->cursor += steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool l_iter_rewind(list_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return 0;
|
||||
iter->end = l_empty(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool l_iter_go_to(list_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= l_count(iter->target))
|
||||
return 0;
|
||||
if (iter->cursor > index)
|
||||
return l_iter_rewind(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return l_iter_advance(iter, index - iter->cursor);
|
||||
return 1;
|
||||
}
|
||||
size_t l_iter_value(list_iter *iter)
|
||||
{
|
||||
if (l_empty(iter->target))
|
||||
return l_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t *l_iter_rvalue(list_iter *iter)
|
||||
{
|
||||
if (l_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->target->buffer[iter->cursor]);
|
||||
}
|
||||
size_t l_iter_index(list_iter *iter) { return iter->cursor; }
|
||||
static bool l_impl_grow(list *_list_, size_t required)
|
||||
{
|
||||
size_t new_capacity = _list_->capacity * 2;
|
||||
if (new_capacity < required)
|
||||
new_capacity = required;
|
||||
size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
_list_->buffer = new_buffer;
|
||||
_list_->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
static list_iter l_impl_it_start(list *_list_)
|
||||
{
|
||||
list_iter iter;
|
||||
|
||||
+359
-189
@@ -1,6 +1,6 @@
|
||||
#include "ext/multimap.h"
|
||||
#include <cmc/multimap.h>
|
||||
|
||||
//MULTIMAP_GENERATE(mm, multimap, , size_t, size_t)
|
||||
//CMC_GENERATE_MULTIMAP(mm, multimap, size_t, size_t)
|
||||
|
||||
typedef struct multimap_s
|
||||
{
|
||||
@@ -28,51 +28,48 @@ typedef struct multimap_iter_s
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} multimap_iter, *multimap_iter_ptr;
|
||||
multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
|
||||
void mm_clear(multimap *_map_);
|
||||
void mm_free(multimap *_map_);
|
||||
bool mm_insert(multimap *_map_, size_t key, size_t value);
|
||||
bool mm_remove(multimap *_map_, size_t key, size_t *value);
|
||||
size_t mm_remove_all(multimap *_map_, size_t key);
|
||||
bool mm_insert_if(multimap *_map_, size_t key, size_t value, bool condition);
|
||||
bool mm_remove_if(multimap *_map_, size_t key, size_t *value, bool condition);
|
||||
bool mm_max(multimap *_map_, size_t *key, size_t *value);
|
||||
bool mm_min(multimap *_map_, size_t *key, size_t *value);
|
||||
void mm_clear(multimap *_map_, void (*deallocator)(size_t, size_t));
|
||||
void mm_free(multimap *_map_, void (*deallocator)(size_t, size_t));
|
||||
_Bool mm_insert(multimap *_map_, size_t key, size_t value);
|
||||
_Bool mm_update(multimap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
size_t mm_update_all(multimap *_map_, size_t key, size_t new_value, size_t **old_values);
|
||||
_Bool mm_remove(multimap *_map_, size_t key, size_t *out_value);
|
||||
size_t mm_remove_all(multimap *_map_, size_t key, size_t **out_values);
|
||||
_Bool mm_max(multimap *_map_, size_t *key, size_t *value);
|
||||
_Bool mm_min(multimap *_map_, size_t *key, size_t *value);
|
||||
size_t mm_get(multimap *_map_, size_t key);
|
||||
size_t *mm_get_ref(multimap *_map_, size_t key);
|
||||
bool mm_contains(multimap *_map_, size_t key);
|
||||
bool mm_empty(multimap *_map_);
|
||||
_Bool mm_contains(multimap *_map_, size_t key);
|
||||
_Bool mm_empty(multimap *_map_);
|
||||
_Bool mm_full(multimap *_map_);
|
||||
size_t mm_count(multimap *_map_);
|
||||
size_t mm_key_count(multimap *_map_, size_t key);
|
||||
size_t mm_capacity(multimap *_map_);
|
||||
double mm_load(multimap *_map_);
|
||||
_Bool mm_resize(multimap *_map_, size_t capacity);
|
||||
multimap *mm_copy_of(multimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t));
|
||||
_Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count);
|
||||
cmc_string mm_to_string(multimap *_map_);
|
||||
multimap_iter *mm_iter_new(multimap *target);
|
||||
void mm_iter_free(multimap_iter *iter);
|
||||
void mm_iter_init(multimap_iter *iter, multimap *target);
|
||||
bool mm_iter_start(multimap_iter *iter);
|
||||
bool mm_iter_end(multimap_iter *iter);
|
||||
_Bool mm_iter_start(multimap_iter *iter);
|
||||
_Bool mm_iter_end(multimap_iter *iter);
|
||||
void mm_iter_to_start(multimap_iter *iter);
|
||||
void mm_iter_to_end(multimap_iter *iter);
|
||||
bool mm_iter_next(multimap_iter *iter);
|
||||
bool mm_iter_prev(multimap_iter *iter);
|
||||
_Bool mm_iter_next(multimap_iter *iter);
|
||||
_Bool mm_iter_prev(multimap_iter *iter);
|
||||
_Bool mm_iter_advance(multimap_iter *iter, size_t steps);
|
||||
_Bool mm_iter_rewind(multimap_iter *iter, size_t steps);
|
||||
_Bool mm_iter_go_to(multimap_iter *iter, size_t index);
|
||||
size_t mm_iter_key(multimap_iter *iter);
|
||||
size_t mm_iter_value(multimap_iter *iter);
|
||||
size_t *mm_iter_rvalue(multimap_iter *iter);
|
||||
size_t mm_iter_index(multimap_iter *iter);
|
||||
static inline size_t mm_impl_default_key(void)
|
||||
{
|
||||
size_t _empty_key_;
|
||||
memset(&_empty_key_, 0, sizeof(size_t));
|
||||
return _empty_key_;
|
||||
}
|
||||
static inline size_t mm_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
bool mm_impl_grow(multimap *_map_);
|
||||
multimap_entry *mm_impl_new_entry(size_t key, size_t value);
|
||||
multimap_entry *mm_impl_get_entry(multimap *_map_, size_t key);
|
||||
size_t mm_impl_calculate_size(size_t required);
|
||||
@@ -81,18 +78,18 @@ static multimap_iter mm_impl_it_end(multimap *_map_);
|
||||
multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
|
||||
{
|
||||
if (capacity == 0 || load <= 0)
|
||||
return NULL;
|
||||
if (capacity >= UINTMAX_MAX * load)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
return ((void *)0);
|
||||
size_t real_capacity = mm_impl_calculate_size(capacity / load);
|
||||
multimap *_map_ = malloc(sizeof(multimap));
|
||||
if (!_map_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_map_->buffer = malloc(sizeof(multimap_entry_ptr[2]) * real_capacity);
|
||||
if (!_map_->buffer)
|
||||
{
|
||||
free(_map_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * real_capacity);
|
||||
_map_->count = 0;
|
||||
@@ -100,25 +97,33 @@ multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), s
|
||||
_map_->load = load;
|
||||
_map_->cmp = compare;
|
||||
_map_->hash = hash;
|
||||
_map_->it_start = mm_impl_it_start;
|
||||
_map_->it_end = mm_impl_it_end;
|
||||
return _map_;
|
||||
}
|
||||
void mm_clear(multimap *_map_)
|
||||
void mm_clear(multimap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
size_t index = 0;
|
||||
multimap_entry *scan;
|
||||
while (index < _map_->capacity)
|
||||
{
|
||||
scan = _map_->buffer[index][0];
|
||||
if (scan != NULL)
|
||||
if (scan != ((void *)0))
|
||||
{
|
||||
if (scan->next == NULL && scan->prev == NULL)
|
||||
if (scan->next == ((void *)0) && scan->prev == ((void *)0))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(scan->key, scan->value);
|
||||
free(scan);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
multimap_entry *tmp = scan;
|
||||
scan = scan->next;
|
||||
if (deallocator)
|
||||
deallocator(tmp->key, tmp->value);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
@@ -128,23 +133,45 @@ void mm_clear(multimap *_map_)
|
||||
memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * _map_->capacity);
|
||||
_map_->count = 0;
|
||||
}
|
||||
void mm_free(multimap *_map_)
|
||||
void mm_free(multimap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
mm_clear(_map_);
|
||||
size_t index = 0;
|
||||
multimap_entry *scan;
|
||||
while (index < _map_->capacity)
|
||||
{
|
||||
scan = _map_->buffer[index][0];
|
||||
if (scan != ((void *)0))
|
||||
{
|
||||
if (scan->next == ((void *)0) && scan->prev == ((void *)0))
|
||||
free(scan);
|
||||
else
|
||||
{
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
multimap_entry *tmp = scan;
|
||||
scan = scan->next;
|
||||
if (deallocator)
|
||||
deallocator(tmp->key, tmp->value);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
free(_map_->buffer);
|
||||
free(_map_);
|
||||
}
|
||||
bool mm_insert(multimap *_map_, size_t key, size_t value)
|
||||
_Bool mm_insert(multimap *_map_, size_t key, size_t value)
|
||||
{
|
||||
if ((double)_map_->capacity * _map_->load <= (double)_map_->count)
|
||||
if (mm_full(_map_))
|
||||
{
|
||||
if (!mm_impl_grow(_map_))
|
||||
return false;
|
||||
if (!mm_resize(_map_, mm_capacity(_map_) + 1))
|
||||
return 0;
|
||||
}
|
||||
size_t hash = _map_->hash(key);
|
||||
size_t pos = hash % _map_->capacity;
|
||||
multimap_entry *entry = mm_impl_new_entry(key, value);
|
||||
if (_map_->buffer[pos][0] == NULL)
|
||||
if (_map_->buffer[pos][0] == ((void *)0))
|
||||
{
|
||||
_map_->buffer[pos][0] = entry;
|
||||
_map_->buffer[pos][1] = entry;
|
||||
@@ -156,31 +183,68 @@ bool mm_insert(multimap *_map_, size_t key, size_t value)
|
||||
_map_->buffer[pos][1] = entry;
|
||||
}
|
||||
_map_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool mm_remove(multimap *_map_, size_t key, size_t *value)
|
||||
_Bool mm_update(multimap *_map_, size_t key, size_t new_value, size_t *old_value)
|
||||
{
|
||||
multimap_entry *entry = mm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return 0;
|
||||
if (old_value)
|
||||
*old_value = entry->value;
|
||||
entry->value = new_value;
|
||||
return 0;
|
||||
}
|
||||
size_t mm_update_all(multimap *_map_, size_t key, size_t new_value, size_t **old_values)
|
||||
{
|
||||
size_t total = mm_key_count(_map_, key);
|
||||
size_t index = 0;
|
||||
if (total == 0)
|
||||
return total;
|
||||
if (old_values)
|
||||
{
|
||||
*old_values = malloc(sizeof(size_t) * total);
|
||||
if (!(*old_values))
|
||||
return 0;
|
||||
}
|
||||
size_t hash = _map_->hash(key);
|
||||
multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0];
|
||||
while (entry != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
{
|
||||
if (old_values)
|
||||
(*old_values)[index++] = entry->value;
|
||||
entry->value = new_value;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
_Bool mm_remove(multimap *_map_, size_t key, size_t *out_value)
|
||||
{
|
||||
size_t hash = _map_->hash(key);
|
||||
multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]);
|
||||
multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]);
|
||||
if (*head == NULL)
|
||||
return false;
|
||||
if (*head == ((void *)0))
|
||||
return 0;
|
||||
multimap_entry *entry = *head;
|
||||
if (entry->next == NULL && entry->prev == NULL)
|
||||
if (entry->next == ((void *)0) && entry->prev == ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
{
|
||||
*head = NULL;
|
||||
*tail = NULL;
|
||||
*value = entry->value;
|
||||
*head = ((void *)0);
|
||||
*tail = ((void *)0);
|
||||
if (out_value)
|
||||
*out_value = entry->value;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool found = false;
|
||||
while (entry != NULL)
|
||||
_Bool found = 0;
|
||||
while (entry != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
{
|
||||
@@ -188,43 +252,48 @@ bool mm_remove(multimap *_map_, size_t key, size_t *value)
|
||||
*head = entry->next;
|
||||
if (*tail == entry)
|
||||
*tail = entry->prev;
|
||||
if (entry->prev != NULL)
|
||||
if (entry->prev != ((void *)0))
|
||||
entry->prev->next = entry->next;
|
||||
if (entry->next != NULL)
|
||||
if (entry->next != ((void *)0))
|
||||
entry->next->prev = entry->prev;
|
||||
*value = entry->value;
|
||||
found = true;
|
||||
if (out_value)
|
||||
*out_value = entry->value;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
entry = entry->next;
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
free(entry);
|
||||
_map_->count--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
size_t mm_remove_all(multimap *_map_, size_t key)
|
||||
size_t mm_remove_all(multimap *_map_, size_t key, size_t **out_values)
|
||||
{
|
||||
size_t total = 0;
|
||||
size_t hash = _map_->hash(key);
|
||||
multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]);
|
||||
multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]);
|
||||
if (*head == NULL)
|
||||
return total;
|
||||
if (*head == ((void *)0))
|
||||
return 0;
|
||||
size_t total = mm_key_count(_map_, key);
|
||||
size_t index = 0;
|
||||
if (out_values)
|
||||
*out_values = malloc(sizeof(multimap_entry) * total);
|
||||
multimap_entry *entry = *head;
|
||||
if (entry->next == NULL)
|
||||
if (entry->next == ((void *)0))
|
||||
{
|
||||
*head = NULL;
|
||||
*tail = NULL;
|
||||
*head = ((void *)0);
|
||||
*tail = ((void *)0);
|
||||
if (out_values)
|
||||
(*out_values)[index++] = entry->value;
|
||||
free(entry);
|
||||
total++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (entry != NULL)
|
||||
while (entry != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
{
|
||||
@@ -233,37 +302,26 @@ size_t mm_remove_all(multimap *_map_, size_t key)
|
||||
if (*tail == entry)
|
||||
*tail = entry->prev;
|
||||
multimap_entry *temp = entry->next;
|
||||
if (entry->prev != NULL)
|
||||
if (entry->prev != ((void *)0))
|
||||
entry->prev->next = entry->next;
|
||||
if (entry->next != NULL)
|
||||
if (entry->next != ((void *)0))
|
||||
entry->next->prev = entry->prev;
|
||||
if (out_values)
|
||||
(*out_values)[index++] = entry->value;
|
||||
free(entry);
|
||||
entry = temp;
|
||||
total++;
|
||||
}
|
||||
else
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
_map_->count -= total;
|
||||
return total;
|
||||
_map_->count -= index;
|
||||
return index;
|
||||
}
|
||||
bool mm_insert_if(multimap *_map_, size_t key, size_t value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return mm_insert(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool mm_remove_if(multimap *_map_, size_t key, size_t *value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return mm_remove(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool mm_max(multimap *_map_, size_t *key, size_t *value)
|
||||
_Bool mm_max(multimap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (mm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
multimap_iter iter;
|
||||
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
@@ -281,12 +339,12 @@ bool mm_max(multimap *_map_, size_t *key, size_t *value)
|
||||
*value = result_value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool mm_min(multimap *_map_, size_t *key, size_t *value)
|
||||
_Bool mm_min(multimap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (mm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
multimap_iter iter;
|
||||
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
@@ -304,47 +362,155 @@ bool mm_min(multimap *_map_, size_t *key, size_t *value)
|
||||
*value = result_value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
size_t mm_get(multimap *_map_, size_t key)
|
||||
{
|
||||
multimap_entry *entry = mm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return mm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return entry->value;
|
||||
}
|
||||
size_t *mm_get_ref(multimap *_map_, size_t key)
|
||||
{
|
||||
multimap_entry *entry = mm_impl_get_entry(_map_, key);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(entry->value);
|
||||
}
|
||||
bool mm_contains(multimap *_map_, size_t key) { return mm_impl_get_entry(_map_, key) != NULL; }
|
||||
bool mm_empty(multimap *_map_) { return _map_->count == 0; }
|
||||
_Bool mm_contains(multimap *_map_, size_t key) { return mm_impl_get_entry(_map_, key) != ((void *)0); }
|
||||
_Bool mm_empty(multimap *_map_) { return _map_->count == 0; }
|
||||
_Bool mm_full(multimap *_map_) { return (double)mm_capacity(_map_) * mm_load(_map_) <= (double)mm_count(_map_); }
|
||||
size_t mm_count(multimap *_map_) { return _map_->count; }
|
||||
size_t mm_key_count(multimap *_map_, size_t key)
|
||||
{
|
||||
size_t hash = _map_->hash(key);
|
||||
multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0];
|
||||
size_t total_count = 0;
|
||||
if (!entry)
|
||||
return total_count;
|
||||
while (entry != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
total_count++;
|
||||
entry = entry->next;
|
||||
}
|
||||
return total_count;
|
||||
}
|
||||
size_t mm_capacity(multimap *_map_) { return _map_->capacity; }
|
||||
double mm_load(multimap *_map_) { return _map_->load; }
|
||||
_Bool mm_resize(multimap *_map_, size_t capacity)
|
||||
{
|
||||
if (mm_capacity(_map_) == capacity)
|
||||
return 1;
|
||||
if (mm_capacity(_map_) > capacity / mm_load(_map_))
|
||||
return 1;
|
||||
if (capacity >= 0xffffffffffffffff * mm_load(_map_))
|
||||
return 0;
|
||||
size_t theoretical_size = mm_impl_calculate_size(capacity);
|
||||
if (theoretical_size < mm_count(_map_) / mm_load(_map_))
|
||||
return 0;
|
||||
multimap *_new_map_ = mm_new(capacity, mm_load(_map_), _map_->cmp, _map_->hash);
|
||||
if (!_new_map_)
|
||||
return 0;
|
||||
multimap_iter iter;
|
||||
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
size_t key = mm_iter_key(&iter);
|
||||
size_t value = mm_iter_value(&iter);
|
||||
mm_insert(_new_map_, key, value);
|
||||
}
|
||||
if (mm_count(_map_) != mm_count(_new_map_))
|
||||
{
|
||||
mm_free(_new_map_, ((void *)0));
|
||||
return 0;
|
||||
}
|
||||
multimap_entry *(*tmp_b)[2] = _map_->buffer;
|
||||
_map_->buffer = _new_map_->buffer;
|
||||
_new_map_->buffer = tmp_b;
|
||||
size_t tmp_c = _map_->capacity;
|
||||
_map_->capacity = _new_map_->capacity;
|
||||
_new_map_->capacity = tmp_c;
|
||||
mm_free(_new_map_, ((void *)0));
|
||||
return 1;
|
||||
}
|
||||
multimap *mm_copy_of(multimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t))
|
||||
{
|
||||
multimap *result = mm_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
multimap_iter iter;
|
||||
mm_iter_init(&iter, _map_);
|
||||
if (!mm_empty(_map_))
|
||||
{
|
||||
for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
size_t key = mm_iter_key(&iter);
|
||||
size_t value = mm_iter_value(&iter);
|
||||
if (key_copy_func)
|
||||
key = key_copy_func(key);
|
||||
if (value_copy_func)
|
||||
value = value_copy_func(value);
|
||||
mm_insert(result, key, value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
_Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count)
|
||||
{
|
||||
if (ignore_key_count)
|
||||
{
|
||||
multimap_iter iter;
|
||||
mm_iter_init(&iter, _map1_);
|
||||
for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
if (mm_impl_get_entry(_map2_, mm_iter_key(&iter)) == ((void *)0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mm_count(_map1_) != mm_count(_map2_))
|
||||
return 0;
|
||||
multimap_iter iter;
|
||||
mm_iter_init(&iter, _map1_);
|
||||
for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
size_t key = mm_iter_key(&iter);
|
||||
if (mm_key_count(_map1_, key) != mm_key_count(_map2_, key))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string mm_to_string(multimap *_map_)
|
||||
{
|
||||
cmc_string str;
|
||||
multimap *m_ = _map_;
|
||||
const char *name = "multimap";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash);
|
||||
return str;
|
||||
}
|
||||
multimap_iter *mm_iter_new(multimap *target)
|
||||
{
|
||||
multimap_iter *iter = malloc(sizeof(multimap_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
mm_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void mm_iter_free(multimap_iter *iter) { free(iter); }
|
||||
void mm_iter_init(multimap_iter *iter, multimap *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(multimap_iter));
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = mm_empty(target);
|
||||
if (!mm_empty(target))
|
||||
{
|
||||
for (size_t i = 0; i < target->capacity; i++)
|
||||
{
|
||||
if (target->buffer[i][0] != NULL)
|
||||
if (target->buffer[i][0] != ((void *)0))
|
||||
{
|
||||
iter->curr_entry = target->buffer[i][0];
|
||||
iter->first = i;
|
||||
@@ -354,7 +520,7 @@ void mm_iter_init(multimap_iter *iter, multimap *target)
|
||||
iter->cursor = iter->first;
|
||||
for (size_t i = target->capacity; i > 0; i--)
|
||||
{
|
||||
if (target->buffer[i - 1][0] != NULL)
|
||||
if (target->buffer[i - 1][0] != ((void *)0))
|
||||
{
|
||||
iter->last = i - 1;
|
||||
break;
|
||||
@@ -362,29 +528,35 @@ void mm_iter_init(multimap_iter *iter, multimap *target)
|
||||
}
|
||||
}
|
||||
}
|
||||
bool mm_iter_start(multimap_iter *iter) { return mm_empty(iter->target) || iter->start; }
|
||||
bool mm_iter_end(multimap_iter *iter) { return mm_empty(iter->target) || iter->end; }
|
||||
_Bool mm_iter_start(multimap_iter *iter) { return mm_empty(iter->target) || iter->start; }
|
||||
_Bool mm_iter_end(multimap_iter *iter) { return mm_empty(iter->target) || iter->end; }
|
||||
void mm_iter_to_start(multimap_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = mm_empty(iter->target);
|
||||
iter->curr_entry = iter->target->buffer[iter->first][0];
|
||||
if (!mm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = mm_empty(iter->target);
|
||||
iter->curr_entry = iter->target->buffer[iter->first][0];
|
||||
}
|
||||
}
|
||||
void mm_iter_to_end(multimap_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = mm_empty(iter->target);
|
||||
iter->end = true;
|
||||
iter->curr_entry = iter->target->buffer[iter->last][1];
|
||||
if (!mm_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = mm_empty(iter->target);
|
||||
iter->end = 1;
|
||||
iter->curr_entry = iter->target->buffer[iter->last][1];
|
||||
}
|
||||
}
|
||||
bool mm_iter_next(multimap_iter *iter)
|
||||
_Bool mm_iter_next(multimap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
if (iter->curr_entry->next != NULL)
|
||||
return 0;
|
||||
if (iter->curr_entry->next != ((void *)0))
|
||||
{
|
||||
iter->curr_entry = iter->curr_entry->next;
|
||||
iter->index++;
|
||||
@@ -393,26 +565,23 @@ bool mm_iter_next(multimap_iter *iter)
|
||||
{
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->cursor++;
|
||||
while (iter->target->buffer[iter->cursor][0] == ((void *)0))
|
||||
iter->cursor++;
|
||||
while (iter->target->buffer[iter->cursor][0] == NULL)
|
||||
iter->cursor++;
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][0];
|
||||
iter->index++;
|
||||
}
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][0];
|
||||
iter->index++;
|
||||
}
|
||||
iter->start = mm_empty(iter->target);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool mm_iter_prev(multimap_iter *iter)
|
||||
_Bool mm_iter_prev(multimap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
if (iter->curr_entry->prev != NULL)
|
||||
return 0;
|
||||
if (iter->curr_entry->prev != ((void *)0))
|
||||
{
|
||||
iter->curr_entry = iter->curr_entry->prev;
|
||||
iter->index--;
|
||||
@@ -421,98 +590,99 @@ bool mm_iter_prev(multimap_iter *iter)
|
||||
{
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->cursor--;
|
||||
while (iter->target->buffer[iter->cursor][1] == ((void *)0))
|
||||
iter->cursor--;
|
||||
while (iter->target->buffer[iter->cursor][1] == NULL)
|
||||
iter->cursor--;
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][1];
|
||||
iter->index--;
|
||||
}
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][1];
|
||||
iter->index--;
|
||||
}
|
||||
iter->end = mm_empty(iter->target);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
_Bool mm_iter_advance(multimap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == mm_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= mm_count(iter->target))
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
mm_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool mm_iter_rewind(multimap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
mm_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool mm_iter_go_to(multimap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= mm_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return mm_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return mm_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t mm_iter_key(multimap_iter *iter)
|
||||
{
|
||||
if (mm_empty(iter->target))
|
||||
return mm_impl_default_key();
|
||||
return (size_t){0};
|
||||
return iter->curr_entry->key;
|
||||
}
|
||||
size_t mm_iter_value(multimap_iter *iter)
|
||||
{
|
||||
if (mm_empty(iter->target))
|
||||
return mm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->curr_entry->value;
|
||||
}
|
||||
size_t *mm_iter_rvalue(multimap_iter *iter)
|
||||
{
|
||||
if (mm_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->curr_entry->value);
|
||||
}
|
||||
size_t mm_iter_index(multimap_iter *iter) { return iter->index; }
|
||||
bool mm_impl_grow(multimap *_map_)
|
||||
{
|
||||
size_t new_capacity = mm_impl_calculate_size(_map_->capacity * 1.5);
|
||||
multimap *_new_map_ = mm_new(new_capacity, _map_->load, _map_->cmp, _map_->hash);
|
||||
if (!_new_map_)
|
||||
return false;
|
||||
multimap_iter iter;
|
||||
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
|
||||
{
|
||||
size_t key = mm_iter_key(&iter);
|
||||
size_t value = mm_iter_value(&iter);
|
||||
mm_insert(_new_map_, key, value);
|
||||
}
|
||||
if (_map_->count != _new_map_->count)
|
||||
{
|
||||
mm_free(_new_map_);
|
||||
return false;
|
||||
}
|
||||
multimap_entry *(*tmp_b)[2] = _map_->buffer;
|
||||
_map_->buffer = _new_map_->buffer;
|
||||
_new_map_->buffer = tmp_b;
|
||||
size_t tmp_c = _map_->capacity;
|
||||
_map_->capacity = _new_map_->capacity;
|
||||
_new_map_->capacity = tmp_c;
|
||||
mm_free(_new_map_);
|
||||
return true;
|
||||
}
|
||||
multimap_entry *mm_impl_new_entry(size_t key, size_t value)
|
||||
{
|
||||
multimap_entry *entry = malloc(sizeof(multimap_entry));
|
||||
if (!entry)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
entry->next = NULL;
|
||||
entry->prev = NULL;
|
||||
entry->next = ((void *)0);
|
||||
entry->prev = ((void *)0);
|
||||
return entry;
|
||||
}
|
||||
multimap_entry *mm_impl_get_entry(multimap *_map_, size_t key)
|
||||
{
|
||||
size_t hash = _map_->hash(key);
|
||||
multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0];
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
if (entry->next == NULL && entry->prev == NULL)
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
return entry;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
while (entry != NULL)
|
||||
while (entry != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(entry->key, key) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
size_t mm_impl_calculate_size(size_t required)
|
||||
{
|
||||
|
||||
+296
-179
@@ -1,6 +1,6 @@
|
||||
#include "ext/multiset.h"
|
||||
#include <cmc/multiset.h>
|
||||
|
||||
//MULTISET_GENERATE(ms, multiset, , size_t)
|
||||
//CMC_GENERATE_MULTISET(ms, multiset, size_t)
|
||||
|
||||
typedef struct multiset_s
|
||||
{
|
||||
@@ -28,58 +28,57 @@ typedef struct multiset_iter_s
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} multiset_iter, *multiset_iter_ptr;
|
||||
multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
|
||||
void ms_clear(multiset *_set_);
|
||||
void ms_free(multiset *_set_);
|
||||
bool ms_insert(multiset *_set_, size_t element);
|
||||
bool ms_insert_many(multiset *_set_, size_t element, size_t count);
|
||||
bool ms_update(multiset *_set_, size_t element, size_t multiplicity);
|
||||
bool ms_remove(multiset *_set_, size_t element);
|
||||
void ms_clear(multiset *_set_, void (*deallocator)(size_t));
|
||||
void ms_free(multiset *_set_, void (*deallocator)(size_t));
|
||||
_Bool ms_insert(multiset *_set_, size_t element);
|
||||
_Bool ms_insert_many(multiset *_set_, size_t element, size_t count);
|
||||
_Bool ms_update(multiset *_set_, size_t element, size_t multiplicity);
|
||||
_Bool ms_remove(multiset *_set_, size_t element);
|
||||
size_t ms_remove_all(multiset *_set_, size_t element);
|
||||
bool ms_insert_if(multiset *_set_, size_t element, bool condition);
|
||||
bool ms_remove_if(multiset *_set_, size_t element, bool condition);
|
||||
bool ms_max(multiset *_set_, size_t *value);
|
||||
bool ms_min(multiset *_set_, size_t *value);
|
||||
_Bool ms_max(multiset *_set_, size_t *value);
|
||||
_Bool ms_min(multiset *_set_, size_t *value);
|
||||
size_t ms_multiplicity_of(multiset *_set_, size_t element);
|
||||
bool ms_contains(multiset *_set_, size_t element);
|
||||
bool ms_empty(multiset *_set_);
|
||||
_Bool ms_contains(multiset *_set_, size_t element);
|
||||
_Bool ms_empty(multiset *_set_);
|
||||
_Bool ms_full(multiset *_set_);
|
||||
size_t ms_count(multiset *_set_);
|
||||
size_t ms_cardinality(multiset *_set_);
|
||||
size_t ms_capacity(multiset *_set_);
|
||||
double ms_load(multiset *_set_);
|
||||
_Bool ms_resize(multiset *_set_, size_t capacity);
|
||||
multiset *ms_copy_of(multiset *_set_, size_t (*copy_func)(size_t));
|
||||
_Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity);
|
||||
cmc_string ms_to_string(multiset *_set_);
|
||||
multiset *ms_union(multiset *_set1_, multiset *_set2_);
|
||||
multiset *ms_intersection(multiset *_set1_, multiset *_set2_);
|
||||
multiset *ms_difference(multiset *_set1_, multiset *_set2_);
|
||||
multiset *ms_summation(multiset *_set1_, multiset *_set2_);
|
||||
multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_);
|
||||
bool ms_is_subset(multiset *_set1_, multiset *_set2_);
|
||||
bool ms_is_superset(multiset *_set1_, multiset *_set2_);
|
||||
bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_);
|
||||
bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_);
|
||||
bool ms_is_disjointset(multiset *_set1_, multiset *_set2_);
|
||||
_Bool ms_is_subset(multiset *_set1_, multiset *_set2_);
|
||||
_Bool ms_is_superset(multiset *_set1_, multiset *_set2_);
|
||||
_Bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_);
|
||||
_Bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_);
|
||||
_Bool ms_is_disjointset(multiset *_set1_, multiset *_set2_);
|
||||
multiset_iter *ms_iter_new(multiset *target);
|
||||
void ms_iter_free(multiset_iter *iter);
|
||||
void ms_iter_init(multiset_iter *iter, multiset *target);
|
||||
bool ms_iter_start(multiset_iter *iter);
|
||||
bool ms_iter_end(multiset_iter *iter);
|
||||
_Bool ms_iter_start(multiset_iter *iter);
|
||||
_Bool ms_iter_end(multiset_iter *iter);
|
||||
void ms_iter_to_start(multiset_iter *iter);
|
||||
void ms_iter_to_end(multiset_iter *iter);
|
||||
bool ms_iter_next(multiset_iter *iter);
|
||||
bool ms_iter_prev(multiset_iter *iter);
|
||||
_Bool ms_iter_next(multiset_iter *iter);
|
||||
_Bool ms_iter_prev(multiset_iter *iter);
|
||||
_Bool ms_iter_advance(multiset_iter *iter, size_t steps);
|
||||
_Bool ms_iter_rewind(multiset_iter *iter, size_t steps);
|
||||
_Bool ms_iter_go_to(multiset_iter *iter, size_t index);
|
||||
size_t ms_iter_value(multiset_iter *iter);
|
||||
size_t ms_iter_multiplicity(multiset_iter *iter);
|
||||
size_t ms_iter_index(multiset_iter *iter);
|
||||
static inline size_t ms_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, bool *new_node);
|
||||
static bool ms_impl_grow(multiset *_set_);
|
||||
static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, _Bool *new_node);
|
||||
static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element);
|
||||
static size_t ms_impl_calculate_size(size_t required);
|
||||
static multiset_iter ms_impl_it_start(multiset *_set_);
|
||||
@@ -87,18 +86,18 @@ static multiset_iter ms_impl_it_end(multiset *_set_);
|
||||
multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return NULL;
|
||||
if (capacity >= UINTMAX_MAX * load)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
return ((void *)0);
|
||||
size_t real_capacity = ms_impl_calculate_size(capacity / load);
|
||||
multiset *_set_ = malloc(sizeof(multiset));
|
||||
if (!_set_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_set_->buffer = malloc(sizeof(multiset_entry) * real_capacity);
|
||||
if (!_set_->buffer)
|
||||
{
|
||||
free(_set_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_set_->buffer, 0, sizeof(multiset_entry) * real_capacity);
|
||||
_set_->count = 0;
|
||||
@@ -111,81 +110,103 @@ multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), s
|
||||
_set_->it_end = ms_impl_it_end;
|
||||
return _set_;
|
||||
}
|
||||
void ms_clear(multiset *_set_)
|
||||
void ms_clear(multiset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
multiset_entry *entry = &(_set_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(_set_->buffer, 0, sizeof(multiset_entry) * _set_->capacity);
|
||||
_set_->count = 0;
|
||||
}
|
||||
void ms_free(multiset *_set_)
|
||||
void ms_free(multiset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
multiset_entry *entry = &(_set_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
deallocator(entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(_set_->buffer);
|
||||
free(_set_);
|
||||
}
|
||||
bool ms_insert(multiset *_set_, size_t element)
|
||||
_Bool ms_insert(multiset *_set_, size_t element)
|
||||
{
|
||||
bool new_node;
|
||||
_Bool new_node;
|
||||
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
|
||||
if (!entry)
|
||||
return false;
|
||||
return 0;
|
||||
if (!new_node)
|
||||
entry->multiplicity++;
|
||||
_set_->cardinality++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_insert_many(multiset *_set_, size_t element, size_t count)
|
||||
_Bool ms_insert_many(multiset *_set_, size_t element, size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return true;
|
||||
bool new_node;
|
||||
return 1;
|
||||
_Bool new_node;
|
||||
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
|
||||
if (!entry)
|
||||
return false;
|
||||
return 0;
|
||||
if (new_node)
|
||||
entry->multiplicity = count;
|
||||
else
|
||||
entry->multiplicity += count;
|
||||
_set_->cardinality += count;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_update(multiset *_set_, size_t element, size_t multiplicity)
|
||||
_Bool ms_update(multiset *_set_, size_t element, size_t multiplicity)
|
||||
{
|
||||
if (multiplicity == 0)
|
||||
return ms_remove_all(_set_, element);
|
||||
bool new_node;
|
||||
_Bool new_node;
|
||||
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
|
||||
if (!entry)
|
||||
return false;
|
||||
return 0;
|
||||
if (new_node)
|
||||
_set_->cardinality++;
|
||||
_set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity;
|
||||
entry->multiplicity = multiplicity;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_remove(multiset *_set_, size_t element)
|
||||
_Bool ms_remove(multiset *_set_, size_t element)
|
||||
{
|
||||
multiset_entry *result = ms_impl_get_entry(_set_, element);
|
||||
if (result == NULL)
|
||||
return false;
|
||||
if (result == ((void *)0))
|
||||
return 0;
|
||||
if (result->multiplicity > 1)
|
||||
result->multiplicity--;
|
||||
else
|
||||
{
|
||||
result->value = ms_impl_default_value();
|
||||
result->value = (size_t){0};
|
||||
result->multiplicity = 0;
|
||||
result->dist = 0;
|
||||
result->state = CMC_ES_DELETED;
|
||||
_set_->count--;
|
||||
}
|
||||
_set_->cardinality--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
size_t ms_remove_all(multiset *_set_, size_t element)
|
||||
{
|
||||
multiset_entry *result = ms_impl_get_entry(_set_, element);
|
||||
if (result == NULL)
|
||||
if (result == ((void *)0))
|
||||
return 0;
|
||||
size_t removed = result->multiplicity;
|
||||
result->value = ms_impl_default_value();
|
||||
result->value = (size_t){0};
|
||||
result->multiplicity = 0;
|
||||
result->dist = 0;
|
||||
result->state = CMC_ES_DELETED;
|
||||
@@ -193,22 +214,10 @@ size_t ms_remove_all(multiset *_set_, size_t element)
|
||||
_set_->cardinality -= removed;
|
||||
return removed;
|
||||
}
|
||||
bool ms_insert_if(multiset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ms_insert(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool ms_remove_if(multiset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ms_remove(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool ms_max(multiset *_set_, size_t *value)
|
||||
_Bool ms_max(multiset *_set_, size_t *value)
|
||||
{
|
||||
if (ms_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
multiset_iter iter;
|
||||
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
@@ -219,12 +228,12 @@ bool ms_max(multiset *_set_, size_t *value)
|
||||
else if (_set_->cmp(result, *value) > 0)
|
||||
*value = result;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_min(multiset *_set_, size_t *value)
|
||||
_Bool ms_min(multiset *_set_, size_t *value)
|
||||
{
|
||||
if (ms_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
multiset_iter iter;
|
||||
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
@@ -235,7 +244,7 @@ bool ms_min(multiset *_set_, size_t *value)
|
||||
else if (_set_->cmp(result, *value) < 0)
|
||||
*value = result;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
size_t ms_multiplicity_of(multiset *_set_, size_t element)
|
||||
{
|
||||
@@ -244,11 +253,97 @@ size_t ms_multiplicity_of(multiset *_set_, size_t element)
|
||||
return 0;
|
||||
return entry->multiplicity;
|
||||
}
|
||||
bool ms_contains(multiset *_set_, size_t element) { return ms_impl_get_entry(_set_, element) != NULL; }
|
||||
bool ms_empty(multiset *_set_) { return _set_->count == 0; }
|
||||
_Bool ms_contains(multiset *_set_, size_t element) { return ms_impl_get_entry(_set_, element) != ((void *)0); }
|
||||
_Bool ms_empty(multiset *_set_) { return _set_->count == 0; }
|
||||
_Bool ms_full(multiset *_set_) { return (double)ms_capacity(_set_) * ms_load(_set_) <= (double)ms_count(_set_); }
|
||||
size_t ms_count(multiset *_set_) { return _set_->count; }
|
||||
size_t ms_cardinality(multiset *_set_) { return _set_->cardinality; }
|
||||
size_t ms_capacity(multiset *_set_) { return _set_->capacity; }
|
||||
double ms_load(multiset *_set_) { return _set_->load; }
|
||||
_Bool ms_resize(multiset *_set_, size_t capacity)
|
||||
{
|
||||
if (ms_capacity(_set_) == capacity)
|
||||
return 1;
|
||||
if (ms_capacity(_set_) > capacity / ms_load(_set_))
|
||||
return 1;
|
||||
if (capacity >= 0xffffffffffffffff * ms_load(_set_))
|
||||
return 0;
|
||||
size_t theoretical_size = ms_impl_calculate_size(capacity);
|
||||
if (theoretical_size < ms_count(_set_) / ms_load(_set_))
|
||||
return 0;
|
||||
multiset *_new_set_ = ms_new(capacity, ms_load(_set_), _set_->cmp, _set_->hash);
|
||||
if (!_new_set_)
|
||||
return 0;
|
||||
multiset_iter iter;
|
||||
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
ms_insert_many(_new_set_, ms_iter_value(&iter), ms_iter_multiplicity(&iter));
|
||||
}
|
||||
if (ms_count(_set_) != ms_count(_new_set_))
|
||||
{
|
||||
ms_free(_new_set_, ((void *)0));
|
||||
return 0;
|
||||
}
|
||||
multiset_entry *tmp_b = _set_->buffer;
|
||||
_set_->buffer = _new_set_->buffer;
|
||||
_new_set_->buffer = tmp_b;
|
||||
size_t tmp_c = _set_->capacity;
|
||||
_set_->capacity = _new_set_->capacity;
|
||||
_new_set_->capacity = tmp_c;
|
||||
ms_free(_new_set_, ((void *)0));
|
||||
return 1;
|
||||
}
|
||||
multiset *ms_copy_of(multiset *_set_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
multiset *result = ms_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
multiset_entry *scan = &(_set_->buffer[i]);
|
||||
if (scan->state != CMC_ES_EMPTY)
|
||||
{
|
||||
multiset_entry *target = &(result->buffer[i]);
|
||||
if (scan->state == CMC_ES_DELETED)
|
||||
target->state = CMC_ES_DELETED;
|
||||
else
|
||||
{
|
||||
target->state = scan->state;
|
||||
target->dist = scan->dist;
|
||||
target->multiplicity = scan->multiplicity;
|
||||
target->value = copy_func(scan->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _set_->buffer, sizeof(multiset_entry) * _set_->capacity);
|
||||
result->count = _set_->count;
|
||||
result->cardinality = _set_->cardinality;
|
||||
return result;
|
||||
}
|
||||
_Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity)
|
||||
{
|
||||
if (ms_count(_set1_) != ms_count(_set2_))
|
||||
return 0;
|
||||
if (!ignore_multiplicity && ms_cardinality(_set1_) != ms_cardinality(_set2_))
|
||||
return 0;
|
||||
if (ms_count(_set1_) == 0)
|
||||
return 1;
|
||||
multiset_iter iter;
|
||||
ms_iter_init(&iter, _set1_);
|
||||
for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
multiset_entry *entry = ms_impl_get_entry(_set2_, ms_iter_value(&iter));
|
||||
if (entry == ((void *)0))
|
||||
return 0;
|
||||
if (!ignore_multiplicity && entry->multiplicity != ms_iter_multiplicity(&iter))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string ms_to_string(multiset *_set_)
|
||||
{
|
||||
cmc_string str;
|
||||
@@ -261,7 +356,7 @@ multiset *ms_union(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
multiset_iter iter1, iter2;
|
||||
ms_iter_init(&iter1, _set1_);
|
||||
ms_iter_init(&iter2, _set2_);
|
||||
@@ -287,7 +382,7 @@ multiset *ms_intersection(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
multiset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
|
||||
multiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
|
||||
multiset_iter iter;
|
||||
@@ -306,7 +401,7 @@ multiset *ms_difference(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
multiset_iter iter;
|
||||
ms_iter_init(&iter, _set1_);
|
||||
for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
@@ -323,7 +418,7 @@ multiset *ms_summation(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
multiset_iter iter1, iter2;
|
||||
ms_iter_init(&iter1, _set1_);
|
||||
ms_iter_init(&iter2, _set2_);
|
||||
@@ -342,7 +437,7 @@ multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_)
|
||||
multiset_iter iter1, iter2;
|
||||
multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
ms_iter_init(&iter1, _set1_);
|
||||
ms_iter_init(&iter2, _set2_);
|
||||
for (ms_iter_to_start(&iter1); !ms_iter_end(&iter1); ms_iter_next(&iter1))
|
||||
@@ -373,12 +468,12 @@ multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_)
|
||||
}
|
||||
return _set_r_;
|
||||
}
|
||||
bool ms_is_subset(multiset *_set1_, multiset *_set2_)
|
||||
_Bool ms_is_subset(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
if (ms_count(_set1_) > ms_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (ms_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
multiset_iter iter;
|
||||
ms_iter_init(&iter, _set1_);
|
||||
for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
@@ -387,21 +482,21 @@ bool ms_is_subset(multiset *_set1_, multiset *_set2_)
|
||||
size_t m1 = ms_iter_multiplicity(&iter);
|
||||
size_t m2 = ms_multiplicity_of(_set2_, value);
|
||||
if (m1 > m2)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_is_superset(multiset *_set1_, multiset *_set2_) { return ms_is_subset(_set2_, _set1_); }
|
||||
bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_)
|
||||
_Bool ms_is_superset(multiset *_set1_, multiset *_set2_) { return ms_is_subset(_set2_, _set1_); }
|
||||
_Bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
if (ms_count(_set1_) >= ms_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (ms_empty(_set1_))
|
||||
{
|
||||
if (!ms_empty(_set2_))
|
||||
return true;
|
||||
return 1;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
multiset_iter iter;
|
||||
ms_iter_init(&iter, _set1_);
|
||||
@@ -411,40 +506,39 @@ bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_)
|
||||
size_t m1 = ms_iter_multiplicity(&iter);
|
||||
size_t m2 = ms_multiplicity_of(_set2_, value);
|
||||
if (m1 >= m2)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_) { return ms_is_proper_subset(_set2_, _set1_); }
|
||||
bool ms_is_disjointset(multiset *_set1_, multiset *_set2_)
|
||||
_Bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_) { return ms_is_proper_subset(_set2_, _set1_); }
|
||||
_Bool ms_is_disjointset(multiset *_set1_, multiset *_set2_)
|
||||
{
|
||||
if (ms_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
multiset_iter iter;
|
||||
ms_iter_init(&iter, _set1_);
|
||||
for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
size_t value = ms_iter_value(&iter);
|
||||
if (ms_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
multiset_iter *ms_iter_new(multiset *target)
|
||||
{
|
||||
multiset_iter *iter = malloc(sizeof(multiset_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
ms_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void ms_iter_free(multiset_iter *iter) { free(iter); }
|
||||
void ms_iter_init(multiset_iter *iter, multiset *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(multiset_iter));
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = ms_empty(target);
|
||||
if (!ms_empty(target))
|
||||
{
|
||||
@@ -467,68 +561,114 @@ void ms_iter_init(multiset_iter *iter, multiset *target)
|
||||
}
|
||||
}
|
||||
}
|
||||
bool ms_iter_start(multiset_iter *iter) { return ms_empty(iter->target) || iter->start; }
|
||||
bool ms_iter_end(multiset_iter *iter) { return ms_empty(iter->target) || iter->end; }
|
||||
_Bool ms_iter_start(multiset_iter *iter) { return ms_empty(iter->target) || iter->start; }
|
||||
_Bool ms_iter_end(multiset_iter *iter) { return ms_empty(iter->target) || iter->end; }
|
||||
void ms_iter_to_start(multiset_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = ms_empty(iter->target);
|
||||
if (!ms_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->first;
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = ms_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void ms_iter_to_end(multiset_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ms_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!ms_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->last;
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ms_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool ms_iter_next(multiset_iter *iter)
|
||||
_Bool ms_iter_next(multiset_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
multiset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->last)
|
||||
iter->end = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index + 1 == ms_count(iter->target))
|
||||
{
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor++;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = ms_empty(iter->target);
|
||||
return true;
|
||||
multiset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index++;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor++;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool ms_iter_prev(multiset_iter *iter)
|
||||
_Bool ms_iter_prev(multiset_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
multiset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (iter->cursor == iter->first)
|
||||
iter->start = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor--;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = ms_empty(iter->target);
|
||||
return true;
|
||||
multiset_entry *scan = &(iter->target->buffer[iter->cursor]);
|
||||
iter->index--;
|
||||
while (1)
|
||||
{
|
||||
iter->cursor--;
|
||||
scan = &(iter->target->buffer[iter->cursor]);
|
||||
if (scan->state == CMC_ES_FILLED)
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_Bool ms_iter_advance(multiset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == ms_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= ms_count(iter->target))
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
ms_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool ms_iter_rewind(multiset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
ms_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool ms_iter_go_to(multiset_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= ms_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return ms_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return ms_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t ms_iter_value(multiset_iter *iter)
|
||||
{
|
||||
if (ms_empty(iter->target))
|
||||
return ms_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor].value;
|
||||
}
|
||||
size_t ms_iter_multiplicity(multiset_iter *iter)
|
||||
@@ -538,17 +678,17 @@ size_t ms_iter_multiplicity(multiset_iter *iter)
|
||||
return iter->target->buffer[iter->cursor].multiplicity;
|
||||
}
|
||||
size_t ms_iter_index(multiset_iter *iter) { return iter->index; }
|
||||
static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, bool *new_node)
|
||||
static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, _Bool *new_node)
|
||||
{
|
||||
*new_node = false;
|
||||
*new_node = 0;
|
||||
multiset_entry *entry = ms_impl_get_entry(_set_, element);
|
||||
if (entry != NULL)
|
||||
if (entry != ((void *)0))
|
||||
return entry;
|
||||
*new_node = true;
|
||||
if ((double)_set_->capacity * _set_->load <= (double)_set_->count)
|
||||
*new_node = 1;
|
||||
if (ms_full(_set_))
|
||||
{
|
||||
if (!ms_impl_grow(_set_))
|
||||
return NULL;
|
||||
if (!ms_resize(_set_, ms_capacity(_set_) + 1))
|
||||
return ((void *)0);
|
||||
}
|
||||
size_t hash = _set_->hash(element);
|
||||
size_t original_pos = hash % _set_->capacity;
|
||||
@@ -564,7 +704,7 @@ static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
pos++;
|
||||
target = &(_set_->buffer[pos % _set_->capacity]);
|
||||
@@ -593,29 +733,6 @@ static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element
|
||||
_set_->count++;
|
||||
return target;
|
||||
}
|
||||
static bool ms_impl_grow(multiset *_set_)
|
||||
{
|
||||
size_t new_size = ms_impl_calculate_size(_set_->capacity + _set_->capacity / 2);
|
||||
multiset *_new_set_ = ms_new(new_size, _set_->load, _set_->cmp, _set_->hash);
|
||||
if (!_new_set_)
|
||||
return false;
|
||||
multiset_iter iter;
|
||||
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
|
||||
{
|
||||
ms_insert_many(_new_set_, ms_iter_value(&iter), ms_iter_multiplicity(&iter));
|
||||
}
|
||||
if (_set_->count != _new_set_->count)
|
||||
{
|
||||
ms_free(_new_set_);
|
||||
return false;
|
||||
}
|
||||
multiset_entry *tmp = _set_->buffer;
|
||||
_set_->buffer = _new_set_->buffer;
|
||||
_new_set_->buffer = tmp;
|
||||
_set_->capacity = _new_set_->capacity;
|
||||
ms_free(_new_set_);
|
||||
return true;
|
||||
}
|
||||
static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element)
|
||||
{
|
||||
size_t hash = _set_->hash(element);
|
||||
@@ -628,7 +745,7 @@ static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element)
|
||||
pos++;
|
||||
target = &(_set_->buffer[pos % _set_->capacity]);
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
static size_t ms_impl_calculate_size(size_t required)
|
||||
{
|
||||
|
||||
+206
-104
@@ -1,6 +1,6 @@
|
||||
#include "cmc/queue.h"
|
||||
#include <cmc/queue.h>
|
||||
|
||||
//QUEUE_GENERATE(q, queue, , size_t)
|
||||
//CMC_GENERATE_QUEUE(q, queue, size_t)
|
||||
|
||||
typedef struct queue_s
|
||||
{
|
||||
@@ -8,7 +8,7 @@ typedef struct queue_s
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
size_t front;
|
||||
size_t rear;
|
||||
size_t back;
|
||||
struct queue_iter_s (*it_start)(struct queue_s *);
|
||||
struct queue_iter_s (*it_end)(struct queue_s *);
|
||||
} queue, *queue_ptr;
|
||||
@@ -17,134 +17,204 @@ typedef struct queue_iter_s
|
||||
struct queue_s *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} queue_iter, *queue_iter_ptr;
|
||||
queue *q_new(size_t capacity);
|
||||
void q_clear(queue *_queue_);
|
||||
void q_free(queue *_queue_);
|
||||
bool q_enqueue(queue *_queue_, size_t element);
|
||||
bool q_dequeue(queue *_queue_);
|
||||
bool q_enqueue_if(queue *_queue_, size_t element, bool condition);
|
||||
bool q_dequeue_if(queue *_queue_, bool condition);
|
||||
void q_clear(queue *_queue_, void (*deallocator)(size_t));
|
||||
void q_free(queue *_queue_, void (*deallocator)(size_t));
|
||||
_Bool q_enqueue(queue *_queue_, size_t element);
|
||||
_Bool q_dequeue(queue *_queue_);
|
||||
size_t q_peek(queue *_queue_);
|
||||
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t));
|
||||
bool q_empty(queue *_queue_);
|
||||
bool q_full(queue *_queue_);
|
||||
_Bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t));
|
||||
_Bool q_empty(queue *_queue_);
|
||||
_Bool q_full(queue *_queue_);
|
||||
size_t q_count(queue *_queue_);
|
||||
size_t q_capacity(queue *_queue_);
|
||||
_Bool q_resize(queue *_queue_, size_t capacity);
|
||||
queue *q_copy_of(queue *_queue_, size_t (*copy_func)(size_t));
|
||||
_Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_t));
|
||||
cmc_string q_to_string(queue *_queue_);
|
||||
queue_iter *q_iter_new(queue *target);
|
||||
void q_iter_free(queue_iter *iter);
|
||||
void q_iter_init(queue_iter *iter, queue *target);
|
||||
bool q_iter_start(queue_iter *iter);
|
||||
bool q_iter_end(queue_iter *iter);
|
||||
_Bool q_iter_start(queue_iter *iter);
|
||||
_Bool q_iter_end(queue_iter *iter);
|
||||
void q_iter_to_start(queue_iter *iter);
|
||||
void q_iter_to_end(queue_iter *iter);
|
||||
bool q_iter_next(queue_iter *iter);
|
||||
bool q_iter_prev(queue_iter *iter);
|
||||
_Bool q_iter_next(queue_iter *iter);
|
||||
_Bool q_iter_prev(queue_iter *iter);
|
||||
_Bool q_iter_advance(queue_iter *iter, size_t steps);
|
||||
_Bool q_iter_rewind(queue_iter *iter, size_t steps);
|
||||
_Bool q_iter_go_to(queue_iter *iter, size_t index);
|
||||
size_t q_iter_value(queue_iter *iter);
|
||||
size_t *q_iter_rvalue(queue_iter *iter);
|
||||
size_t q_iter_index(queue_iter *iter);
|
||||
static inline size_t q_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool q_impl_grow(queue *_queue_);
|
||||
static queue_iter q_impl_it_start(queue *_queue_);
|
||||
static queue_iter q_impl_it_end(queue *_queue_);
|
||||
queue *q_new(size_t capacity)
|
||||
{
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
queue *_queue_ = malloc(sizeof(queue));
|
||||
if (!_queue_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_queue_->buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!_queue_->buffer)
|
||||
{
|
||||
free(_queue_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_queue_->buffer, 0, sizeof(size_t) * capacity);
|
||||
_queue_->capacity = capacity;
|
||||
_queue_->count = 0;
|
||||
_queue_->front = 0;
|
||||
_queue_->rear = 0;
|
||||
_queue_->back = 0;
|
||||
_queue_->it_start = q_impl_it_start;
|
||||
_queue_->it_end = q_impl_it_end;
|
||||
return _queue_;
|
||||
}
|
||||
void q_clear(queue *_queue_)
|
||||
void q_clear(queue *_queue_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
deallocator(_queue_->buffer[i]);
|
||||
i = (i + 1) % _queue_->capacity;
|
||||
}
|
||||
}
|
||||
memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity);
|
||||
_queue_->count = 0;
|
||||
_queue_->front = 0;
|
||||
_queue_->rear = 0;
|
||||
_queue_->back = 0;
|
||||
}
|
||||
void q_free(queue *_queue_)
|
||||
void q_free(queue *_queue_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
deallocator(_queue_->buffer[i]);
|
||||
i = (i + 1) % _queue_->capacity;
|
||||
}
|
||||
}
|
||||
free(_queue_->buffer);
|
||||
free(_queue_);
|
||||
}
|
||||
bool q_enqueue(queue *_queue_, size_t element)
|
||||
_Bool q_enqueue(queue *_queue_, size_t element)
|
||||
{
|
||||
if (q_full(_queue_))
|
||||
{
|
||||
if (!q_impl_grow(_queue_))
|
||||
return false;
|
||||
if (!q_resize(_queue_, q_capacity(_queue_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_queue_->buffer[_queue_->rear] = element;
|
||||
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1;
|
||||
_queue_->buffer[_queue_->back] = element;
|
||||
_queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1;
|
||||
_queue_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool q_dequeue(queue *_queue_)
|
||||
_Bool q_dequeue(queue *_queue_)
|
||||
{
|
||||
if (q_empty(_queue_))
|
||||
return false;
|
||||
_queue_->buffer[_queue_->front] = q_impl_default_value();
|
||||
return 0;
|
||||
_queue_->buffer[_queue_->front] = (size_t){0};
|
||||
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1;
|
||||
_queue_->count--;
|
||||
return true;
|
||||
}
|
||||
bool q_enqueue_if(queue *_queue_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return q_enqueue(_queue_, element);
|
||||
return false;
|
||||
}
|
||||
bool q_dequeue_if(queue *_queue_, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return q_dequeue(_queue_);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
size_t q_peek(queue *_queue_)
|
||||
{
|
||||
if (q_empty(_queue_))
|
||||
return q_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _queue_->buffer[_queue_->front];
|
||||
}
|
||||
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t))
|
||||
_Bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++)
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
if (comparator(_queue_->buffer[i], element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
i = (i + 1) % _queue_->capacity;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool q_empty(queue *_queue_) { return _queue_->count == 0; }
|
||||
bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; }
|
||||
_Bool q_empty(queue *_queue_) { return _queue_->count == 0; }
|
||||
_Bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; }
|
||||
size_t q_count(queue *_queue_) { return _queue_->count; }
|
||||
size_t q_capacity(queue *_queue_) { return _queue_->capacity; }
|
||||
_Bool q_resize(queue *_queue_, size_t capacity)
|
||||
{
|
||||
if (q_capacity(_queue_) == capacity)
|
||||
return 1;
|
||||
if (capacity < q_count(_queue_))
|
||||
return 0;
|
||||
size_t *new_buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
new_buffer[j] = _queue_->buffer[i];
|
||||
i = (i + 1) % q_capacity(_queue_);
|
||||
}
|
||||
free(_queue_->buffer);
|
||||
_queue_->buffer = new_buffer;
|
||||
_queue_->capacity = capacity;
|
||||
_queue_->front = 0;
|
||||
_queue_->back = _queue_->count;
|
||||
return 1;
|
||||
}
|
||||
queue *q_copy_of(queue *_queue_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
queue *result = q_new(_queue_->capacity);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
result->buffer[j] = copy_func(_queue_->buffer[i]);
|
||||
i = (i + 1) % _queue_->capacity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++)
|
||||
{
|
||||
result->buffer[j] = _queue_->buffer[i];
|
||||
i = (i + 1) % _queue_->capacity;
|
||||
}
|
||||
}
|
||||
result->count = _queue_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
if (q_count(_queue1_) != q_count(_queue2_))
|
||||
return 0;
|
||||
size_t i, j, k;
|
||||
for (i = _queue1_->front, j = _queue2_->front, k = 0; k < q_count(_queue1_); k++)
|
||||
{
|
||||
if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0)
|
||||
return 0;
|
||||
i = (i + 1) % _queue1_->capacity;
|
||||
j = (j + 1) % _queue2_->capacity;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string q_to_string(queue *_queue_)
|
||||
{
|
||||
cmc_string str;
|
||||
queue *q_ = _queue_;
|
||||
const char *name = "queue";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back);
|
||||
return str;
|
||||
}
|
||||
queue_iter *q_iter_new(queue *target)
|
||||
{
|
||||
queue_iter *iter = malloc(sizeof(queue_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
q_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -154,16 +224,16 @@ void q_iter_init(queue_iter *iter, queue *target)
|
||||
iter->target = target;
|
||||
iter->cursor = target->front;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = q_empty(target);
|
||||
}
|
||||
bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; }
|
||||
bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; }
|
||||
_Bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; }
|
||||
_Bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; }
|
||||
void q_iter_to_start(queue_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->front;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = q_empty(iter->target);
|
||||
}
|
||||
void q_iter_to_end(queue_iter *iter)
|
||||
@@ -171,69 +241,101 @@ void q_iter_to_end(queue_iter *iter)
|
||||
if (q_empty(iter->target))
|
||||
iter->cursor = 0;
|
||||
else
|
||||
iter->cursor = (iter->target->rear == 0) ? iter->target->capacity - 1 : iter->target->rear - 1;
|
||||
{
|
||||
if (iter->target->back == 0)
|
||||
iter->cursor = iter->target->capacity - 1;
|
||||
else
|
||||
iter->cursor = iter->target->back - 1;
|
||||
}
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = q_empty(iter->target);
|
||||
iter->end = true;
|
||||
iter->end = 1;
|
||||
}
|
||||
bool q_iter_next(queue_iter *iter)
|
||||
_Bool q_iter_next(queue_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = q_empty(iter->target);
|
||||
if (iter->index == iter->target->count - 1)
|
||||
iter->end = true;
|
||||
else
|
||||
return 0;
|
||||
if (iter->index + 1 == q_count(iter->target))
|
||||
{
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
|
||||
iter->index++;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->start = q_empty(iter->target);
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
|
||||
iter->index++;
|
||||
return 1;
|
||||
}
|
||||
bool q_iter_prev(queue_iter *iter)
|
||||
_Bool q_iter_prev(queue_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = q_empty(iter->target);
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
iter->start = true;
|
||||
else
|
||||
{
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
|
||||
iter->index--;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
iter->end = q_empty(iter->target);
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
|
||||
iter->index--;
|
||||
return 1;
|
||||
}
|
||||
_Bool q_iter_advance(queue_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->index + 1 == q_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= q_count(iter->target))
|
||||
return 0;
|
||||
iter->start = q_empty(iter->target);
|
||||
iter->index += steps;
|
||||
iter->cursor = (iter->cursor + steps) % iter->target->capacity;
|
||||
return 1;
|
||||
}
|
||||
_Bool q_iter_rewind(queue_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->index == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
iter->end = q_empty(iter->target);
|
||||
iter->index -= steps;
|
||||
if (iter->cursor < steps)
|
||||
iter->cursor += q_capacity(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool q_iter_go_to(queue_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= q_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return q_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return q_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t q_iter_value(queue_iter *iter)
|
||||
{
|
||||
if (q_empty(iter->target))
|
||||
return q_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t *q_iter_rvalue(queue_iter *iter)
|
||||
{
|
||||
if (q_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->target->buffer[iter->cursor]);
|
||||
}
|
||||
size_t q_iter_index(queue_iter *iter) { return iter->index; }
|
||||
static bool q_impl_grow(queue *_queue_)
|
||||
{
|
||||
size_t new_capacity = _queue_->capacity * 2;
|
||||
size_t *new_buffer = malloc(sizeof(size_t) * new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++)
|
||||
{
|
||||
new_buffer[j] = _queue_->buffer[i];
|
||||
}
|
||||
free(_queue_->buffer);
|
||||
_queue_->buffer = new_buffer;
|
||||
_queue_->capacity = new_capacity;
|
||||
_queue_->front = 0;
|
||||
_queue_->rear = _queue_->count;
|
||||
return true;
|
||||
}
|
||||
static queue_iter q_impl_it_start(queue *_queue_)
|
||||
{
|
||||
queue_iter iter;
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
#include <cmc/sortedlist.h>
|
||||
|
||||
//CMC_GENERATE_SORTEDLIST(sl, sortedlist, size_t)
|
||||
|
||||
typedef struct sortedlist_s
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
_Bool is_sorted;
|
||||
int (*cmp)(size_t, size_t);
|
||||
struct sortedlist_iter_s (*it_start)(struct sortedlist_s *);
|
||||
struct sortedlist_iter_s (*it_end)(struct sortedlist_s *);
|
||||
} sortedlist, *sortedlist_ptr;
|
||||
typedef struct sortedlist_iter_s
|
||||
{
|
||||
struct sortedlist_s *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} sortedlist_iter, *sortedlist_iter_ptr;
|
||||
sortedlist *sl_new(size_t capacity, int (*compare)(size_t, size_t));
|
||||
void sl_clear(sortedlist *_list_, void (*deallocator)(size_t));
|
||||
void sl_free(sortedlist *_list_, void (*deallocator)(size_t));
|
||||
_Bool sl_insert(sortedlist *_list_, size_t element);
|
||||
_Bool sl_remove(sortedlist *_list_, size_t index);
|
||||
_Bool sl_max(sortedlist *_list_, size_t *result);
|
||||
_Bool sl_min(sortedlist *_list_, size_t *result);
|
||||
size_t sl_get(sortedlist *_list_, size_t index);
|
||||
size_t sl_indexof(sortedlist *_list_, size_t element, _Bool from_start);
|
||||
_Bool sl_contains(sortedlist *_list_, size_t element);
|
||||
_Bool sl_empty(sortedlist *_list_);
|
||||
_Bool sl_full(sortedlist *_list_);
|
||||
size_t sl_count(sortedlist *_list_);
|
||||
size_t sl_capacity(sortedlist *_list_);
|
||||
_Bool sl_resize(sortedlist *_list_, size_t capacity);
|
||||
void sl_sort(sortedlist *_list_);
|
||||
sortedlist *sl_copy_of(sortedlist *_list_, size_t (*copy_func)(size_t));
|
||||
_Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_);
|
||||
cmc_string sl_to_string(sortedlist *_list_);
|
||||
sortedlist_iter *sl_iter_new(sortedlist *target);
|
||||
void sl_iter_free(sortedlist_iter *iter);
|
||||
void sl_iter_init(sortedlist_iter *iter, sortedlist *target);
|
||||
_Bool sl_iter_start(sortedlist_iter *iter);
|
||||
_Bool sl_iter_end(sortedlist_iter *iter);
|
||||
void sl_iter_to_start(sortedlist_iter *iter);
|
||||
void sl_iter_to_end(sortedlist_iter *iter);
|
||||
_Bool sl_iter_next(sortedlist_iter *iter);
|
||||
_Bool sl_iter_prev(sortedlist_iter *iter);
|
||||
_Bool sl_iter_advance(sortedlist_iter *iter, size_t steps);
|
||||
_Bool sl_iter_rewind(sortedlist_iter *iter, size_t steps);
|
||||
_Bool sl_iter_go_to(sortedlist_iter *iter, size_t index);
|
||||
size_t sl_iter_value(sortedlist_iter *iter);
|
||||
size_t sl_iter_index(sortedlist_iter *iter);
|
||||
static size_t sl_impl_binary_search_first(sortedlist *_list_, size_t value);
|
||||
static size_t sl_impl_binary_search_last(sortedlist *_list_, size_t value);
|
||||
void sl_impl_sort_quicksort(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high);
|
||||
void sl_impl_sort_insertion(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high);
|
||||
static sortedlist_iter sl_impl_it_start(sortedlist *_list_);
|
||||
static sortedlist_iter sl_impl_it_end(sortedlist *_list_);
|
||||
sortedlist *sl_new(size_t capacity, int (*compare)(size_t, size_t))
|
||||
{
|
||||
if (capacity < 1)
|
||||
return ((void *)0);
|
||||
sortedlist *_list_ = malloc(sizeof(sortedlist));
|
||||
if (!_list_)
|
||||
return ((void *)0);
|
||||
_list_->buffer = calloc(capacity, sizeof(size_t));
|
||||
if (!_list_->buffer)
|
||||
{
|
||||
free(_list_);
|
||||
return ((void *)0);
|
||||
}
|
||||
_list_->capacity = capacity;
|
||||
_list_->count = 0;
|
||||
_list_->cmp = compare;
|
||||
_list_->is_sorted = 0;
|
||||
_list_->it_start = sl_impl_it_start;
|
||||
_list_->it_end = sl_impl_it_end;
|
||||
return _list_;
|
||||
}
|
||||
void sl_clear(sortedlist *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
deallocator(_list_->buffer[i]);
|
||||
}
|
||||
memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity);
|
||||
_list_->count = 0;
|
||||
}
|
||||
void sl_free(sortedlist *_list_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
deallocator(_list_->buffer[i]);
|
||||
}
|
||||
free(_list_->buffer);
|
||||
free(_list_);
|
||||
}
|
||||
_Bool sl_insert(sortedlist *_list_, size_t element)
|
||||
{
|
||||
if (sl_full(_list_))
|
||||
{
|
||||
if (!sl_resize(_list_, sl_capacity(_list_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_list_->buffer[_list_->count++] = element;
|
||||
_list_->is_sorted = 0;
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_remove(sortedlist *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count)
|
||||
return 0;
|
||||
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t));
|
||||
_list_->buffer[--_list_->count] = (size_t){0};
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_min(sortedlist *_list_, size_t *result)
|
||||
{
|
||||
if (sl_empty(_list_))
|
||||
return 0;
|
||||
sl_sort(_list_);
|
||||
*result = _list_->buffer[0];
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_max(sortedlist *_list_, size_t *result)
|
||||
{
|
||||
if (sl_empty(_list_))
|
||||
return 0;
|
||||
sl_sort(_list_);
|
||||
*result = _list_->buffer[_list_->count - 1];
|
||||
return 1;
|
||||
}
|
||||
size_t sl_get(sortedlist *_list_, size_t index)
|
||||
{
|
||||
if (index >= _list_->count)
|
||||
return (size_t){0};
|
||||
sl_sort(_list_);
|
||||
return _list_->buffer[index];
|
||||
}
|
||||
size_t sl_indexof(sortedlist *_list_, size_t element, _Bool from_start)
|
||||
{
|
||||
sl_sort(_list_);
|
||||
if (from_start)
|
||||
{
|
||||
return sl_impl_binary_search_first(_list_, element);
|
||||
}
|
||||
return sl_impl_binary_search_last(_list_, element);
|
||||
}
|
||||
_Bool sl_contains(sortedlist *_list_, size_t element)
|
||||
{
|
||||
if (sl_empty(_list_))
|
||||
return 0;
|
||||
sl_sort(_list_);
|
||||
return sl_impl_binary_search_first(_list_, element) < sl_count(_list_);
|
||||
}
|
||||
_Bool sl_empty(sortedlist *_list_) { return _list_->count == 0; }
|
||||
_Bool sl_full(sortedlist *_list_) { return _list_->count >= _list_->capacity; }
|
||||
size_t sl_count(sortedlist *_list_) { return _list_->count; }
|
||||
size_t sl_capacity(sortedlist *_list_) { return _list_->capacity; }
|
||||
_Bool sl_resize(sortedlist *_list_, size_t capacity)
|
||||
{
|
||||
if (sl_capacity(_list_) == capacity)
|
||||
return 1;
|
||||
if (capacity < sl_count(_list_))
|
||||
return 0;
|
||||
size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
_list_->buffer = new_buffer;
|
||||
_list_->capacity = capacity;
|
||||
return 1;
|
||||
}
|
||||
void sl_sort(sortedlist *_list_)
|
||||
{
|
||||
if (!_list_->is_sorted && _list_->count > 1)
|
||||
{
|
||||
sl_impl_sort_quicksort(_list_->buffer, _list_->cmp, 0, _list_->count - 1);
|
||||
_list_->is_sorted = 1;
|
||||
}
|
||||
}
|
||||
sortedlist *sl_copy_of(sortedlist *_list_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
sortedlist *result = sl_new(_list_->capacity, _list_->cmp);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _list_->count; i++)
|
||||
result->buffer[i] = copy_func(_list_->buffer[i]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count);
|
||||
result->count = _list_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_)
|
||||
{
|
||||
if (sl_count(_list1_) != sl_count(_list2_))
|
||||
return 0;
|
||||
for (size_t i = 0; i < sl_count(_list1_); i++)
|
||||
{
|
||||
if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cmc_string sl_to_string(sortedlist *_list_)
|
||||
{
|
||||
cmc_string str;
|
||||
sortedlist *l_ = _list_;
|
||||
const char *name = "sortedlist";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, name, l_, l_->buffer, l_->capacity, l_->count, l_->is_sorted ? "true" : "false", l_->cmp);
|
||||
return str;
|
||||
}
|
||||
sortedlist_iter *sl_iter_new(sortedlist *target)
|
||||
{
|
||||
sortedlist_iter *iter = malloc(sizeof(sortedlist_iter));
|
||||
if (!iter)
|
||||
return ((void *)0);
|
||||
sl_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void sl_iter_free(sortedlist_iter *iter) { free(iter); }
|
||||
void sl_iter_init(sortedlist_iter *iter, sortedlist *target)
|
||||
{
|
||||
sl_sort(target);
|
||||
iter->target = target;
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = sl_empty(target);
|
||||
}
|
||||
_Bool sl_iter_start(sortedlist_iter *iter) { return sl_empty(iter->target) || iter->start; }
|
||||
_Bool sl_iter_end(sortedlist_iter *iter) { return sl_empty(iter->target) || iter->end; }
|
||||
void sl_iter_to_start(sortedlist_iter *iter)
|
||||
{
|
||||
if (!sl_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = 1;
|
||||
iter->end = sl_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void sl_iter_to_end(sortedlist_iter *iter)
|
||||
{
|
||||
if (!sl_empty(iter->target))
|
||||
{
|
||||
iter->start = sl_empty(iter->target);
|
||||
iter->cursor = sl_empty(iter->target) ? 0 : iter->target->count - 1;
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
_Bool sl_iter_next(sortedlist_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == sl_count(iter->target))
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = sl_empty(iter->target);
|
||||
iter->cursor++;
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_iter_prev(sortedlist_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = sl_empty(iter->target);
|
||||
iter->cursor--;
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_iter_advance(sortedlist_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == iter->target->count)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor + steps >= sl_count(iter->target))
|
||||
return 0;
|
||||
iter->start = sl_empty(iter->target);
|
||||
iter->cursor += steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_iter_rewind(sortedlist_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return 0;
|
||||
iter->end = sl_empty(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool sl_iter_go_to(sortedlist_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= sl_count(iter->target))
|
||||
return 0;
|
||||
if (iter->cursor > index)
|
||||
return sl_iter_rewind(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return sl_iter_advance(iter, index - iter->cursor);
|
||||
return 1;
|
||||
}
|
||||
size_t sl_iter_value(sortedlist_iter *iter)
|
||||
{
|
||||
if (sl_empty(iter->target))
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t sl_iter_index(sortedlist_iter *iter) { return iter->cursor; }
|
||||
static size_t sl_impl_binary_search_first(sortedlist *_list_, size_t value)
|
||||
{
|
||||
if (sl_empty(_list_))
|
||||
return 1;
|
||||
size_t L = 0;
|
||||
size_t R = sl_count(_list_);
|
||||
while (L < R)
|
||||
{
|
||||
size_t M = L + (R - L) / 2;
|
||||
if (_list_->cmp(_list_->buffer[M], value) < 0)
|
||||
L = M + 1;
|
||||
else
|
||||
R = M;
|
||||
}
|
||||
if (_list_->cmp(_list_->buffer[L], value) == 0)
|
||||
return L;
|
||||
return sl_count(_list_);
|
||||
}
|
||||
static size_t sl_impl_binary_search_last(sortedlist *_list_, size_t value)
|
||||
{
|
||||
if (sl_empty(_list_))
|
||||
return 1;
|
||||
size_t L = 0;
|
||||
size_t R = sl_count(_list_);
|
||||
while (L < R)
|
||||
{
|
||||
size_t M = L + (R - L) / 2;
|
||||
if (_list_->cmp(_list_->buffer[M], value) > 0)
|
||||
R = M;
|
||||
else
|
||||
L = M + 1;
|
||||
}
|
||||
if (_list_->cmp(_list_->buffer[L - 1], value) == 0)
|
||||
return L - 1;
|
||||
return sl_count(_list_);
|
||||
}
|
||||
void sl_impl_sort_quicksort(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high)
|
||||
{
|
||||
while (low < high)
|
||||
{
|
||||
if (high - low < 10)
|
||||
{
|
||||
sl_impl_sort_insertion(array, cmp, low, high);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t pivot = array[high];
|
||||
size_t pindex = low;
|
||||
for (size_t i = low; i < high; i++)
|
||||
{
|
||||
if (cmp(array[i], pivot) <= 0)
|
||||
{
|
||||
size_t _tmp_ = array[i];
|
||||
array[i] = array[pindex];
|
||||
array[pindex] = _tmp_;
|
||||
pindex++;
|
||||
}
|
||||
}
|
||||
size_t _tmp_ = array[pindex];
|
||||
array[pindex] = array[high];
|
||||
array[high] = _tmp_;
|
||||
if (pindex - low < high - pindex)
|
||||
{
|
||||
sl_impl_sort_quicksort(array, cmp, low, pindex - 1);
|
||||
low = pindex + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl_impl_sort_quicksort(array, cmp, pindex + 1, high);
|
||||
high = pindex - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void sl_impl_sort_insertion(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high)
|
||||
{
|
||||
for (size_t i = low + 1; i <= high; i++)
|
||||
{
|
||||
size_t _tmp_ = array[i];
|
||||
size_t j = i;
|
||||
while (j > low && cmp(array[j - 1], _tmp_) > 0)
|
||||
{
|
||||
array[j] = array[j - 1];
|
||||
j--;
|
||||
}
|
||||
array[j] = _tmp_;
|
||||
}
|
||||
}
|
||||
static sortedlist_iter sl_impl_it_start(sortedlist *_list_)
|
||||
{
|
||||
sortedlist_iter iter;
|
||||
sl_iter_init(&iter, _list_);
|
||||
sl_iter_to_start(&iter);
|
||||
return iter;
|
||||
}
|
||||
static sortedlist_iter sl_impl_it_end(sortedlist *_list_)
|
||||
{
|
||||
sortedlist_iter iter;
|
||||
sl_iter_init(&iter, _list_);
|
||||
sl_iter_to_end(&iter);
|
||||
return iter;
|
||||
}
|
||||
+172
-98
@@ -1,6 +1,6 @@
|
||||
#include "cmc/stack.h"
|
||||
#include <cmc/stack.h>
|
||||
|
||||
//STACK_GENERATE(s, stack, , size_t)
|
||||
//CMC_GENERATE_STACK(s, stack, size_t)
|
||||
|
||||
typedef struct stack_s
|
||||
{
|
||||
@@ -14,55 +14,53 @@ typedef struct stack_iter_s
|
||||
{
|
||||
struct stack_s *target;
|
||||
size_t cursor;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} stack_iter, *stack_iter_ptr;
|
||||
stack *s_new(size_t capacity);
|
||||
void s_clear(stack *_stack_);
|
||||
void s_free(stack *_stack_);
|
||||
bool s_push(stack *_stack_, size_t element);
|
||||
bool s_pop(stack *_stack_);
|
||||
bool s_push_if(stack *_stack_, size_t element, bool condition);
|
||||
bool s_pop_if(stack *_stack_, bool condition);
|
||||
void s_clear(stack *_stack_, void (*deallocator)(size_t));
|
||||
void s_free(stack *_stack_, void (*deallocator)(size_t));
|
||||
_Bool s_push(stack *_stack_, size_t element);
|
||||
_Bool s_pop(stack *_stack_);
|
||||
size_t s_top(stack *_stack_);
|
||||
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t));
|
||||
bool s_empty(stack *_stack_);
|
||||
bool s_full(stack *_stack_);
|
||||
_Bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t));
|
||||
_Bool s_empty(stack *_stack_);
|
||||
_Bool s_full(stack *_stack_);
|
||||
size_t s_count(stack *_stack_);
|
||||
size_t s_capacity(stack *_stack_);
|
||||
_Bool s_resize(stack *_stack_, size_t capacity);
|
||||
stack *s_copy_of(stack *_stack_, size_t (*copy_func)(size_t));
|
||||
_Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_t));
|
||||
cmc_string s_to_string(stack *_stack_);
|
||||
stack_iter *s_iter_new(stack *target);
|
||||
void s_iter_free(stack_iter *iter);
|
||||
void s_iter_init(stack_iter *iter, stack *target);
|
||||
bool s_iter_start(stack_iter *iter);
|
||||
bool s_iter_end(stack_iter *iter);
|
||||
_Bool s_iter_start(stack_iter *iter);
|
||||
_Bool s_iter_end(stack_iter *iter);
|
||||
void s_iter_to_start(stack_iter *iter);
|
||||
void s_iter_to_end(stack_iter *iter);
|
||||
bool s_iter_next(stack_iter *iter);
|
||||
bool s_iter_prev(stack_iter *iter);
|
||||
_Bool s_iter_next(stack_iter *iter);
|
||||
_Bool s_iter_prev(stack_iter *iter);
|
||||
_Bool s_iter_advance(stack_iter *iter, size_t steps);
|
||||
_Bool s_iter_rewind(stack_iter *iter, size_t steps);
|
||||
_Bool s_iter_go_to(stack_iter *iter, size_t index);
|
||||
size_t s_iter_value(stack_iter *iter);
|
||||
size_t *s_iter_rvalue(stack_iter *iter);
|
||||
size_t s_iter_index(stack_iter *iter);
|
||||
static inline size_t s_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static bool s_impl_grow(stack *_stack_);
|
||||
static stack_iter s_impl_it_start(stack *_stack_);
|
||||
static stack_iter s_impl_it_end(stack *_stack_);
|
||||
stack *s_new(size_t capacity)
|
||||
{
|
||||
if (capacity < 1)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
stack *_stack_ = malloc(sizeof(stack));
|
||||
if (!_stack_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_stack_->buffer = malloc(sizeof(size_t) * capacity);
|
||||
if (!_stack_->buffer)
|
||||
{
|
||||
free(_stack_);
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
memset(_stack_->buffer, 0, sizeof(size_t) * capacity);
|
||||
_stack_->capacity = capacity;
|
||||
@@ -71,69 +69,114 @@ stack *s_new(size_t capacity)
|
||||
_stack_->it_end = s_impl_it_end;
|
||||
return _stack_;
|
||||
}
|
||||
void s_clear(stack *_stack_)
|
||||
void s_clear(stack *_stack_, void (*deallocator)(size_t))
|
||||
{
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _stack_->count; i++)
|
||||
deallocator(_stack_->buffer[i]);
|
||||
}
|
||||
memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity);
|
||||
_stack_->count = 0;
|
||||
}
|
||||
void s_free(stack *_stack_)
|
||||
void s_free(stack *_stack_, void (*deallocator)(size_t))
|
||||
{
|
||||
free(_stack_->buffer);
|
||||
if (deallocator)
|
||||
{
|
||||
for (size_t i = 0; i < _stack_->count; i++)
|
||||
deallocator(_stack_->buffer[i]);
|
||||
}
|
||||
free(_stack_);
|
||||
}
|
||||
bool s_push(stack *_stack_, size_t element)
|
||||
_Bool s_push(stack *_stack_, size_t element)
|
||||
{
|
||||
if (s_full(_stack_))
|
||||
{
|
||||
if (!s_impl_grow(_stack_))
|
||||
return false;
|
||||
if (!s_resize(_stack_, s_capacity(_stack_) * 2))
|
||||
return 0;
|
||||
}
|
||||
_stack_->buffer[_stack_->count++] = element;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool s_pop(stack *_stack_)
|
||||
_Bool s_pop(stack *_stack_)
|
||||
{
|
||||
if (s_empty(_stack_))
|
||||
return false;
|
||||
_stack_->buffer[--_stack_->count] = s_impl_default_value();
|
||||
return true;
|
||||
}
|
||||
bool s_push_if(stack *_stack_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return s_push(_stack_, element);
|
||||
return false;
|
||||
}
|
||||
bool s_pop_if(stack *_stack_, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return s_pop(_stack_);
|
||||
return false;
|
||||
return 0;
|
||||
_stack_->buffer[--_stack_->count] = (size_t){0};
|
||||
return 1;
|
||||
}
|
||||
size_t s_top(stack *_stack_)
|
||||
{
|
||||
if (s_empty(_stack_))
|
||||
return s_impl_default_value();
|
||||
return (size_t){0};
|
||||
return _stack_->buffer[_stack_->count - 1];
|
||||
}
|
||||
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t))
|
||||
_Bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
for (size_t i = 0; i < _stack_->count; i++)
|
||||
{
|
||||
if (comparator(_stack_->buffer[i], element) == 0)
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool s_empty(stack *_stack_) { return _stack_->count == 0; }
|
||||
bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; }
|
||||
_Bool s_empty(stack *_stack_) { return _stack_->count == 0; }
|
||||
_Bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; }
|
||||
size_t s_count(stack *_stack_) { return _stack_->count; }
|
||||
size_t s_capacity(stack *_stack_) { return _stack_->capacity; }
|
||||
_Bool s_resize(stack *_stack_, size_t capacity)
|
||||
{
|
||||
if (s_capacity(_stack_) == capacity)
|
||||
return 1;
|
||||
if (capacity < s_count(_stack_))
|
||||
return 0;
|
||||
size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * capacity);
|
||||
if (!new_buffer)
|
||||
return 0;
|
||||
_stack_->buffer = new_buffer;
|
||||
_stack_->capacity = capacity;
|
||||
return 1;
|
||||
}
|
||||
stack *s_copy_of(stack *_stack_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
stack *result = s_new(_stack_->capacity);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
if (copy_func)
|
||||
{
|
||||
for (size_t i = 0; i < _stack_->count; i++)
|
||||
result->buffer[i] = copy_func(_stack_->buffer[i]);
|
||||
}
|
||||
else
|
||||
memcpy(result->buffer, _stack_->buffer, sizeof(size_t) * _stack_->count);
|
||||
result->count = _stack_->count;
|
||||
return result;
|
||||
}
|
||||
_Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_t))
|
||||
{
|
||||
if (s_count(_stack1_) != s_count(_stack2_))
|
||||
return 0;
|
||||
for (size_t i = 0; i < s_count(_stack1_); i++)
|
||||
{
|
||||
if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string s_to_string(stack *_stack_)
|
||||
{
|
||||
cmc_string str;
|
||||
stack *s_ = _stack_;
|
||||
const char *name = "stack";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, name, s_, s_->buffer, s_->capacity, s_->count);
|
||||
return str;
|
||||
}
|
||||
stack_iter *s_iter_new(stack *target)
|
||||
{
|
||||
stack_iter *iter = malloc(sizeof(stack_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
s_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
@@ -141,65 +184,106 @@ void s_iter_free(stack_iter *iter) { free(iter); }
|
||||
void s_iter_init(stack_iter *iter, stack *target)
|
||||
{
|
||||
iter->target = target;
|
||||
if (s_empty(target))
|
||||
iter->cursor = 0;
|
||||
else
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = true;
|
||||
iter->cursor = s_empty(target) ? 0 : iter->target->count - 1;
|
||||
iter->start = 1;
|
||||
iter->end = s_empty(target);
|
||||
}
|
||||
bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; }
|
||||
bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; }
|
||||
_Bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; }
|
||||
_Bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; }
|
||||
void s_iter_to_start(stack_iter *iter)
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = true;
|
||||
iter->end = s_empty(iter->target);
|
||||
if (!s_empty(iter->target))
|
||||
{
|
||||
iter->cursor = iter->target->count - 1;
|
||||
iter->start = 1;
|
||||
iter->end = s_empty(iter->target);
|
||||
}
|
||||
}
|
||||
void s_iter_to_end(stack_iter *iter)
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = s_empty(iter->target);
|
||||
iter->end = true;
|
||||
if (!s_empty(iter->target))
|
||||
{
|
||||
iter->cursor = 0;
|
||||
iter->start = s_empty(iter->target);
|
||||
iter->end = 1;
|
||||
}
|
||||
}
|
||||
bool s_iter_next(stack_iter *iter)
|
||||
_Bool s_iter_next(stack_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = s_empty(iter->target);
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->end = true;
|
||||
return false;
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
iter->cursor--;
|
||||
return true;
|
||||
iter->start = s_empty(iter->target);
|
||||
iter->cursor--;
|
||||
return 1;
|
||||
}
|
||||
bool s_iter_prev(stack_iter *iter)
|
||||
_Bool s_iter_prev(stack_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = s_empty(iter->target);
|
||||
if (iter->cursor == iter->target->count - 1)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == s_count(iter->target))
|
||||
{
|
||||
iter->start = true;
|
||||
return false;
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
iter->cursor++;
|
||||
return true;
|
||||
iter->end = s_empty(iter->target);
|
||||
iter->cursor++;
|
||||
return 1;
|
||||
}
|
||||
_Bool s_iter_advance(stack_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor == 0)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor < steps)
|
||||
return 0;
|
||||
iter->start = s_empty(iter->target);
|
||||
iter->cursor -= steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool s_iter_rewind(stack_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor + 1 == s_count(iter->target))
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->cursor + steps >= s_count(iter->target))
|
||||
return 0;
|
||||
iter->end = s_empty(iter->target);
|
||||
iter->cursor += steps;
|
||||
return 1;
|
||||
}
|
||||
_Bool s_iter_go_to(stack_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= s_count(iter->target))
|
||||
return 0;
|
||||
if (iter->cursor > index)
|
||||
return s_iter_rewind(iter, iter->cursor - index);
|
||||
else if (iter->cursor < index)
|
||||
return s_iter_advance(iter, index - iter->cursor);
|
||||
return 1;
|
||||
}
|
||||
size_t s_iter_value(stack_iter *iter)
|
||||
{
|
||||
if (s_empty(iter->target))
|
||||
return s_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->target->buffer[iter->cursor];
|
||||
}
|
||||
size_t *s_iter_rvalue(stack_iter *iter)
|
||||
{
|
||||
if (s_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->target->buffer[iter->cursor]);
|
||||
}
|
||||
size_t s_iter_index(stack_iter *iter)
|
||||
@@ -208,16 +292,6 @@ size_t s_iter_index(stack_iter *iter)
|
||||
return 0;
|
||||
return iter->target->count - 1 - iter->cursor;
|
||||
}
|
||||
static bool s_impl_grow(stack *_stack_)
|
||||
{
|
||||
size_t new_capacity = _stack_->capacity * 2;
|
||||
size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
_stack_->buffer = new_buffer;
|
||||
_stack_->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
static stack_iter s_impl_it_start(stack *_stack_)
|
||||
{
|
||||
stack_iter iter;
|
||||
|
||||
+263
-167
@@ -1,6 +1,6 @@
|
||||
#include "cmc/treemap.h"
|
||||
#include <cmc/treemap.h>
|
||||
|
||||
//TREEMAP_GENERATE(tm, treemap, , size_t, size_t)
|
||||
//CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t)
|
||||
|
||||
typedef struct treemap_s
|
||||
{
|
||||
@@ -26,48 +26,41 @@ typedef struct treemap_iter_s
|
||||
struct treemap_node_s *first;
|
||||
struct treemap_node_s *last;
|
||||
size_t index;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} treemap_iter, *treemap_iter_ptr;
|
||||
treemap *tm_new(int (*compare)(size_t, size_t));
|
||||
void tm_clear(treemap *_map_);
|
||||
void tm_free(treemap *_map_);
|
||||
bool tm_insert(treemap *_map_, size_t key, size_t value);
|
||||
bool tm_remove(treemap *_map_, size_t key, size_t *value);
|
||||
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition);
|
||||
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition);
|
||||
bool tm_max(treemap *_map_, size_t *key, size_t *value);
|
||||
bool tm_min(treemap *_map_, size_t *key, size_t *value);
|
||||
void tm_clear(treemap *_map_, void (*deallocator)(size_t, size_t));
|
||||
void tm_free(treemap *_map_, void (*deallocator)(size_t, size_t));
|
||||
_Bool tm_insert(treemap *_map_, size_t key, size_t value);
|
||||
_Bool tm_update(treemap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
_Bool tm_remove(treemap *_map_, size_t key, size_t *out_value);
|
||||
_Bool tm_max(treemap *_map_, size_t *key, size_t *value);
|
||||
_Bool tm_min(treemap *_map_, size_t *key, size_t *value);
|
||||
size_t tm_get(treemap *_map_, size_t key);
|
||||
size_t *tm_get_ref(treemap *_map_, size_t key);
|
||||
bool tm_contains(treemap *_map_, size_t key);
|
||||
bool tm_empty(treemap *_map_);
|
||||
_Bool tm_contains(treemap *_map_, size_t key);
|
||||
_Bool tm_empty(treemap *_map_);
|
||||
size_t tm_count(treemap *_map_);
|
||||
treemap *tm_copy_of(treemap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t));
|
||||
_Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t, size_t));
|
||||
cmc_string tm_to_string(treemap *_map_);
|
||||
treemap_iter *tm_iter_new(treemap *target);
|
||||
void tm_iter_free(treemap_iter *iter);
|
||||
void tm_iter_init(treemap_iter *iter, treemap *target);
|
||||
bool tm_iter_start(treemap_iter *iter);
|
||||
bool tm_iter_end(treemap_iter *iter);
|
||||
_Bool tm_iter_start(treemap_iter *iter);
|
||||
_Bool tm_iter_end(treemap_iter *iter);
|
||||
void tm_iter_to_start(treemap_iter *iter);
|
||||
void tm_iter_to_end(treemap_iter *iter);
|
||||
bool tm_iter_next(treemap_iter *iter);
|
||||
bool tm_iter_prev(treemap_iter *iter);
|
||||
_Bool tm_iter_next(treemap_iter *iter);
|
||||
_Bool tm_iter_prev(treemap_iter *iter);
|
||||
_Bool tm_iter_advance(treemap_iter *iter, size_t steps);
|
||||
_Bool tm_iter_rewind(treemap_iter *iter, size_t steps);
|
||||
_Bool tm_iter_go_to(treemap_iter *iter, size_t index);
|
||||
size_t tm_iter_key(treemap_iter *iter);
|
||||
size_t tm_iter_value(treemap_iter *iter);
|
||||
size_t *tm_iter_rvalue(treemap_iter *iter);
|
||||
size_t tm_iter_index(treemap_iter *iter);
|
||||
static inline size_t tm_impl_default_key(void)
|
||||
{
|
||||
size_t _empty_key_;
|
||||
memset(&_empty_key_, 0, sizeof(size_t));
|
||||
return _empty_key_;
|
||||
}
|
||||
static inline size_t tm_impl_default_value(void)
|
||||
{
|
||||
size_t _empty_value_;
|
||||
memset(&_empty_value_, 0, sizeof(size_t));
|
||||
return _empty_value_;
|
||||
}
|
||||
static treemap_node *tm_impl_new_node(size_t key, size_t value);
|
||||
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key);
|
||||
static unsigned char tm_impl_h(treemap_node *node);
|
||||
@@ -81,49 +74,53 @@ treemap *tm_new(int (*compare)(size_t, size_t))
|
||||
{
|
||||
treemap *_map_ = malloc(sizeof(treemap));
|
||||
if (!_map_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_map_->count = 0;
|
||||
_map_->root = NULL;
|
||||
_map_->root = ((void *)0);
|
||||
_map_->cmp = compare;
|
||||
_map_->it_start = tm_impl_it_start;
|
||||
_map_->it_end = tm_impl_it_end;
|
||||
return _map_;
|
||||
}
|
||||
void tm_clear(treemap *_map_)
|
||||
void tm_clear(treemap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
treemap_node *scan = _map_->root;
|
||||
treemap_node *up = NULL;
|
||||
while (scan != NULL)
|
||||
treemap_node *up = ((void *)0);
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (scan->left != NULL)
|
||||
if (scan->left != ((void *)0))
|
||||
{
|
||||
treemap_node *left = scan->left;
|
||||
scan->left = up;
|
||||
up = scan;
|
||||
scan = left;
|
||||
}
|
||||
else if (scan->right != NULL)
|
||||
else if (scan->right != ((void *)0))
|
||||
{
|
||||
treemap_node *right = scan->right;
|
||||
scan->left = up;
|
||||
scan->right = NULL;
|
||||
scan->right = ((void *)0);
|
||||
up = scan;
|
||||
scan = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (up == NULL)
|
||||
if (up == ((void *)0))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(scan->key, scan->value);
|
||||
free(scan);
|
||||
scan = NULL;
|
||||
scan = ((void *)0);
|
||||
}
|
||||
while (up != NULL)
|
||||
while (up != ((void *)0))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(scan->key, scan->value);
|
||||
free(scan);
|
||||
if (up->right != NULL)
|
||||
if (up->right != ((void *)0))
|
||||
{
|
||||
scan = up->right;
|
||||
up->right = NULL;
|
||||
up->right = ((void *)0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -135,26 +132,26 @@ void tm_clear(treemap *_map_)
|
||||
}
|
||||
}
|
||||
_map_->count = 0;
|
||||
_map_->root = NULL;
|
||||
_map_->root = ((void *)0);
|
||||
}
|
||||
void tm_free(treemap *_map_)
|
||||
void tm_free(treemap *_map_, void (*deallocator)(size_t, size_t))
|
||||
{
|
||||
tm_clear(_map_);
|
||||
tm_clear(_map_, deallocator);
|
||||
free(_map_);
|
||||
}
|
||||
bool tm_insert(treemap *_map_, size_t key, size_t value)
|
||||
_Bool tm_insert(treemap *_map_, size_t key, size_t value)
|
||||
{
|
||||
if (tm_empty(_map_))
|
||||
{
|
||||
_map_->root = tm_impl_new_node(key, value);
|
||||
if (!_map_->root)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
treemap_node *scan = _map_->root;
|
||||
treemap_node *parent = scan;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
parent = scan;
|
||||
if (_map_->cmp(scan->key, key) > 0)
|
||||
@@ -162,14 +159,14 @@ bool tm_insert(treemap *_map_, size_t key, size_t value)
|
||||
else if (_map_->cmp(scan->key, key) < 0)
|
||||
scan = scan->right;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
treemap_node *node;
|
||||
if (_map_->cmp(parent->key, key) > 0)
|
||||
{
|
||||
parent->left = tm_impl_new_node(key, value);
|
||||
if (!parent->left)
|
||||
return false;
|
||||
return 0;
|
||||
parent->left->parent = parent;
|
||||
node = parent->left;
|
||||
}
|
||||
@@ -177,43 +174,54 @@ bool tm_insert(treemap *_map_, size_t key, size_t value)
|
||||
{
|
||||
parent->right = tm_impl_new_node(key, value);
|
||||
if (!parent->right)
|
||||
return false;
|
||||
return 0;
|
||||
parent->right->parent = parent;
|
||||
node = parent->right;
|
||||
}
|
||||
tm_impl_rebalance(_map_, node);
|
||||
}
|
||||
_map_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool tm_remove(treemap *_map_, size_t key, size_t *value)
|
||||
_Bool tm_update(treemap *_map_, size_t key, size_t new_value, size_t *old_value)
|
||||
{
|
||||
treemap_node *node = tm_impl_get_node(_map_, key);
|
||||
if (!node)
|
||||
return false;
|
||||
*value = node->value;
|
||||
treemap_node *temp = NULL, *unbalanced = NULL;
|
||||
bool is_root = node->parent == NULL;
|
||||
if (node->left == NULL && node->right == NULL)
|
||||
return 0;
|
||||
if (old_value)
|
||||
*old_value = node->value;
|
||||
node->value = new_value;
|
||||
return 1;
|
||||
}
|
||||
_Bool tm_remove(treemap *_map_, size_t key, size_t *out_value)
|
||||
{
|
||||
treemap_node *node = tm_impl_get_node(_map_, key);
|
||||
if (!node)
|
||||
return 0;
|
||||
if (out_value)
|
||||
*out_value = node->value;
|
||||
treemap_node *temp = ((void *)0), *unbalanced = ((void *)0);
|
||||
_Bool is_root = node->parent == ((void *)0);
|
||||
if (node->left == ((void *)0) && node->right == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
_map_->root = NULL;
|
||||
_map_->root = ((void *)0);
|
||||
else
|
||||
{
|
||||
unbalanced = node->parent;
|
||||
if (node->parent->right == node)
|
||||
node->parent->right = NULL;
|
||||
node->parent->right = ((void *)0);
|
||||
else
|
||||
node->parent->left = NULL;
|
||||
node->parent->left = ((void *)0);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
else if (node->left == NULL)
|
||||
else if (node->left == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
{
|
||||
_map_->root = node->right;
|
||||
_map_->root->parent = NULL;
|
||||
_map_->root->parent = ((void *)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -226,12 +234,12 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value)
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
else if (node->right == NULL)
|
||||
else if (node->right == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
{
|
||||
_map_->root = node->left;
|
||||
_map_->root->parent = NULL;
|
||||
_map_->root->parent = ((void *)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -247,19 +255,19 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value)
|
||||
else
|
||||
{
|
||||
temp = node->right;
|
||||
while (temp->left != NULL)
|
||||
while (temp->left != ((void *)0))
|
||||
temp = temp->left;
|
||||
size_t temp_key = temp->key;
|
||||
size_t temp_val = temp->value;
|
||||
unbalanced = temp->parent;
|
||||
if (temp->left == NULL && temp->right == NULL)
|
||||
if (temp->left == ((void *)0) && temp->right == ((void *)0))
|
||||
{
|
||||
if (temp->parent->right == temp)
|
||||
temp->parent->right = NULL;
|
||||
temp->parent->right = ((void *)0);
|
||||
else
|
||||
temp->parent->left = NULL;
|
||||
temp->parent->left = ((void *)0);
|
||||
}
|
||||
else if (temp->left == NULL)
|
||||
else if (temp->left == ((void *)0))
|
||||
{
|
||||
temp->right->parent = temp->parent;
|
||||
if (temp->parent->right == temp)
|
||||
@@ -267,7 +275,7 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value)
|
||||
else
|
||||
temp->parent->left = temp->right;
|
||||
}
|
||||
else if (temp->right == NULL)
|
||||
else if (temp->right == ((void *)0))
|
||||
{
|
||||
temp->left->parent = temp->parent;
|
||||
if (temp->parent->right == temp)
|
||||
@@ -279,190 +287,278 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value)
|
||||
node->key = temp_key;
|
||||
node->value = temp_val;
|
||||
}
|
||||
if (unbalanced != NULL)
|
||||
if (unbalanced != ((void *)0))
|
||||
tm_impl_rebalance(_map_, unbalanced);
|
||||
_map_->count--;
|
||||
if (_map_->count == 0)
|
||||
_map_->root = NULL;
|
||||
return true;
|
||||
_map_->root = ((void *)0);
|
||||
return 1;
|
||||
}
|
||||
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return tm_insert(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return tm_remove(_map_, key, value);
|
||||
return false;
|
||||
}
|
||||
bool tm_max(treemap *_map_, size_t *key, size_t *value)
|
||||
_Bool tm_max(treemap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (tm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
treemap_node *scan = _map_->root;
|
||||
while (scan->right != NULL)
|
||||
while (scan->right != ((void *)0))
|
||||
scan = scan->right;
|
||||
*key = scan->key;
|
||||
*value = scan->value;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool tm_min(treemap *_map_, size_t *key, size_t *value)
|
||||
_Bool tm_min(treemap *_map_, size_t *key, size_t *value)
|
||||
{
|
||||
if (tm_empty(_map_))
|
||||
return false;
|
||||
return 0;
|
||||
treemap_node *scan = _map_->root;
|
||||
while (scan->left != NULL)
|
||||
while (scan->left != ((void *)0))
|
||||
scan = scan->left;
|
||||
*key = scan->key;
|
||||
*value = scan->value;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
size_t tm_get(treemap *_map_, size_t key)
|
||||
{
|
||||
treemap_node *node = tm_impl_get_node(_map_, key);
|
||||
if (!node)
|
||||
return tm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return node->value;
|
||||
}
|
||||
size_t *tm_get_ref(treemap *_map_, size_t key)
|
||||
{
|
||||
treemap_node *node = tm_impl_get_node(_map_, key);
|
||||
if (!node)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(node->value);
|
||||
}
|
||||
bool tm_contains(treemap *_map_, size_t key)
|
||||
_Bool tm_contains(treemap *_map_, size_t key)
|
||||
{
|
||||
treemap_node *scan = _map_->root;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(scan->key, key) > 0)
|
||||
scan = scan->left;
|
||||
else if (_map_->cmp(scan->key, key) < 0)
|
||||
scan = scan->right;
|
||||
else
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool tm_empty(treemap *_map_) { return _map_->count == 0; }
|
||||
_Bool tm_empty(treemap *_map_) { return _map_->count == 0; }
|
||||
size_t tm_count(treemap *_map_) { return _map_->count; }
|
||||
treemap *tm_copy_of(treemap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t))
|
||||
{
|
||||
treemap *result = tm_new(_map_->cmp);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
treemap_iter iter;
|
||||
tm_iter_init(&iter, _map_);
|
||||
if (!tm_empty(_map_))
|
||||
{
|
||||
for (tm_iter_to_start(&iter); !tm_iter_end(&iter); tm_iter_next(&iter))
|
||||
{
|
||||
size_t key = tm_iter_key(&iter);
|
||||
size_t value = tm_iter_value(&iter);
|
||||
if (key_copy_func)
|
||||
key = key_copy_func(key);
|
||||
if (value_copy_func)
|
||||
value = value_copy_func(value);
|
||||
tm_insert(result, key, value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
_Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t, size_t))
|
||||
{
|
||||
if (tm_count(_map1_) != tm_count(_map2_))
|
||||
return 0;
|
||||
treemap_iter iter;
|
||||
tm_iter_init(&iter, _map1_);
|
||||
for (tm_iter_to_start(&iter); !tm_iter_end(&iter); tm_iter_next(&iter))
|
||||
{
|
||||
treemap_node *node = tm_impl_get_node(_map2_, tm_iter_key(&iter));
|
||||
if (node == ((void *)0))
|
||||
return 0;
|
||||
if (value_comparator)
|
||||
{
|
||||
if (value_comparator(node->value, tm_iter_value(&iter)) != 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string tm_to_string(treemap *_map_)
|
||||
{
|
||||
cmc_string str;
|
||||
treemap *m_ = _map_;
|
||||
const char *name = "treemap";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, name, m_, m_->root, m_->count, m_->cmp);
|
||||
return str;
|
||||
}
|
||||
treemap_iter *tm_iter_new(treemap *target)
|
||||
{
|
||||
treemap_iter *iter = malloc(sizeof(treemap_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
tm_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void tm_iter_free(treemap_iter *iter) { free(iter); }
|
||||
void tm_iter_init(treemap_iter *iter, treemap *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(treemap_iter));
|
||||
iter->target = target;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = tm_empty(target);
|
||||
iter->cursor = target->root;
|
||||
while (iter->cursor->left != NULL)
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->first = iter->cursor;
|
||||
iter->last = target->root;
|
||||
while (iter->last->right != NULL)
|
||||
iter->last = iter->last->right;
|
||||
if (!tm_empty(target))
|
||||
{
|
||||
while (iter->cursor->left != ((void *)0))
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->first = iter->cursor;
|
||||
iter->last = target->root;
|
||||
while (iter->last->right != ((void *)0))
|
||||
iter->last = iter->last->right;
|
||||
}
|
||||
}
|
||||
bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; }
|
||||
bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; }
|
||||
_Bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; }
|
||||
_Bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; }
|
||||
void tm_iter_to_start(treemap_iter *iter)
|
||||
{
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = tm_empty(iter->target);
|
||||
iter->cursor = iter->first;
|
||||
if (!tm_empty(iter->target))
|
||||
{
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = tm_empty(iter->target);
|
||||
iter->cursor = iter->first;
|
||||
}
|
||||
}
|
||||
void tm_iter_to_end(treemap_iter *iter)
|
||||
{
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = tm_empty(iter->target);
|
||||
iter->end = true;
|
||||
iter->cursor = iter->last;
|
||||
if (!tm_empty(iter->target))
|
||||
{
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = tm_empty(iter->target);
|
||||
iter->end = 1;
|
||||
iter->cursor = iter->last;
|
||||
}
|
||||
}
|
||||
bool tm_iter_next(treemap_iter *iter)
|
||||
_Bool tm_iter_next(treemap_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
iter->start = false;
|
||||
if (iter->cursor->right != NULL)
|
||||
return 0;
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->start = tm_empty(iter->target);
|
||||
if (iter->cursor->right != ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->right;
|
||||
while (iter->cursor->left != NULL)
|
||||
while (iter->cursor->left != ((void *)0))
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->index++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = true;
|
||||
return true;
|
||||
}
|
||||
if (iter->cursor->parent->left == iter->cursor)
|
||||
{
|
||||
iter->cursor = iter->cursor->parent;
|
||||
iter->index++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
iter->cursor = iter->cursor->parent;
|
||||
}
|
||||
}
|
||||
bool tm_iter_prev(treemap_iter *iter)
|
||||
_Bool tm_iter_prev(treemap_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
iter->end = false;
|
||||
if (iter->cursor->left != NULL)
|
||||
return 0;
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
iter->end = tm_empty(iter->target);
|
||||
if (iter->cursor->left != ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->left;
|
||||
while (iter->cursor->right != NULL)
|
||||
while (iter->cursor->right != ((void *)0))
|
||||
iter->cursor = iter->cursor->right;
|
||||
iter->index--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = true;
|
||||
return true;
|
||||
}
|
||||
if (iter->cursor->parent->right == iter->cursor)
|
||||
{
|
||||
iter->cursor = iter->cursor->parent;
|
||||
iter->index--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
iter->cursor = iter->cursor->parent;
|
||||
}
|
||||
}
|
||||
_Bool tm_iter_advance(treemap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= tm_count(iter->target))
|
||||
return 0;
|
||||
iter->index += steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
tm_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool tm_iter_rewind(treemap_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
iter->index -= steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
tm_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool tm_iter_go_to(treemap_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= tm_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return tm_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return tm_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t tm_iter_key(treemap_iter *iter)
|
||||
{
|
||||
if (tm_empty(iter->target))
|
||||
return tm_impl_default_key();
|
||||
return (size_t){0};
|
||||
return iter->cursor->key;
|
||||
}
|
||||
size_t tm_iter_value(treemap_iter *iter)
|
||||
{
|
||||
if (tm_empty(iter->target))
|
||||
return tm_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->cursor->value;
|
||||
}
|
||||
size_t *tm_iter_rvalue(treemap_iter *iter)
|
||||
{
|
||||
if (tm_empty(iter->target))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
return &(iter->cursor->value);
|
||||
}
|
||||
size_t tm_iter_index(treemap_iter *iter) { return iter->index; }
|
||||
@@ -470,21 +566,21 @@ static treemap_node *tm_impl_new_node(size_t key, size_t value)
|
||||
{
|
||||
treemap_node *node = malloc(sizeof(treemap_node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
node->key = key;
|
||||
node->value = value;
|
||||
node->right = NULL;
|
||||
node->left = NULL;
|
||||
node->parent = NULL;
|
||||
node->right = ((void *)0);
|
||||
node->left = ((void *)0);
|
||||
node->parent = ((void *)0);
|
||||
node->height = 0;
|
||||
return node;
|
||||
}
|
||||
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key)
|
||||
{
|
||||
if (tm_empty(_map_))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treemap_node *scan = _map_->root;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (_map_->cmp(scan->key, key) > 0)
|
||||
scan = scan->left;
|
||||
@@ -493,17 +589,17 @@ static treemap_node *tm_impl_get_node(treemap *_map_, size_t key)
|
||||
else
|
||||
return scan;
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
static unsigned char tm_impl_h(treemap_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
if (node == ((void *)0))
|
||||
return 0;
|
||||
return node->height;
|
||||
}
|
||||
static unsigned char tm_impl_hupdate(treemap_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
if (node == ((void *)0))
|
||||
return 0;
|
||||
unsigned char h_l = tm_impl_h(node->left);
|
||||
unsigned char h_r = tm_impl_h(node->right);
|
||||
@@ -513,7 +609,7 @@ static void tm_impl_rotate_right(treemap_node **Z)
|
||||
{
|
||||
treemap_node *root = *Z;
|
||||
treemap_node *new_root = root->left;
|
||||
if (root->parent != NULL)
|
||||
if (root->parent != ((void *)0))
|
||||
{
|
||||
if (root->parent->left == root)
|
||||
root->parent->left = new_root;
|
||||
@@ -534,7 +630,7 @@ static void tm_impl_rotate_left(treemap_node **Z)
|
||||
{
|
||||
treemap_node *root = *Z;
|
||||
treemap_node *new_root = root->right;
|
||||
if (root->parent != NULL)
|
||||
if (root->parent != ((void *)0))
|
||||
{
|
||||
if (root->parent->right == root)
|
||||
root->parent->right = new_root;
|
||||
@@ -553,13 +649,13 @@ static void tm_impl_rotate_left(treemap_node **Z)
|
||||
}
|
||||
static void tm_impl_rebalance(treemap *_map_, treemap_node *node)
|
||||
{
|
||||
treemap_node *scan = node, *child = NULL;
|
||||
treemap_node *scan = node, *child = ((void *)0);
|
||||
int balance;
|
||||
bool is_root = false;
|
||||
while (scan != NULL)
|
||||
_Bool is_root = 0;
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (scan->parent == NULL)
|
||||
is_root = true;
|
||||
if (scan->parent == ((void *)0))
|
||||
is_root = 1;
|
||||
scan->height = tm_impl_hupdate(scan);
|
||||
balance = tm_impl_h(scan->right) - tm_impl_h(scan->left);
|
||||
if (balance >= 2)
|
||||
@@ -579,7 +675,7 @@ static void tm_impl_rebalance(treemap *_map_, treemap_node *node)
|
||||
if (is_root)
|
||||
{
|
||||
_map_->root = scan;
|
||||
is_root = false;
|
||||
is_root = 0;
|
||||
}
|
||||
scan = scan->parent;
|
||||
}
|
||||
|
||||
+265
-178
@@ -1,6 +1,6 @@
|
||||
#include "cmc/treeset.h"
|
||||
#include <cmc/treeset.h>
|
||||
|
||||
//TREESET_GENERATE(ts, treeset, , size_t)
|
||||
//CMC_GENERATE_TREESET(ts, treeset, size_t)
|
||||
|
||||
typedef struct treeset_s
|
||||
{
|
||||
@@ -25,39 +25,43 @@ typedef struct treeset_iter_s
|
||||
struct treeset_node_s *first;
|
||||
struct treeset_node_s *last;
|
||||
size_t index;
|
||||
bool start;
|
||||
bool end;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
} treeset_iter, *treeset_iter_ptr;
|
||||
treeset *ts_new(int (*compare)(size_t, size_t));
|
||||
void ts_clear(treeset *_set_);
|
||||
void ts_free(treeset *_set_);
|
||||
bool ts_insert(treeset *_set_, size_t element);
|
||||
bool ts_remove(treeset *_set_, size_t element);
|
||||
bool ts_insert_if(treeset *_set_, size_t element, bool condition);
|
||||
bool ts_remove_if(treeset *_set_, size_t element, bool condition);
|
||||
bool ts_max(treeset *_set_, size_t *value);
|
||||
bool ts_min(treeset *_set_, size_t *value);
|
||||
bool ts_contains(treeset *_set_, size_t element);
|
||||
bool ts_empty(treeset *_set_);
|
||||
void ts_clear(treeset *_set_, void (*deallocator)(size_t));
|
||||
void ts_free(treeset *_set_, void (*deallocator)(size_t));
|
||||
_Bool ts_insert(treeset *_set_, size_t element);
|
||||
_Bool ts_remove(treeset *_set_, size_t element);
|
||||
_Bool ts_max(treeset *_set_, size_t *value);
|
||||
_Bool ts_min(treeset *_set_, size_t *value);
|
||||
_Bool ts_contains(treeset *_set_, size_t element);
|
||||
_Bool ts_empty(treeset *_set_);
|
||||
size_t ts_count(treeset *_set_);
|
||||
treeset *ts_copy_of(treeset *_set_, size_t (*copy_func)(size_t));
|
||||
_Bool ts_equals(treeset *_set1_, treeset *_set2_);
|
||||
cmc_string ts_to_string(treeset *_set_);
|
||||
treeset *ts_union(treeset *_set1_, treeset *_set2_);
|
||||
treeset *ts_intersection(treeset *_set1_, treeset *_set2_);
|
||||
treeset *ts_difference(treeset *_set1_, treeset *_set2_);
|
||||
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_);
|
||||
bool ts_is_subset(treeset *_set1_, treeset *_set2_);
|
||||
bool ts_is_superset(treeset *_set1_, treeset *_set2_);
|
||||
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_);
|
||||
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_);
|
||||
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_);
|
||||
_Bool ts_is_subset(treeset *_set1_, treeset *_set2_);
|
||||
_Bool ts_is_superset(treeset *_set1_, treeset *_set2_);
|
||||
_Bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_);
|
||||
_Bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_);
|
||||
_Bool ts_is_disjointset(treeset *_set1_, treeset *_set2_);
|
||||
treeset_iter *ts_iter_new(treeset *target);
|
||||
void ts_iter_free(treeset_iter *iter);
|
||||
void ts_iter_init(treeset_iter *iter, treeset *target);
|
||||
bool ts_iter_start(treeset_iter *iter);
|
||||
bool ts_iter_end(treeset_iter *iter);
|
||||
_Bool ts_iter_start(treeset_iter *iter);
|
||||
_Bool ts_iter_end(treeset_iter *iter);
|
||||
void ts_iter_to_start(treeset_iter *iter);
|
||||
void ts_iter_to_end(treeset_iter *iter);
|
||||
bool ts_iter_next(treeset_iter *iter);
|
||||
bool ts_iter_prev(treeset_iter *iter);
|
||||
_Bool ts_iter_next(treeset_iter *iter);
|
||||
_Bool ts_iter_prev(treeset_iter *iter);
|
||||
_Bool ts_iter_advance(treeset_iter *iter, size_t steps);
|
||||
_Bool ts_iter_rewind(treeset_iter *iter, size_t steps);
|
||||
_Bool ts_iter_go_to(treeset_iter *iter, size_t index);
|
||||
size_t ts_iter_value(treeset_iter *iter);
|
||||
size_t ts_iter_index(treeset_iter *iter);
|
||||
static inline size_t ts_impl_default_value(void)
|
||||
@@ -79,49 +83,53 @@ treeset *ts_new(int (*compare)(size_t, size_t))
|
||||
{
|
||||
treeset *_set_ = malloc(sizeof(treeset));
|
||||
if (!_set_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
_set_->count = 0;
|
||||
_set_->root = NULL;
|
||||
_set_->root = ((void *)0);
|
||||
_set_->cmp = compare;
|
||||
_set_->it_start = ts_impl_it_start;
|
||||
_set_->it_end = ts_impl_it_end;
|
||||
return _set_;
|
||||
}
|
||||
void ts_clear(treeset *_set_)
|
||||
void ts_clear(treeset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
treeset_node *scan = _set_->root;
|
||||
treeset_node *up = NULL;
|
||||
while (scan != NULL)
|
||||
treeset_node *up = ((void *)0);
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (scan->left != NULL)
|
||||
if (scan->left != ((void *)0))
|
||||
{
|
||||
treeset_node *left = scan->left;
|
||||
scan->left = up;
|
||||
up = scan;
|
||||
scan = left;
|
||||
}
|
||||
else if (scan->right != NULL)
|
||||
else if (scan->right != ((void *)0))
|
||||
{
|
||||
treeset_node *right = scan->right;
|
||||
scan->left = up;
|
||||
scan->right = NULL;
|
||||
scan->right = ((void *)0);
|
||||
up = scan;
|
||||
scan = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (up == NULL)
|
||||
if (up == ((void *)0))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(scan->value);
|
||||
free(scan);
|
||||
scan = NULL;
|
||||
scan = ((void *)0);
|
||||
}
|
||||
while (up != NULL)
|
||||
while (up != ((void *)0))
|
||||
{
|
||||
if (deallocator)
|
||||
deallocator(scan->value);
|
||||
free(scan);
|
||||
if (up->right != NULL)
|
||||
if (up->right != ((void *)0))
|
||||
{
|
||||
scan = up->right;
|
||||
up->right = NULL;
|
||||
up->right = ((void *)0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -133,26 +141,26 @@ void ts_clear(treeset *_set_)
|
||||
}
|
||||
}
|
||||
_set_->count = 0;
|
||||
_set_->root = NULL;
|
||||
_set_->root = ((void *)0);
|
||||
}
|
||||
void ts_free(treeset *_set_)
|
||||
void ts_free(treeset *_set_, void (*deallocator)(size_t))
|
||||
{
|
||||
ts_clear(_set_);
|
||||
ts_clear(_set_, deallocator);
|
||||
free(_set_);
|
||||
}
|
||||
bool ts_insert(treeset *_set_, size_t element)
|
||||
_Bool ts_insert(treeset *_set_, size_t element)
|
||||
{
|
||||
if (ts_empty(_set_))
|
||||
{
|
||||
_set_->root = ts_impl_new_node(element);
|
||||
if (!_set_->root)
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
treeset_node *scan = _set_->root;
|
||||
treeset_node *parent = scan;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
parent = scan;
|
||||
if (_set_->cmp(scan->value, element) > 0)
|
||||
@@ -160,14 +168,14 @@ bool ts_insert(treeset *_set_, size_t element)
|
||||
else if (_set_->cmp(scan->value, element) < 0)
|
||||
scan = scan->right;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
treeset_node *node;
|
||||
if (_set_->cmp(parent->value, element) > 0)
|
||||
{
|
||||
parent->left = ts_impl_new_node(element);
|
||||
if (!parent->left)
|
||||
return false;
|
||||
return 0;
|
||||
parent->left->parent = parent;
|
||||
node = parent->left;
|
||||
}
|
||||
@@ -175,42 +183,42 @@ bool ts_insert(treeset *_set_, size_t element)
|
||||
{
|
||||
parent->right = ts_impl_new_node(element);
|
||||
if (!parent->right)
|
||||
return false;
|
||||
return 0;
|
||||
parent->right->parent = parent;
|
||||
node = parent->right;
|
||||
}
|
||||
ts_impl_rebalance(_set_, node);
|
||||
}
|
||||
_set_->count++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ts_remove(treeset *_set_, size_t element)
|
||||
_Bool ts_remove(treeset *_set_, size_t element)
|
||||
{
|
||||
treeset_node *node = ts_impl_get_node(_set_, element);
|
||||
if (!node)
|
||||
return false;
|
||||
treeset_node *temp = NULL, *unbalanced = NULL;
|
||||
bool is_root = node->parent == NULL;
|
||||
if (node->left == NULL && node->right == NULL)
|
||||
return 0;
|
||||
treeset_node *temp = ((void *)0), *unbalanced = ((void *)0);
|
||||
_Bool is_root = node->parent == ((void *)0);
|
||||
if (node->left == ((void *)0) && node->right == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
_set_->root = NULL;
|
||||
_set_->root = ((void *)0);
|
||||
else
|
||||
{
|
||||
unbalanced = node->parent;
|
||||
if (node->parent->right == node)
|
||||
node->parent->right = NULL;
|
||||
node->parent->right = ((void *)0);
|
||||
else
|
||||
node->parent->left = NULL;
|
||||
node->parent->left = ((void *)0);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
else if (node->left == NULL)
|
||||
else if (node->left == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
{
|
||||
_set_->root = node->right;
|
||||
_set_->root->parent = NULL;
|
||||
_set_->root->parent = ((void *)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -223,12 +231,12 @@ bool ts_remove(treeset *_set_, size_t element)
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
else if (node->right == NULL)
|
||||
else if (node->right == ((void *)0))
|
||||
{
|
||||
if (is_root)
|
||||
{
|
||||
_set_->root = node->left;
|
||||
_set_->root->parent = NULL;
|
||||
_set_->root->parent = ((void *)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -244,18 +252,18 @@ bool ts_remove(treeset *_set_, size_t element)
|
||||
else
|
||||
{
|
||||
temp = node->right;
|
||||
while (temp->left != NULL)
|
||||
while (temp->left != ((void *)0))
|
||||
temp = temp->left;
|
||||
size_t temp_value = temp->value;
|
||||
unbalanced = temp->parent;
|
||||
if (temp->left == NULL && temp->right == NULL)
|
||||
if (temp->left == ((void *)0) && temp->right == ((void *)0))
|
||||
{
|
||||
if (temp->parent->right == temp)
|
||||
temp->parent->right = NULL;
|
||||
temp->parent->right = ((void *)0);
|
||||
else
|
||||
temp->parent->left = NULL;
|
||||
temp->parent->left = ((void *)0);
|
||||
}
|
||||
else if (temp->left == NULL)
|
||||
else if (temp->left == ((void *)0))
|
||||
{
|
||||
temp->right->parent = temp->parent;
|
||||
if (temp->parent->right == temp)
|
||||
@@ -263,7 +271,7 @@ bool ts_remove(treeset *_set_, size_t element)
|
||||
else
|
||||
temp->parent->left = temp->right;
|
||||
}
|
||||
else if (temp->right == NULL)
|
||||
else if (temp->right == ((void *)0))
|
||||
{
|
||||
temp->left->parent = temp->parent;
|
||||
if (temp->parent->right == temp)
|
||||
@@ -274,66 +282,94 @@ bool ts_remove(treeset *_set_, size_t element)
|
||||
free(temp);
|
||||
node->value = temp_value;
|
||||
}
|
||||
if (unbalanced != NULL)
|
||||
if (unbalanced != ((void *)0))
|
||||
ts_impl_rebalance(_set_, unbalanced);
|
||||
_set_->count--;
|
||||
if (_set_->count == 0)
|
||||
_set_->root = NULL;
|
||||
return true;
|
||||
_set_->root = ((void *)0);
|
||||
return 1;
|
||||
}
|
||||
bool ts_insert_if(treeset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ts_insert(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool ts_remove_if(treeset *_set_, size_t element, bool condition)
|
||||
{
|
||||
if (condition)
|
||||
return ts_remove(_set_, element);
|
||||
return false;
|
||||
}
|
||||
bool ts_max(treeset *_set_, size_t *value)
|
||||
_Bool ts_max(treeset *_set_, size_t *value)
|
||||
{
|
||||
if (ts_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
treeset_node *scan = _set_->root;
|
||||
while (scan->right != NULL)
|
||||
while (scan->right != ((void *)0))
|
||||
scan = scan->right;
|
||||
*value = scan->value;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ts_min(treeset *_set_, size_t *value)
|
||||
_Bool ts_min(treeset *_set_, size_t *value)
|
||||
{
|
||||
if (ts_empty(_set_))
|
||||
return false;
|
||||
return 0;
|
||||
treeset_node *scan = _set_->root;
|
||||
while (scan->left != NULL)
|
||||
while (scan->left != ((void *)0))
|
||||
scan = scan->left;
|
||||
*value = scan->value;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ts_contains(treeset *_set_, size_t element)
|
||||
_Bool ts_contains(treeset *_set_, size_t element)
|
||||
{
|
||||
treeset_node *scan = _set_->root;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (_set_->cmp(scan->value, element) > 0)
|
||||
scan = scan->left;
|
||||
else if (_set_->cmp(scan->value, element) < 0)
|
||||
scan = scan->right;
|
||||
else
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
bool ts_empty(treeset *_set_) { return _set_->count == 0; }
|
||||
_Bool ts_empty(treeset *_set_) { return _set_->count == 0; }
|
||||
size_t ts_count(treeset *_set_) { return _set_->count; }
|
||||
treeset *ts_copy_of(treeset *_set_, size_t (*copy_func)(size_t))
|
||||
{
|
||||
treeset *result = ts_new(_set_->cmp);
|
||||
if (!result)
|
||||
return ((void *)0);
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set_);
|
||||
if (!ts_empty(_set_))
|
||||
{
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
if (copy_func)
|
||||
ts_insert(result, copy_func(ts_iter_value(&iter)));
|
||||
else
|
||||
ts_insert(result, ts_iter_value(&iter));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
_Bool ts_equals(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
if (ts_count(_set1_) != ts_count(_set2_))
|
||||
return 0;
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set1_);
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
if (ts_impl_get_node(_set2_, ts_iter_value(&iter)) == ((void *)0))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cmc_string ts_to_string(treeset *_set_)
|
||||
{
|
||||
cmc_string str;
|
||||
treeset *s_ = _set_;
|
||||
const char *name = "treeset";
|
||||
snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, name, s_, s_->root, s_->count, s_->cmp);
|
||||
return str;
|
||||
}
|
||||
treeset *ts_union(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
treeset *_set_r_ = ts_new(_set1_->cmp);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treeset_iter iter1, iter2;
|
||||
ts_iter_init(&iter1, _set1_);
|
||||
ts_iter_init(&iter2, _set2_);
|
||||
@@ -351,7 +387,7 @@ treeset *ts_intersection(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
treeset *_set_r_ = ts_new(_set1_->cmp);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
|
||||
treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
|
||||
treeset_iter iter;
|
||||
@@ -359,7 +395,7 @@ treeset *ts_intersection(treeset *_set1_, treeset *_set2_)
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter);
|
||||
if (ts_impl_get_node(_set_B_, value) != NULL)
|
||||
if (ts_impl_get_node(_set_B_, value) != ((void *)0))
|
||||
ts_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
@@ -368,13 +404,13 @@ treeset *ts_difference(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
treeset *_set_r_ = ts_new(_set1_->cmp);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set1_);
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter);
|
||||
if (ts_impl_get_node(_set2_, value) == NULL)
|
||||
if (ts_impl_get_node(_set2_, value) == ((void *)0))
|
||||
ts_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
@@ -383,51 +419,51 @@ treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
treeset *_set_r_ = ts_new(_set1_->cmp);
|
||||
if (!_set_r_)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treeset_iter iter1, iter2;
|
||||
ts_iter_init(&iter1, _set1_);
|
||||
ts_iter_init(&iter2, _set2_);
|
||||
for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter1);
|
||||
if (ts_impl_get_node(_set2_, value) == NULL)
|
||||
if (ts_impl_get_node(_set2_, value) == ((void *)0))
|
||||
ts_insert(_set_r_, value);
|
||||
}
|
||||
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter2);
|
||||
if (ts_impl_get_node(_set1_, value) == NULL)
|
||||
if (ts_impl_get_node(_set1_, value) == ((void *)0))
|
||||
ts_insert(_set_r_, value);
|
||||
}
|
||||
return _set_r_;
|
||||
}
|
||||
bool ts_is_subset(treeset *_set1_, treeset *_set2_)
|
||||
_Bool ts_is_subset(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
if (ts_count(_set1_) > ts_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (ts_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set1_);
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter);
|
||||
if (!ts_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); }
|
||||
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_)
|
||||
_Bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); }
|
||||
_Bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
if (ts_count(_set1_) >= ts_count(_set2_))
|
||||
return false;
|
||||
return 0;
|
||||
if (ts_empty(_set1_))
|
||||
{
|
||||
if (!ts_empty(_set2_))
|
||||
return true;
|
||||
return 1;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set1_);
|
||||
@@ -435,126 +471,177 @@ bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
size_t value = ts_iter_value(&iter);
|
||||
if (!ts_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); }
|
||||
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_)
|
||||
_Bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); }
|
||||
_Bool ts_is_disjointset(treeset *_set1_, treeset *_set2_)
|
||||
{
|
||||
if (ts_empty(_set1_))
|
||||
return true;
|
||||
return 1;
|
||||
treeset_iter iter;
|
||||
ts_iter_init(&iter, _set1_);
|
||||
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
|
||||
{
|
||||
size_t value = ts_iter_value(&iter);
|
||||
if (ts_contains(_set2_, value))
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
treeset_iter *ts_iter_new(treeset *target)
|
||||
{
|
||||
treeset_iter *iter = malloc(sizeof(treeset_iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
ts_iter_init(iter, target);
|
||||
return iter;
|
||||
}
|
||||
void ts_iter_free(treeset_iter *iter) { free(iter); }
|
||||
void ts_iter_init(treeset_iter *iter, treeset *target)
|
||||
{
|
||||
memset(iter, 0, sizeof(treeset_iter));
|
||||
iter->target = target;
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->start = 1;
|
||||
iter->end = ts_empty(target);
|
||||
iter->cursor = target->root;
|
||||
while (iter->cursor->left != NULL)
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->first = iter->cursor;
|
||||
iter->last = target->root;
|
||||
while (iter->last->right != NULL)
|
||||
iter->last = iter->last->right;
|
||||
if (!ts_empty(target))
|
||||
{
|
||||
while (iter->cursor->left != ((void *)0))
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->first = iter->cursor;
|
||||
iter->last = target->root;
|
||||
while (iter->last->right != ((void *)0))
|
||||
iter->last = iter->last->right;
|
||||
}
|
||||
}
|
||||
bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; }
|
||||
bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; }
|
||||
_Bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; }
|
||||
_Bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; }
|
||||
void ts_iter_to_start(treeset_iter *iter)
|
||||
{
|
||||
iter->index = 0;
|
||||
iter->start = true;
|
||||
iter->end = ts_empty(iter->target);
|
||||
iter->cursor = iter->first;
|
||||
if (!ts_empty(iter->target))
|
||||
{
|
||||
iter->index = 0;
|
||||
iter->start = 1;
|
||||
iter->end = ts_empty(iter->target);
|
||||
iter->cursor = iter->first;
|
||||
}
|
||||
}
|
||||
void ts_iter_to_end(treeset_iter *iter)
|
||||
{
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ts_empty(iter->target);
|
||||
iter->end = true;
|
||||
iter->cursor = iter->last;
|
||||
if (!ts_empty(iter->target))
|
||||
{
|
||||
iter->index = iter->target->count - 1;
|
||||
iter->start = ts_empty(iter->target);
|
||||
iter->end = 1;
|
||||
iter->cursor = iter->last;
|
||||
}
|
||||
}
|
||||
bool ts_iter_next(treeset_iter *iter)
|
||||
_Bool ts_iter_next(treeset_iter *iter)
|
||||
{
|
||||
if (iter->end)
|
||||
return false;
|
||||
return 0;
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 1;
|
||||
}
|
||||
iter->start = ts_empty(iter->target);
|
||||
if (iter->cursor->right != NULL)
|
||||
if (iter->cursor->right != ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->right;
|
||||
while (iter->cursor->left != NULL)
|
||||
while (iter->cursor->left != ((void *)0))
|
||||
iter->cursor = iter->cursor->left;
|
||||
iter->index++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = true;
|
||||
return true;
|
||||
}
|
||||
if (iter->cursor->parent->left == iter->cursor)
|
||||
{
|
||||
iter->cursor = iter->cursor->parent;
|
||||
iter->index++;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
iter->cursor = iter->cursor->parent;
|
||||
}
|
||||
}
|
||||
bool ts_iter_prev(treeset_iter *iter)
|
||||
_Bool ts_iter_prev(treeset_iter *iter)
|
||||
{
|
||||
if (iter->start)
|
||||
return false;
|
||||
return 0;
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 1;
|
||||
}
|
||||
iter->end = ts_empty(iter->target);
|
||||
if (iter->cursor->left != NULL)
|
||||
if (iter->cursor->left != ((void *)0))
|
||||
{
|
||||
iter->cursor = iter->cursor->left;
|
||||
while (iter->cursor->right != NULL)
|
||||
while (iter->cursor->right != ((void *)0))
|
||||
iter->cursor = iter->cursor->right;
|
||||
iter->index--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
while (true)
|
||||
while (1)
|
||||
{
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = true;
|
||||
return true;
|
||||
}
|
||||
if (iter->cursor->parent->right == iter->cursor)
|
||||
{
|
||||
iter->cursor = iter->cursor->parent;
|
||||
iter->index--;
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
iter->cursor = iter->cursor->parent;
|
||||
}
|
||||
}
|
||||
_Bool ts_iter_advance(treeset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->end)
|
||||
return 0;
|
||||
if (iter->cursor == iter->last)
|
||||
{
|
||||
iter->end = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index + steps >= ts_count(iter->target))
|
||||
return 0;
|
||||
iter->index += steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
ts_iter_next(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool ts_iter_rewind(treeset_iter *iter, size_t steps)
|
||||
{
|
||||
if (iter->start)
|
||||
return 0;
|
||||
if (iter->cursor == iter->first)
|
||||
{
|
||||
iter->start = 1;
|
||||
return 0;
|
||||
}
|
||||
if (steps == 0 || iter->index < steps)
|
||||
return 0;
|
||||
iter->index -= steps;
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
ts_iter_prev(iter);
|
||||
return 1;
|
||||
}
|
||||
_Bool ts_iter_go_to(treeset_iter *iter, size_t index)
|
||||
{
|
||||
if (index >= ts_count(iter->target))
|
||||
return 0;
|
||||
if (iter->index > index)
|
||||
return ts_iter_rewind(iter, iter->index - index);
|
||||
else if (iter->index < index)
|
||||
return ts_iter_advance(iter, index - iter->index);
|
||||
return 1;
|
||||
}
|
||||
size_t ts_iter_value(treeset_iter *iter)
|
||||
{
|
||||
if (ts_empty(iter->target))
|
||||
return ts_impl_default_value();
|
||||
return (size_t){0};
|
||||
return iter->cursor->value;
|
||||
}
|
||||
size_t ts_iter_index(treeset_iter *iter) { return iter->index; }
|
||||
@@ -562,20 +649,20 @@ static treeset_node *ts_impl_new_node(size_t element)
|
||||
{
|
||||
treeset_node *node = malloc(sizeof(treeset_node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
node->value = element;
|
||||
node->right = NULL;
|
||||
node->left = NULL;
|
||||
node->parent = NULL;
|
||||
node->right = ((void *)0);
|
||||
node->left = ((void *)0);
|
||||
node->parent = ((void *)0);
|
||||
node->height = 0;
|
||||
return node;
|
||||
}
|
||||
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element)
|
||||
{
|
||||
if (ts_empty(_set_))
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
treeset_node *scan = _set_->root;
|
||||
while (scan != NULL)
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (_set_->cmp(scan->value, element) > 0)
|
||||
scan = scan->left;
|
||||
@@ -584,17 +671,17 @@ static treeset_node *ts_impl_get_node(treeset *_set_, size_t element)
|
||||
else
|
||||
return scan;
|
||||
}
|
||||
return NULL;
|
||||
return ((void *)0);
|
||||
}
|
||||
static unsigned char ts_impl_h(treeset_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
if (node == ((void *)0))
|
||||
return 0;
|
||||
return node->height;
|
||||
}
|
||||
static unsigned char ts_impl_hupdate(treeset_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
if (node == ((void *)0))
|
||||
return 0;
|
||||
unsigned char h_l = ts_impl_h(node->left);
|
||||
unsigned char h_r = ts_impl_h(node->right);
|
||||
@@ -604,7 +691,7 @@ static void ts_impl_rotate_right(treeset_node **Z)
|
||||
{
|
||||
treeset_node *root = *Z;
|
||||
treeset_node *new_root = root->left;
|
||||
if (root->parent != NULL)
|
||||
if (root->parent != ((void *)0))
|
||||
{
|
||||
if (root->parent->left == root)
|
||||
root->parent->left = new_root;
|
||||
@@ -625,7 +712,7 @@ static void ts_impl_rotate_left(treeset_node **Z)
|
||||
{
|
||||
treeset_node *root = *Z;
|
||||
treeset_node *new_root = root->right;
|
||||
if (root->parent != NULL)
|
||||
if (root->parent != ((void *)0))
|
||||
{
|
||||
if (root->parent->right == root)
|
||||
root->parent->right = new_root;
|
||||
@@ -644,13 +731,13 @@ static void ts_impl_rotate_left(treeset_node **Z)
|
||||
}
|
||||
static void ts_impl_rebalance(treeset *_set_, treeset_node *node)
|
||||
{
|
||||
treeset_node *scan = node, *child = NULL;
|
||||
treeset_node *scan = node, *child = ((void *)0);
|
||||
int balance;
|
||||
bool is_root = false;
|
||||
while (scan != NULL)
|
||||
_Bool is_root = 0;
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (scan->parent == NULL)
|
||||
is_root = true;
|
||||
if (scan->parent == ((void *)0))
|
||||
is_root = 1;
|
||||
scan->height = ts_impl_hupdate(scan);
|
||||
balance = ts_impl_h(scan->right) - ts_impl_h(scan->left);
|
||||
if (balance >= 2)
|
||||
@@ -670,7 +757,7 @@ static void ts_impl_rebalance(treeset *_set_, treeset_node *node)
|
||||
if (is_root)
|
||||
{
|
||||
_set_->root = scan;
|
||||
is_root = false;
|
||||
is_root = 0;
|
||||
}
|
||||
scan = scan->parent;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/bidimap.c"
|
||||
|
||||
CMC_CREATE_UNIT(bidimap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
bm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count], {
|
||||
bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(bm_insert(map, i, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, bm_count(map));
|
||||
|
||||
bm_clear(map, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, bm_count(map));
|
||||
|
||||
bm_free(map, NULL);
|
||||
});
|
||||
});
|
||||
+579
-9
@@ -1,5 +1,8 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/deque.c"
|
||||
|
||||
CMC_CREATE_UNIT(deque_test, false, {
|
||||
@@ -11,16 +14,16 @@ CMC_CREATE_UNIT(deque_test, false, {
|
||||
cmc_assert_equals(size_t, 1000000, d->capacity);
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
d_free(d);
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
deque *d = d_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, d);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
deque *d = d_new(UINT64_MAX);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, d);
|
||||
@@ -36,15 +39,15 @@ CMC_CREATE_UNIT(deque_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, d_count(d));
|
||||
|
||||
d_clear(d);
|
||||
d_clear(d, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
cmc_assert_equals(size_t, 100, d_capacity(d));
|
||||
|
||||
d_free(d);
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
deque *d = d_new(1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
@@ -55,7 +58,574 @@ CMC_CREATE_UNIT(deque_test, false, {
|
||||
cmc_assert_equals(size_t, 50, d_count(d));
|
||||
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
|
||||
|
||||
d_free(d);
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 1200; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
d_push_front(d, i);
|
||||
else
|
||||
d_push_back(d, i);
|
||||
}
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
sum += d->buffer[i];
|
||||
|
||||
cmc_assert_equals(size_t, 1200, d_count(d));
|
||||
cmc_assert_equals(size_t, 720600, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[count capacity], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
cmc_assert(d_push_front(d, i));
|
||||
|
||||
cmc_assert_equals(size_t, 150, d_count(d));
|
||||
cmc_assert_greater(size_t, 100, d_capacity(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(d_push_front(d, i));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
{
|
||||
sum += d->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_back[count capacity], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
|
||||
cmc_assert_equals(size_t, 150, d_count(d));
|
||||
cmc_assert_greater(size_t, 100, d_capacity(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_back[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
{
|
||||
sum += d->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[count capacity], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 200; i++)
|
||||
cmc_assert(d_push_front(d, i));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
{
|
||||
sum += d->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_back[count capacity], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_back[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 200; i++)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
{
|
||||
sum += d->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(Mixed IO, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
// ----------
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_back(d));
|
||||
cmc_assert(d_pop_front(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
cmc_assert(d_push_front(d, 10));
|
||||
cmc_assert(d_push_back(d, 10));
|
||||
cmc_assert(d_pop_front(d));
|
||||
cmc_assert(d_pop_back(d));
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(front[count = 0], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
size_t r = d_front(d);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){0}, r);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(front[sum], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d, i));
|
||||
}
|
||||
|
||||
while (!d_empty(d))
|
||||
{
|
||||
size_t r = d_front(d);
|
||||
|
||||
sum += r;
|
||||
|
||||
cmc_assert(d_pop_front(d));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(back[count = 0], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
size_t r = d_back(d);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){0}, r);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(back[sum], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d, i));
|
||||
}
|
||||
|
||||
while (!d_empty(d))
|
||||
{
|
||||
size_t r = d_back(d);
|
||||
|
||||
sum += r;
|
||||
|
||||
cmc_assert(d_pop_back(d));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(d_contains(d, i, cmp));
|
||||
|
||||
d_clear(d, NULL);
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(d_push_front(d, i));
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(d_contains(d, i, cmp));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 0], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(!d_contains(d, 10, cmp));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 1], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(!d_contains(d, 10, cmp));
|
||||
|
||||
cmc_assert(d_push_back(d, 100));
|
||||
|
||||
cmc_assert(d_contains(d, 100, cmp));
|
||||
cmc_assert(!d_contains(d, 101, cmp));
|
||||
|
||||
cmc_assert(d_pop_front(d));
|
||||
cmc_assert(d_push_front(d, 100));
|
||||
|
||||
cmc_assert(d_contains(d, 100, cmp));
|
||||
cmc_assert(!d_contains(d, 101, cmp));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(d_empty(d));
|
||||
|
||||
cmc_assert(d_push_front(d, 1));
|
||||
|
||||
cmc_assert(!d_empty(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert(!d_full(d));
|
||||
|
||||
for (size_t i = 0; i != d_capacity(d); i++)
|
||||
cmc_assert(d_push_front(d, i));
|
||||
|
||||
cmc_assert(d_full(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(count, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert_equals(size_t, 0, d_count(d));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
|
||||
cmc_assert_equals(size_t, 100, d_count(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
cmc_assert_equals(size_t, 100, d_capacity(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(resize, {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d, i));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 150, d_count(d));
|
||||
cmc_assert(d_resize(d, d_count(d)));
|
||||
cmc_assert_equals(size_t, 150, d_capacity(d));
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(resize[item preservation], {
|
||||
deque *d = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
if (i % 2 != 0)
|
||||
cmc_assert(d_push_back(d, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d, i));
|
||||
}
|
||||
|
||||
cmc_assert(d_resize(d, d_count(d)));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
|
||||
{
|
||||
sum += d->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 11325, sum);
|
||||
|
||||
d_free(d, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(copy_of, {
|
||||
deque *d1 = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
if (i % 2 != 0)
|
||||
cmc_assert(d_push_back(d1, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d1, i));
|
||||
}
|
||||
|
||||
deque *d2 = d_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
cmc_assert_equals(size_t, d_count(d1), d_count(d2));
|
||||
|
||||
for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++)
|
||||
{
|
||||
cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]);
|
||||
|
||||
i1 = (i1 + 1) % d1->capacity;
|
||||
i2 = (i2 + 1) % d2->capacity;
|
||||
}
|
||||
|
||||
d_free(d1, NULL);
|
||||
d_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals, {
|
||||
deque *d1 = d_new(100);
|
||||
deque *d2 = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
if (i % 2 != 0)
|
||||
{
|
||||
cmc_assert(d_push_back(d1, i));
|
||||
cmc_assert(d_push_back(d2, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
cmc_assert(d_push_front(d1, i));
|
||||
cmc_assert(d_push_front(d2, i));
|
||||
}
|
||||
}
|
||||
|
||||
cmc_assert(d_equals(d1, d2, cmp));
|
||||
|
||||
d_free(d1, NULL);
|
||||
d_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals[from copy], {
|
||||
deque *d1 = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
if (i % 2 != 0)
|
||||
cmc_assert(d_push_back(d1, i));
|
||||
else
|
||||
cmc_assert(d_push_front(d1, i));
|
||||
}
|
||||
|
||||
deque *d2 = d_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
cmc_assert(d_equals(d1, d2, cmp));
|
||||
|
||||
d_free(d1, NULL);
|
||||
d_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals[count = 0], {
|
||||
deque *d1 = d_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
deque *d2 = d_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
cmc_assert(d_equals(d1, d2, cmp));
|
||||
|
||||
d_free(d1, NULL);
|
||||
d_free(d2, NULL);
|
||||
});
|
||||
});
|
||||
+415
-10
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/hashmap.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/hashmap.c"
|
||||
|
||||
CMC_CREATE_UNIT(hashmap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -13,17 +14,17 @@ CMC_CREATE_UNIT(hashmap_test, false, {
|
||||
cmc_assert_equals(size_t, 0, hm_count(map));
|
||||
cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map));
|
||||
|
||||
hm_free(map);
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
hashmap *map = hm_new(0, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
hashmap *map = hm_new(UINT64_MAX, 0.6, cmp, hash);
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
hashmap *map = hm_new(UINT64_MAX, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, map);
|
||||
});
|
||||
@@ -38,11 +39,415 @@ CMC_CREATE_UNIT(hashmap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, hm_count(map));
|
||||
|
||||
hm_clear(map);
|
||||
hm_clear(map, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, hm_count(map));
|
||||
|
||||
hm_free(map);
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_insert(map, 1, 1));
|
||||
cmc_assert_equals(size_t, 1, hm_count(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[smallest capacity], {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
|
||||
cmc_assert(hm_insert(map, 1, 1));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[element position], {
|
||||
// Using the numhash the key is the hash itself
|
||||
hashmap *map = hm_new(1, 0.99, cmp, numhash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
size_t capacity = hm_capacity(map);
|
||||
|
||||
cmc_assert_greater(size_t, 0, capacity);
|
||||
|
||||
cmc_assert(hm_insert(map, capacity - 1, capacity - 1));
|
||||
cmc_assert(hm_insert(map, capacity, capacity));
|
||||
|
||||
cmc_assert_equals(size_t, capacity - 1, map->buffer[capacity - 1].key);
|
||||
cmc_assert_equals(size_t, capacity, map->buffer[0].key);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[distance], {
|
||||
hashmap *map = hm_new(500, 0.6, cmp, hash0);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
// Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
cmc_assert_equals(size_t, i, map->buffer[i].dist);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[distance wrap], {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hashcapminus1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
size_t capacity = hm_capacity(map);
|
||||
|
||||
// Just to be sure, not part of the test
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0));
|
||||
cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0));
|
||||
|
||||
cmc_assert(hm_insert(map, 0, 0));
|
||||
cmc_assert(hm_insert(map, 1, 1));
|
||||
|
||||
cmc_assert_equals(size_t, 0, map->buffer[capacity - 1].dist);
|
||||
cmc_assert_equals(size_t, 1, map->buffer[0].dist);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[distances], {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hashcapminus4);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
|
||||
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
cmc_assert_equals(size_t, i, hm_impl_get_entry(map, i)->dist);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[buffer growth and item preservation], {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
|
||||
|
||||
size_t p = 0;
|
||||
for (size_t i = 0; i < 100000; i++)
|
||||
{
|
||||
if (hm_full(map))
|
||||
p++;
|
||||
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[p], hm_capacity(map));
|
||||
|
||||
for (size_t i = 0; i < 100000; i++)
|
||||
cmc_assert(hm_contains(map, i));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(update, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_insert(map, 1, 1));
|
||||
|
||||
size_t old;
|
||||
cmc_assert(hm_update(map, 1, 2, &old));
|
||||
|
||||
cmc_assert_equals(size_t, 1, old);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(update[key not found], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
cmc_assert(!hm_update(map, 120, 120, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hm_remove(map, i, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 100; i < 200; i++)
|
||||
cmc_assert(!hm_remove(map, i, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[key not found], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
for (size_t i = 100; i < 200; i++)
|
||||
cmc_assert(!hm_remove(map, i, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(max, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
size_t key;
|
||||
size_t val;
|
||||
cmc_assert(hm_max(map, &key, &val));
|
||||
|
||||
cmc_assert_equals(size_t, 100, key);
|
||||
cmc_assert_equals(size_t, 100, val);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(max[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(!hm_min(map, NULL, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(min, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
size_t key;
|
||||
size_t val;
|
||||
cmc_assert(hm_min(map, &key, &val));
|
||||
|
||||
cmc_assert_equals(size_t, 1, key);
|
||||
cmc_assert_equals(size_t, 1, val);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(min[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(!hm_min(map, NULL, NULL));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(get, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_insert(map, 4321, 1234));
|
||||
|
||||
cmc_assert_equals(size_t, 1234, hm_get(map, 4321));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(get[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){0}, hm_get(map, 4321));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(get_ref, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_insert(map, 4321, 1234));
|
||||
|
||||
size_t *result = hm_get_ref(map, 4321);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, result);
|
||||
cmc_assert_equals(size_t, 1234, *result);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(get_ref[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, hm_get_ref(map, 4321));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_insert(map, 987654321, 1));
|
||||
|
||||
cmc_assert(hm_contains(map, 987654321));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 0], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(!hm_contains(map, 987654321));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[sum], {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 101; i <= 200; i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 1; i <= 300; i++)
|
||||
if (hm_contains(map, i))
|
||||
sum += i;
|
||||
|
||||
cmc_assert_equals(size_t, 15050, sum);
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert(hm_empty(map));
|
||||
|
||||
cmc_assert(hm_insert(map, 1, 1));
|
||||
|
||||
cmc_assert(!hm_empty(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full, {
|
||||
hashmap *map = hm_new(cmc_hashtable_primes[0], 0.99999, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
|
||||
|
||||
for (size_t i = 0; i < hm_capacity(map); i++)
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
|
||||
cmc_assert(hm_full(map));
|
||||
|
||||
cmc_assert(hm_insert(map, 10000, 10000));
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[1], hm_capacity(map));
|
||||
|
||||
cmc_assert(!hm_full(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(count, {
|
||||
hashmap *map = hm_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 1; i < 100; i++)
|
||||
{
|
||||
cmc_assert(hm_insert(map, i, i));
|
||||
cmc_assert_equals(size_t, i, hm_count(map));
|
||||
}
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity, {
|
||||
hashmap *map = hm_new(2500, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hm_capacity(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity[small], {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(load, {
|
||||
hashmap *map = hm_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hm_load(map));
|
||||
|
||||
hm_free(map, NULL);
|
||||
});
|
||||
});
|
||||
+320
-10
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/hashset.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/hashset.c"
|
||||
|
||||
CMC_CREATE_UNIT(hashset_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -13,17 +14,17 @@ CMC_CREATE_UNIT(hashset_test, false, {
|
||||
cmc_assert_equals(size_t, 0, hs_count(set));
|
||||
cmc_assert_greater_equals(size_t, (943722 / 0.6), hs_capacity(set));
|
||||
|
||||
hs_free(set);
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
hashset *set = hs_new(0, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, set);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
hashset *set = hs_new(UINT64_MAX, 0.6, cmp, hash);
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
hashset *set = hs_new(UINT64_MAX, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, set);
|
||||
});
|
||||
@@ -38,11 +39,320 @@ CMC_CREATE_UNIT(hashset_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, hs_count(set));
|
||||
|
||||
hs_clear(set);
|
||||
hs_clear(set, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, hs_count(set));
|
||||
|
||||
hs_free(set);
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(hs_insert(set, 1));
|
||||
cmc_assert_equals(size_t, 1, hs_count(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[smallest capacity], {
|
||||
hashset *set = hs_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
|
||||
cmc_assert(hs_insert(set, 1));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[element position], {
|
||||
// Using the numhash the key is the hash itself
|
||||
hashset *set = hs_new(1, 0.99, cmp, numhash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
size_t capacity = hs_capacity(set);
|
||||
|
||||
cmc_assert_greater(size_t, 0, capacity);
|
||||
|
||||
cmc_assert(hs_insert(set, capacity - 1));
|
||||
cmc_assert(hs_insert(set, capacity));
|
||||
|
||||
cmc_assert_equals(size_t, capacity - 1, set->buffer[capacity - 1].value);
|
||||
cmc_assert_equals(size_t, capacity, set->buffer[0].value);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[distance], {
|
||||
hashset *set = hs_new(500, 0.6, cmp, hash0);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
// Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
cmc_assert_equals(size_t, i, set->buffer[i].dist);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[distance wrap], {
|
||||
hashset *set = hs_new(1, 0.99, cmp, hashcapminus1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
size_t capacity = hs_capacity(set);
|
||||
|
||||
// Just to be sure, not part of the test
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0));
|
||||
cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0));
|
||||
|
||||
cmc_assert(hs_insert(set, 0));
|
||||
cmc_assert(hs_insert(set, 1));
|
||||
|
||||
cmc_assert_equals(size_t, 0, set->buffer[capacity - 1].dist);
|
||||
cmc_assert_equals(size_t, 1, set->buffer[0].dist);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[buffer growth and item preservation], {
|
||||
hashset *set = hs_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
|
||||
|
||||
size_t p = 0;
|
||||
for (size_t i = 0; i < 100000; i++)
|
||||
{
|
||||
if (hs_full(set))
|
||||
p++;
|
||||
|
||||
cmc_assert(hs_insert(set, i));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[p], hs_capacity(set));
|
||||
|
||||
for (size_t i = 0; i < 100000; i++)
|
||||
cmc_assert(hs_contains(set, i));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hs_remove(set, i));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 100; i < 200; i++)
|
||||
cmc_assert(!hs_remove(set, i));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[key not found], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
for (size_t i = 100; i < 200; i++)
|
||||
cmc_assert(!hs_remove(set, i));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(max, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
size_t val;
|
||||
cmc_assert(hs_max(set, &val));
|
||||
|
||||
cmc_assert_equals(size_t, 100, val);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(max[count = 0], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(!hs_min(set, NULL));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(min, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
size_t val;
|
||||
cmc_assert(hs_min(set, &val));
|
||||
|
||||
cmc_assert_equals(size_t, 1, val);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(min[count = 0], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(!hs_min(set, NULL));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(hs_insert(set, 987654321));
|
||||
|
||||
cmc_assert(hs_contains(set, 987654321));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 0], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(!hs_contains(set, 987654321));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[sum], {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 101; i <= 200; i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 1; i <= 300; i++)
|
||||
if (hs_contains(set, i))
|
||||
sum += i;
|
||||
|
||||
cmc_assert_equals(size_t, 15050, sum);
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(hs_empty(set));
|
||||
|
||||
cmc_assert(hs_insert(set, 1));
|
||||
|
||||
cmc_assert(!hs_empty(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full, {
|
||||
hashset *set = hs_new(cmc_hashtable_primes[0], 0.99999, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
|
||||
|
||||
for (size_t i = 0; i < hs_capacity(set); i++)
|
||||
cmc_assert(hs_insert(set, i));
|
||||
|
||||
cmc_assert(hs_full(set));
|
||||
|
||||
cmc_assert(hs_insert(set, 10000));
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[1], hs_capacity(set));
|
||||
|
||||
cmc_assert(!hs_full(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(count, {
|
||||
hashset *set = hs_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 1; i < 100; i++)
|
||||
{
|
||||
cmc_assert(hs_insert(set, i));
|
||||
cmc_assert_equals(size_t, i, hs_count(set));
|
||||
}
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity, {
|
||||
hashset *set = hs_new(2500, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hs_capacity(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity[small], {
|
||||
hashset *set = hs_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(load, {
|
||||
hashset *set = hs_new(1, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hs_load(set));
|
||||
|
||||
hs_free(set, NULL);
|
||||
});
|
||||
});
|
||||
+112
-12
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/heap.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/heap.c"
|
||||
|
||||
CMC_CREATE_UNIT(heap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -13,16 +14,16 @@ CMC_CREATE_UNIT(heap_test, false, {
|
||||
cmc_assert_equals(size_t, 1000000, h_capacity(h));
|
||||
cmc_assert_equals(size_t, 0, h_count(h));
|
||||
|
||||
h_free(h);
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[edge_case capacity = 0], {
|
||||
heap *h = h_new(0, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], {
|
||||
heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, h);
|
||||
@@ -38,25 +39,124 @@ CMC_CREATE_UNIT(heap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, h_count(h));
|
||||
|
||||
h_clear(h);
|
||||
h_clear(h, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, h_count(h));
|
||||
cmc_assert_equals(size_t, 100, h_capacity(h));
|
||||
|
||||
h_free(h);
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], {
|
||||
heap *h = h_new(1, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
h_insert(h, i);
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, h_count(h));
|
||||
|
||||
h_free(h);
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert, {
|
||||
heap *h = h_new(100, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
cmc_assert(h_insert(h, 10));
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[item preservation], {
|
||||
heap *h = h_new(50, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 0; i < h_count(h); i++)
|
||||
sum += h->buffer[i];
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove, {
|
||||
heap *h = h_new(50, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
size_t r;
|
||||
cmc_assert(h_remove(h, &r));
|
||||
|
||||
cmc_assert_equals(size_t, 100, r);
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
heap *h = h_new(100, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
size_t _;
|
||||
cmc_assert(!h_remove(h, &_));
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[sorted], {
|
||||
heap *h = h_new(100, cmc_min_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
size_t r;
|
||||
size_t i = 0;
|
||||
size_t arr[100];
|
||||
while (!h_empty(h))
|
||||
{
|
||||
cmc_assert(h_remove(h, &r));
|
||||
|
||||
arr[i++] = r;
|
||||
}
|
||||
|
||||
cmc_assert_array_sorted_any(size_t, arr, cmp, 0, 99);
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek, {
|
||||
heap *h = h_new(100, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(h_insert(h, i));
|
||||
|
||||
cmc_assert_equals(size_t, 100, h_peek(h));
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek[count = 0], {
|
||||
heap *h = h_new(100, cmc_max_heap, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, h);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){0}, h_peek(h));
|
||||
|
||||
h_free(h, NULL);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/intervalheap.c"
|
||||
|
||||
CMC_CREATE_UNIT(intervalheap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
intervalheap *ih = ih_new(1000000, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
cmc_assert_not_equals(ptr, NULL, ih->buffer);
|
||||
cmc_assert_equals(size_t, 500000, ih_capacity(ih));
|
||||
cmc_assert_equals(size_t, 0, ih_count(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
intervalheap *ih = ih_new(0, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, ih);
|
||||
|
||||
if (ih)
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[capacity], {
|
||||
intervalheap *ih = ih_new(1, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
cmc_assert_equals(size_t, 1, ih_capacity(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
|
||||
ih = ih_new(2, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
cmc_assert_equals(size_t, 1, ih_capacity(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
|
||||
ih = ih_new(3, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
cmc_assert_equals(size_t, 2, ih_capacity(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
|
||||
ih = ih_new(4, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
cmc_assert_equals(size_t, 2, ih_capacity(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
intervalheap *ih = ih_new(UINT64_MAX, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, ih);
|
||||
|
||||
if (ih)
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count capacity], {
|
||||
intervalheap *ih = ih_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(ih_insert(ih, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, ih_count(ih));
|
||||
|
||||
ih_clear(ih, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, ih_count(ih));
|
||||
cmc_assert_equals(size_t, 50, ih_capacity(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
intervalheap *ih = ih_new(1, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(ih_insert(ih, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, ih_count(ih));
|
||||
cmc_assert_greater(size_t, 50, ih_capacity(ih) * 2);
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[count], {
|
||||
intervalheap *ih = ih_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
|
||||
cmc_assert(ih_insert(ih, 1));
|
||||
cmc_assert(ih_insert(ih, 0));
|
||||
|
||||
cmc_assert_equals(size_t, 2, ih_count(ih));
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[max min], {
|
||||
intervalheap *ih = ih_new(1, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ih);
|
||||
|
||||
cmc_assert(ih_insert(ih, 1));
|
||||
cmc_assert(ih_insert(ih, 0));
|
||||
|
||||
size_t min;
|
||||
size_t max;
|
||||
|
||||
cmc_assert(ih_min(ih, &min));
|
||||
cmc_assert(ih_max(ih, &max));
|
||||
|
||||
cmc_assert_equals(size_t, 0, min);
|
||||
cmc_assert_equals(size_t, 1, max);
|
||||
|
||||
ih_free(ih, NULL);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/linkedlist.c"
|
||||
|
||||
CMC_CREATE_UNIT(linkedlist_test, false, {
|
||||
@@ -11,7 +14,7 @@ CMC_CREATE_UNIT(linkedlist_test, false, {
|
||||
cmc_assert_equals(ptr, NULL, ll->head);
|
||||
cmc_assert_equals(ptr, NULL, ll->tail);
|
||||
|
||||
ll_free(ll);
|
||||
ll_free(ll, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count capacity], {
|
||||
@@ -24,23 +27,23 @@ CMC_CREATE_UNIT(linkedlist_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, ll_count(ll));
|
||||
|
||||
ll_clear(ll);
|
||||
ll_clear(ll, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, ll_count(ll));
|
||||
|
||||
ll_free(ll);
|
||||
ll_free(ll, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(clear[count = 0], {
|
||||
linkedlist *ll = ll_new();
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ll);
|
||||
|
||||
ll_clear(ll);
|
||||
ll_clear(ll, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, ll_count(ll));
|
||||
|
||||
ll_free(ll);
|
||||
ll_free(ll, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[count], {
|
||||
@@ -54,10 +57,10 @@ CMC_CREATE_UNIT(linkedlist_test, false, {
|
||||
cmc_assert_not_equals(ptr, NULL, ll->tail);
|
||||
cmc_assert_equals(size_t, 1, ll_count(ll));
|
||||
|
||||
ll_free(ll);
|
||||
ll_free(ll, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[item_preservation], {
|
||||
CMC_CREATE_TEST(push_front[item preservation], {
|
||||
linkedlist *ll = ll_new();
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, ll);
|
||||
@@ -68,7 +71,6 @@ CMC_CREATE_UNIT(linkedlist_test, false, {
|
||||
for (size_t i = 0; i < ll_count(ll); i++)
|
||||
cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1);
|
||||
|
||||
ll_free(ll);
|
||||
ll_free(ll, NULL);
|
||||
});
|
||||
|
||||
});
|
||||
+54
-51
@@ -1,5 +1,8 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/list.c"
|
||||
|
||||
CMC_CREATE_UNIT(list_test, false, {
|
||||
@@ -11,22 +14,22 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
cmc_assert_equals(size_t, 1000000, l_capacity(l));
|
||||
cmc_assert_equals(size_t, 0, l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
list *l = l_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, l);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
list *l = l_new(UINT64_MAX);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, l);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new_from[count item_preservation], {
|
||||
CMC_CREATE_TEST(new_from[count and item preservation], {
|
||||
size_t v[5];
|
||||
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
@@ -41,10 +44,10 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
cmc_assert_equals(size_t, i, l_get(l, i));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new_from[edge_case:size = 1], {
|
||||
CMC_CREATE_TEST(new_from[size = 1], {
|
||||
size_t a = 10;
|
||||
|
||||
size_t *values = &a;
|
||||
@@ -53,7 +56,7 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count capacity], {
|
||||
@@ -66,15 +69,15 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, l_count(l));
|
||||
|
||||
l_clear(l);
|
||||
l_clear(l, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, l_count(l));
|
||||
cmc_assert_equals(size_t, 100, l_capacity(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
list *l = l_new(1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -87,7 +90,7 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert_equals(size_t, i, l_get(l, i));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[count], {
|
||||
@@ -100,7 +103,7 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 250, l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[capacity], {
|
||||
@@ -113,10 +116,10 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_front[item_preservation], {
|
||||
CMC_CREATE_TEST(push_front[item preservation], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -127,10 +130,10 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
for (size_t i = 0; i < l_count(l); i++)
|
||||
cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[count], {
|
||||
CMC_CREATE_TEST(push_at[count], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -139,14 +142,14 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
cmc_assert(l_push_back(l, 249));
|
||||
|
||||
for (size_t i = 1; i < 249; i++)
|
||||
cmc_assert(l_push(l, i, l_count(l) - 1));
|
||||
cmc_assert(l_push_at(l, i, l_count(l) - 1));
|
||||
|
||||
cmc_assert_equals(size_t, 250, l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[capacity], {
|
||||
CMC_CREATE_TEST(push_at[capacity], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -155,14 +158,14 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
cmc_assert(l_push_back(l, 249));
|
||||
|
||||
for (size_t i = 1; i < 249; i++)
|
||||
cmc_assert(l_push(l, i, l_count(l) - 1));
|
||||
cmc_assert(l_push_at(l, i, l_count(l) - 1));
|
||||
|
||||
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[item_preservation], {
|
||||
CMC_CREATE_TEST(push_at[item preservation], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -171,12 +174,12 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
cmc_assert(l_push_back(l, 249));
|
||||
|
||||
for (size_t i = 1; i < 249; i++)
|
||||
cmc_assert(l_push(l, i, l_count(l) - 1));
|
||||
cmc_assert(l_push_at(l, i, l_count(l) - 1));
|
||||
|
||||
for (size_t i = 0; i < l_count(l); i++)
|
||||
cmc_assert_equals(size_t, l_get(l, i), i);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_back[count], {
|
||||
@@ -189,7 +192,7 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 250, l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_back[capacity], {
|
||||
@@ -202,10 +205,10 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_back[item_preservation], {
|
||||
CMC_CREATE_TEST(push_back[item preservation], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -216,7 +219,7 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
for (size_t i = 0; i < l_count(l); i++)
|
||||
cmc_assert_equals(size_t, l_get(l, i), i);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[count], {
|
||||
@@ -229,10 +232,10 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert(l_pop_front(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[item_preservation], {
|
||||
CMC_CREATE_TEST(pop_front[item preservation], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
@@ -245,26 +248,26 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
for (size_t i = 0; i < l_count(l); i++)
|
||||
cmc_assert_equals(size_t, l_get(l, i), i + 1);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(pop_front[count = 0], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(!l_pop_front(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(pop_front[count = 1], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(l_push_back(l, 10));
|
||||
cmc_assert(l_pop_front(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_front[buffer_clear], {
|
||||
@@ -278,58 +281,58 @@ CMC_CREATE_UNIT(list_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 0, l->buffer[1]);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(pop_at[count = 0], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(!l_pop(l, 1));
|
||||
cmc_assert(!l_pop_at(l, 1));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(pop_at[count = 1], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(l_push_back(l, 1));
|
||||
cmc_assert(l_pop(l, 0));
|
||||
cmc_assert(l_pop_at(l, 0));
|
||||
|
||||
cmc_assert_equals(size_t, 0, l->buffer[0]);
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[buffer_clear], {
|
||||
CMC_CREATE_TEST(pop_at[buffer_clear], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(l_push_back(l, 1));
|
||||
cmc_assert(l_push_back(l, 2));
|
||||
cmc_assert(l_push_back(l, 3));
|
||||
cmc_assert(l_pop(l, 1));
|
||||
cmc_assert(l_pop_at(l, 1));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_back[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(pop_back[count = 0], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(!l_pop_back(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_back[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(pop_back[count = 1], {
|
||||
list *l = l_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, l);
|
||||
cmc_assert(l_push_back(l, 10));
|
||||
cmc_assert(l_pop_back(l));
|
||||
|
||||
l_free(l);
|
||||
l_free(l, NULL);
|
||||
});
|
||||
})
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/multimap.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/multimap.c"
|
||||
|
||||
CMC_CREATE_UNIT(multimap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -13,17 +14,17 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
cmc_assert_equals(size_t, 0, mm_count(map));
|
||||
cmc_assert_greater_equals(size_t, (943722 / 0.8), mm_capacity(map));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
multimap *map = mm_new(0, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
multimap *map = mm_new(UINT64_MAX, 0.8, cmp, hash);
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
multimap *map = mm_new(UINT64_MAX, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, map);
|
||||
});
|
||||
@@ -38,11 +39,11 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, mm_count(map));
|
||||
|
||||
mm_clear(map);
|
||||
mm_clear(map, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, mm_count(map));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[count], {
|
||||
@@ -50,12 +51,12 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(mm_insert(map, i % 20, i % 20));
|
||||
|
||||
cmc_assert_equals(size_t, 200, mm_count(map));
|
||||
cmc_assert_equals(size_t, 100, mm_count(map));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count], {
|
||||
@@ -73,10 +74,10 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 140, mm_count(map));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
multimap *map = mm_new(100, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
@@ -85,10 +86,10 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
|
||||
cmc_assert(!mm_remove(map, 10, &r));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(remove[count = 1], {
|
||||
multimap *map = mm_new(100, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
@@ -98,41 +99,10 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
cmc_assert(mm_insert(map, 10, 11));
|
||||
cmc_assert(mm_remove(map, 10, &r));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert_if, {
|
||||
multimap *map = mm_new(100, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(mm_insert_if(map, i % 20, i, i % 2 == 0) || i % 2 != 0);
|
||||
|
||||
cmc_assert_equals(size_t, 50, mm_count(map));
|
||||
|
||||
mm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove_if, {
|
||||
multimap *map = mm_new(100, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(mm_insert(map, i % 20, i));
|
||||
|
||||
size_t r;
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(mm_remove_if(map, i % 20, &r, i % 2 == 0) || i % 2 != 0);
|
||||
|
||||
cmc_assert_equals(size_t, 50, mm_count(map));
|
||||
|
||||
mm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(get[key_ordering], {
|
||||
CMC_CREATE_TEST(get[key ordering], {
|
||||
multimap *map = mm_new(100, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
@@ -145,7 +115,22 @@ CMC_CREATE_UNIT(multimap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 100, mm_get(map, 10));
|
||||
|
||||
mm_free(map);
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(key_count, {
|
||||
multimap *map = mm_new(50, 0.8, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
for (size_t i = 0; i < 1000; i++)
|
||||
cmc_assert(mm_insert(map, i % 20, i % 20));
|
||||
|
||||
cmc_assert_equals(size_t, 1000, mm_count(map));
|
||||
|
||||
for (size_t i = 0; i < 20; i++)
|
||||
cmc_assert_equals(size_t, 50, mm_key_count(map, i));
|
||||
|
||||
mm_free(map, NULL);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/multiset.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/multiset.c"
|
||||
|
||||
CMC_CREATE_UNIT(multiset_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -13,17 +14,17 @@ CMC_CREATE_UNIT(multiset_test, false, {
|
||||
cmc_assert_equals(size_t, 0, ms_count(set));
|
||||
cmc_assert_greater_equals(size_t, ((size_t)(943722 / 0.6)), ms_capacity(set));
|
||||
|
||||
ms_free(set);
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
multiset *set = ms_new(0, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, set);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINTMAX_MAX], {
|
||||
multiset *set = ms_new(UINTMAX_MAX, 0.99, cmp, hash);
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
multiset *set = ms_new(UINT64_MAX, 0.99, cmp, hash);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, set);
|
||||
});
|
||||
@@ -38,11 +39,11 @@ CMC_CREATE_UNIT(multiset_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, ms_count(set));
|
||||
|
||||
ms_clear(set);
|
||||
ms_clear(set, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, ms_count(set));
|
||||
|
||||
ms_free(set);
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert[count cardinality multiplicity], {
|
||||
@@ -63,24 +64,88 @@ CMC_CREATE_UNIT(multiset_test, false, {
|
||||
for (size_t i = 0; i <= 3; i++)
|
||||
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
|
||||
|
||||
ms_free(set);
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(multiplicity, {
|
||||
CMC_CREATE_TEST(remove[count cardinality multiplicity], {
|
||||
multiset *set = ms_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(ms_insert(set, 1));
|
||||
cmc_assert(ms_insert(set, 2));
|
||||
cmc_assert(ms_insert(set, 2));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
|
||||
cmc_assert_equals(size_t, 3, ms_count(set));
|
||||
cmc_assert_equals(size_t, 6, ms_cardinality(set));
|
||||
|
||||
for (size_t i = 0; i <= 3; i++)
|
||||
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
|
||||
|
||||
cmc_assert(ms_remove(set, 1));
|
||||
cmc_assert(ms_remove(set, 2));
|
||||
cmc_assert(ms_remove(set, 3));
|
||||
|
||||
cmc_assert_equals(size_t, 2, ms_count(set));
|
||||
cmc_assert_equals(size_t, 3, ms_cardinality(set));
|
||||
|
||||
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0));
|
||||
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1));
|
||||
cmc_assert_equals(size_t, 1, ms_multiplicity_of(set, 2));
|
||||
cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 3));
|
||||
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove_all[count cardinality multiplicity], {
|
||||
multiset *set = ms_new(100, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
cmc_assert(ms_insert(set, 1));
|
||||
cmc_assert(ms_insert(set, 2));
|
||||
cmc_assert(ms_insert(set, 2));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
cmc_assert(ms_insert(set, 3));
|
||||
|
||||
cmc_assert_equals(size_t, 3, ms_count(set));
|
||||
cmc_assert_equals(size_t, 6, ms_cardinality(set));
|
||||
|
||||
for (size_t i = 0; i <= 3; i++)
|
||||
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
|
||||
|
||||
cmc_assert(ms_remove_all(set, 1));
|
||||
cmc_assert(ms_remove_all(set, 3));
|
||||
|
||||
cmc_assert_equals(size_t, 1, ms_count(set));
|
||||
cmc_assert_equals(size_t, 2, ms_cardinality(set));
|
||||
|
||||
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0));
|
||||
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1));
|
||||
cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 2));
|
||||
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 3));
|
||||
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(multiplicity, {
|
||||
multiset *set = ms_new(50, 0.6, cmp, hash);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
for (size_t i = 0; i < 1000; i++)
|
||||
cmc_assert(ms_insert(set, i % 20));
|
||||
|
||||
cmc_assert_equals(size_t, 20, ms_count(set));
|
||||
cmc_assert_equals(size_t, 100, ms_cardinality(set));
|
||||
cmc_assert_equals(size_t, 1000, ms_cardinality(set));
|
||||
|
||||
for (size_t i = 0; i < 20; i++)
|
||||
cmc_assert_equals(size_t, 5, ms_multiplicity_of(set, i));
|
||||
cmc_assert_equals(size_t, 50, ms_multiplicity_of(set, i));
|
||||
|
||||
ms_free(set);
|
||||
ms_free(set, NULL);
|
||||
});
|
||||
|
||||
});
|
||||
+356
-9
@@ -1,5 +1,8 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/queue.c"
|
||||
|
||||
CMC_CREATE_UNIT(queue_test, false, {
|
||||
@@ -12,16 +15,16 @@ CMC_CREATE_UNIT(queue_test, false, {
|
||||
cmc_assert_equals(size_t, 0, q_count(q));
|
||||
cmc_assert_not_equals(ptr, NULL, q->buffer);
|
||||
|
||||
q_free(q);
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
queue *q = q_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, q);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
queue *q = q_new(UINT64_MAX);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, q);
|
||||
@@ -37,15 +40,15 @@ CMC_CREATE_UNIT(queue_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, q_count(q));
|
||||
|
||||
q_clear(q);
|
||||
q_clear(q, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, q_count(q));
|
||||
cmc_assert_equals(size_t, 100, q_capacity(q));
|
||||
|
||||
q_free(q);
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
queue *q = q_new(1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
@@ -55,7 +58,351 @@ CMC_CREATE_UNIT(queue_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, q_count(q));
|
||||
|
||||
q_free(q);
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[item preservation], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 1; i <= 1200; i++)
|
||||
{
|
||||
q_enqueue(q, i);
|
||||
}
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
|
||||
sum += q->buffer[i];
|
||||
|
||||
cmc_assert_equals(size_t, 1200, q_count(q));
|
||||
cmc_assert_equals(size_t, 720600, sum);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(enqueue[count capacity], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
cmc_assert_equals(size_t, 150, q_count(q));
|
||||
cmc_assert_greater(size_t, 100, q_capacity(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(enqueue[item preservation], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 1; i <= 100; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
|
||||
{
|
||||
sum += q->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(dequeue[count capacity], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert(q_enqueue(q, 10));
|
||||
cmc_assert(q_dequeue(q));
|
||||
|
||||
cmc_assert_equals(size_t, 0, q_count(q));
|
||||
|
||||
cmc_assert(q_enqueue(q, 10));
|
||||
cmc_assert(q_dequeue(q));
|
||||
|
||||
cmc_assert_equals(size_t, 0, q_count(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(dequeue[item preservation], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 200; i > 0; i--)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(q_dequeue(q));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
|
||||
{
|
||||
sum += q->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek[count = 0], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
size_t r = q_peek(q);
|
||||
|
||||
cmc_assert_equals(size_t, (size_t){0}, r);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(peek[sum], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = 0; i <= 100; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
while (!q_empty(q))
|
||||
{
|
||||
size_t r = q_peek(q);
|
||||
|
||||
sum += r;
|
||||
|
||||
cmc_assert(q_dequeue(q));
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 5050, sum);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(q_contains(q, i, cmp));
|
||||
|
||||
q_clear(q, NULL);
|
||||
|
||||
for (size_t i = 1; i <= 20; i++)
|
||||
cmc_assert(!q_contains(q, i, cmp));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 0], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert(!q_contains(q, 10, cmp));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[count = 1], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert(!q_contains(q, 10, cmp));
|
||||
|
||||
cmc_assert(q_enqueue(q, 100));
|
||||
|
||||
cmc_assert(q_contains(q, 100, cmp));
|
||||
cmc_assert(!q_contains(q, 101, cmp));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert(q_empty(q));
|
||||
|
||||
cmc_assert(q_enqueue(q, 1));
|
||||
|
||||
cmc_assert(!q_empty(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert(!q_full(q));
|
||||
|
||||
for (size_t i = 0; i != q_capacity(q); i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
cmc_assert(q_full(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(count, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert_equals(size_t, 0, q_count(q));
|
||||
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
cmc_assert_equals(size_t, 100, q_count(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(capacity, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
cmc_assert_equals(size_t, 100, q_capacity(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(resize, {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
cmc_assert_equals(size_t, 150, q_count(q));
|
||||
cmc_assert(q_resize(q, q_count(q)));
|
||||
cmc_assert_equals(size_t, 150, q_capacity(q));
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(resize[item preservation], {
|
||||
queue *q = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, q);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
cmc_assert(q_enqueue(q, i));
|
||||
|
||||
cmc_assert(q_resize(q, q_count(q)));
|
||||
|
||||
size_t sum = 0;
|
||||
|
||||
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
|
||||
{
|
||||
sum += q->buffer[i];
|
||||
}
|
||||
|
||||
cmc_assert_equals(size_t, 11325, sum);
|
||||
|
||||
q_free(q, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(copy_of, {
|
||||
queue *d1 = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
cmc_assert(q_enqueue(d1, i));
|
||||
|
||||
queue *d2 = q_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
cmc_assert_equals(size_t, q_count(d1), q_count(d2));
|
||||
|
||||
for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++)
|
||||
{
|
||||
cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]);
|
||||
|
||||
i1 = (i1 + 1) % d1->capacity;
|
||||
i2 = (i2 + 1) % d2->capacity;
|
||||
}
|
||||
|
||||
q_free(d1, NULL);
|
||||
q_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals, {
|
||||
queue *d1 = q_new(100);
|
||||
queue *d2 = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
cmc_assert(q_enqueue(d1, i));
|
||||
cmc_assert(q_enqueue(d2, i));
|
||||
}
|
||||
|
||||
cmc_assert(q_equals(d1, d2, cmp));
|
||||
|
||||
q_free(d1, NULL);
|
||||
q_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals[from copy], {
|
||||
queue *d1 = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
for (size_t i = 1; i <= 150; i++)
|
||||
{
|
||||
cmc_assert(q_enqueue(d1, i));
|
||||
}
|
||||
|
||||
queue *d2 = q_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
cmc_assert(q_equals(d1, d2, cmp));
|
||||
|
||||
q_free(d1, NULL);
|
||||
q_free(d2, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(equals[count = 0], {
|
||||
queue *d1 = q_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d1);
|
||||
|
||||
queue *d2 = q_copy_of(d1, NULL);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, d2);
|
||||
|
||||
cmc_assert(q_equals(d1, d2, cmp));
|
||||
|
||||
q_free(d1, NULL);
|
||||
q_free(d2, NULL);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/sortedlist.c"
|
||||
|
||||
CMC_CREATE_UNIT(sortedlist_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
sortedlist *sl = sl_new(1000000, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
cmc_assert_not_equals(ptr, NULL, sl->buffer);
|
||||
cmc_assert_equals(size_t, 1000000, sl_capacity(sl));
|
||||
cmc_assert_equals(size_t, 0, sl_count(sl));
|
||||
cmc_assert_not_equals(ptr, NULL, sl->buffer);
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
sortedlist *sl = sl_new(0, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, sl);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
sortedlist *sl = sl_new(UINT64_MAX, cmp);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, sl);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count capacity], {
|
||||
sortedlist *sl = sl_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(sl_insert(sl, i));
|
||||
|
||||
cmc_assert_equals(size_t, 50, sl_count(sl));
|
||||
|
||||
sl_clear(sl, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, sl_count(sl));
|
||||
cmc_assert_equals(size_t, 100, sl_capacity(sl));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
sortedlist *sl = sl_new(1, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
for (size_t i = 0; i < 50; i++)
|
||||
cmc_assert(sl_insert(sl, i));
|
||||
|
||||
sl_sort(sl);
|
||||
|
||||
cmc_assert_equals(size_t, 50, sl_count(sl));
|
||||
cmc_assert_array_sorted_any(size_t, sl->buffer, cmp, 0, sl->count - 1);
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(insert, {
|
||||
sortedlist *sl = sl_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
cmc_assert(sl_insert(sl, 1));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove, {
|
||||
sortedlist *sl = sl_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
cmc_assert(sl_insert(sl, 32));
|
||||
|
||||
cmc_assert(sl_remove(sl, 0));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[count = 0], {
|
||||
sortedlist *sl = sl_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
cmc_assert(!sl_remove(sl, 0));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(remove[out of range], {
|
||||
sortedlist *sl = sl_new(100, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
cmc_assert(sl_insert(sl, 32));
|
||||
|
||||
cmc_assert(!sl_remove(sl, 2));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(indexof, {
|
||||
sortedlist *sl = sl_new(1, cmp);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, sl);
|
||||
|
||||
for (size_t i = 0; i < 20; i++)
|
||||
cmc_assert(sl_insert(sl, i % 10));
|
||||
|
||||
/* 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 */
|
||||
cmc_assert_equals(size_t, 4, sl_indexof(sl, 2, true));
|
||||
cmc_assert_equals(size_t, 5, sl_indexof(sl, 2, false));
|
||||
|
||||
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true));
|
||||
cmc_assert_equals(size_t, 1, sl_indexof(sl, 0, false));
|
||||
|
||||
cmc_assert(sl_remove(sl, 0));
|
||||
|
||||
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true));
|
||||
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, false));
|
||||
|
||||
cmc_assert(sl_remove(sl, 0));
|
||||
|
||||
cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, true));
|
||||
cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, false));
|
||||
|
||||
sl_free(sl, NULL);
|
||||
});
|
||||
});
|
||||
+64
-95
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/stack.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/stack.c"
|
||||
|
||||
CMC_CREATE_UNIT(stack_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -14,16 +15,16 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert_equals(size_t, 0, s_count(s));
|
||||
cmc_assert_not_equals(ptr, NULL, s->buffer);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
|
||||
CMC_CREATE_TEST(new[capacity = 0], {
|
||||
stack *s = s_new(0);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, s);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
|
||||
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
|
||||
stack *s = s_new(UINT64_MAX);
|
||||
|
||||
cmc_assert_equals(ptr, NULL, s);
|
||||
@@ -39,15 +40,15 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, s_count(s));
|
||||
|
||||
s_clear(s);
|
||||
s_clear(s, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, s_count(s));
|
||||
cmc_assert_equals(size_t, 100, s_capacity(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
|
||||
stack *s = s_new(1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -58,7 +59,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert_equals(size_t, 50, s_count(s));
|
||||
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[count], {
|
||||
@@ -71,7 +72,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 250, s_count(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[capacity], {
|
||||
@@ -84,10 +85,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push[item_preservation], {
|
||||
CMC_CREATE_TEST(push[item preservation], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -98,7 +99,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
for (size_t i = 0; i < s_count(s); i++)
|
||||
cmc_assert_equals(size_t, i, s->buffer[i]);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[count], {
|
||||
@@ -113,7 +114,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 249, s_count(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[capacity], {
|
||||
@@ -128,10 +129,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[item_preservation], {
|
||||
CMC_CREATE_TEST(pop[item preservation], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -145,48 +146,17 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
for (size_t i = 0; i < s_count(s); i++)
|
||||
cmc_assert_equals(size_t, i, s->buffer[i]);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(pop[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
|
||||
cmc_assert_equals(bool, false, s_pop(s));
|
||||
|
||||
s_free(s);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(push_if, {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
|
||||
for (size_t i = 0; i < 250; i++)
|
||||
s_push_if(s, i, i % 2 == 0);
|
||||
|
||||
for (size_t i = 0; i < s_count(s); i++)
|
||||
cmc_assert(s->buffer[i] % 2 == 0);
|
||||
|
||||
s_free(s);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(pop_if, {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
|
||||
for (size_t i = 0; i < 250; i++)
|
||||
{
|
||||
s_push(s, i);
|
||||
s_pop_if(s, s_top(s) % 2 == 0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < s_count(s); i++)
|
||||
cmc_assert_not_equals(uint32_t, 0, s->buffer[i] % 2);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(top, {
|
||||
@@ -202,10 +172,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 247, s_top(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(top[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(top[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -214,12 +184,12 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_pop(s));
|
||||
|
||||
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
|
||||
cmc_assert_equals(size_t, (size_t){0}, s_top(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(top[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(top[count = 1], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -228,7 +198,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert_equals(size_t, 1, s_count(s));
|
||||
cmc_assert_equals(size_t, 10, s_top(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains, {
|
||||
@@ -242,17 +212,17 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
for (size_t i = 0; i < 150; i++)
|
||||
cmc_assert(s_contains(s, i, cmp));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(contains[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(contains[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
|
||||
cmc_assert_equals(bool, false, s_contains(s, 10, cmp));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty, {
|
||||
@@ -262,7 +232,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_empty(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(empty[after_io], {
|
||||
@@ -274,7 +244,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert(s_pop(s));
|
||||
cmc_assert(s_empty(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full, {
|
||||
@@ -287,10 +257,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_full(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
|
||||
CMC_CREATE_TEST(full[capacity = 1], {
|
||||
stack *s = s_new(1);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -299,7 +269,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_full(s));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_alloc, {
|
||||
@@ -312,10 +282,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert_not_equals(ptr, NULL, iter);
|
||||
|
||||
s_iter_free(iter);
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_init[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(iter_init[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -329,10 +299,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert(iter.start);
|
||||
cmc_assert(iter.end);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_start[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(iter_start[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -343,10 +313,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_iter_start(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_end[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(iter_end[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -357,7 +327,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert(s_iter_end(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration, {
|
||||
@@ -384,7 +354,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 40200, total);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[while loop], {
|
||||
@@ -414,10 +384,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 40200, total);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[edge_case:count = 1], {
|
||||
CMC_CREATE_TEST(iteration[count = 1], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -437,10 +407,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 20, total);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[edge_case:count = capacity], {
|
||||
CMC_CREATE_TEST(iteration[count = capacity], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -466,7 +436,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 2000, total);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], {
|
||||
@@ -501,10 +471,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
cmc_assert_equals(bool, it1.start, it2.start);
|
||||
cmc_assert_equals(bool, it1.end, it2.end);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[boundaries:count = 0], {
|
||||
CMC_CREATE_TEST(iteration[boundaries count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -520,10 +490,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(bool, false, s_iter_prev(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iteration[boundaries:count > 0], {
|
||||
CMC_CREATE_TEST(iteration[boundaries count > 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -542,10 +512,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(bool, false, s_iter_prev(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_value[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(iter_value[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -554,12 +524,12 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
s_iter_init(&iter, s);
|
||||
|
||||
cmc_assert_equals(size_t, s_impl_default_value(), s_iter_value(&iter));
|
||||
cmc_assert_equals(size_t, (size_t){0}, s_iter_value(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(iter_rvalue[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(iter_rvalue[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -570,7 +540,7 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(ptr, NULL, s_iter_rvalue(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(index, {
|
||||
@@ -585,12 +555,12 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
size_t total = 0;
|
||||
|
||||
for (stack_iter it = s->it_start(s); false; )
|
||||
for (stack_iter it = s->it_start(s); false;)
|
||||
{
|
||||
cmc_assert_equals(size_t, 0, s_iter_index(&it));
|
||||
}
|
||||
|
||||
for (stack_iter it = s->it_start(s); false; )
|
||||
for (stack_iter it = s->it_start(s); false;)
|
||||
{
|
||||
cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it));
|
||||
}
|
||||
@@ -609,10 +579,10 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 90, total);
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(index[edge_case:count = 0], {
|
||||
CMC_CREATE_TEST(index[count = 0], {
|
||||
stack *s = s_new(100);
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, s);
|
||||
@@ -622,7 +592,6 @@ CMC_CREATE_UNIT(stack_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 0, s_iter_index(&iter));
|
||||
|
||||
s_free(s);
|
||||
s_free(s, NULL);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/treemap.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/treemap.c"
|
||||
|
||||
CMC_CREATE_UNIT(treemap_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -10,7 +11,7 @@ CMC_CREATE_UNIT(treemap_test, false, {
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, map);
|
||||
|
||||
tm_free(map);
|
||||
tm_free(map, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count], {
|
||||
@@ -23,12 +24,11 @@ CMC_CREATE_UNIT(treemap_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, tm_count(map));
|
||||
|
||||
tm_clear(map);
|
||||
tm_clear(map, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, tm_count(map));
|
||||
cmc_assert_equals(ptr, NULL, map->root);
|
||||
|
||||
tm_free(map);
|
||||
tm_free(map, NULL);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "utl/assert.h"
|
||||
#include "utl/test.h"
|
||||
#include "../src/treeset.c"
|
||||
|
||||
#include "utl.c"
|
||||
#include <utl/assert.h>
|
||||
#include <utl/log.h>
|
||||
#include <utl/test.h>
|
||||
|
||||
#include "../src/treeset.c"
|
||||
|
||||
CMC_CREATE_UNIT(treeset_test, false, {
|
||||
CMC_CREATE_TEST(new, {
|
||||
@@ -10,7 +11,7 @@ CMC_CREATE_UNIT(treeset_test, false, {
|
||||
|
||||
cmc_assert_not_equals(ptr, NULL, set);
|
||||
|
||||
ts_free(set);
|
||||
ts_free(set, NULL);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(clear[count], {
|
||||
@@ -23,12 +24,11 @@ CMC_CREATE_UNIT(treeset_test, false, {
|
||||
|
||||
cmc_assert_equals(size_t, 50, ts_count(set));
|
||||
|
||||
ts_clear(set);
|
||||
ts_clear(set, NULL);
|
||||
|
||||
cmc_assert_equals(size_t, 0, ts_count(set));
|
||||
cmc_assert_equals(ptr, NULL, set->root);
|
||||
|
||||
ts_free(set);
|
||||
ts_free(set, NULL);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -3,6 +3,7 @@
|
||||
#define CMC_UNIT_TEST_UTL__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cmc/hashmap.h>
|
||||
|
||||
int cmp(size_t a, size_t b)
|
||||
{
|
||||
@@ -20,4 +21,24 @@ size_t hash(size_t a)
|
||||
return a;
|
||||
}
|
||||
|
||||
size_t numhash(size_t a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
size_t hashcapminus1(size_t a)
|
||||
{
|
||||
return cmc_hashtable_primes[0] - 1;
|
||||
}
|
||||
|
||||
size_t hashcapminus4(size_t a)
|
||||
{
|
||||
return cmc_hashtable_primes[0] - 1;
|
||||
}
|
||||
|
||||
size_t hash0(size_t a)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CMC_UNIT_TEST_UTL__ */
|
||||
Reference in new issue
Block a user