Redone tests

./codecov is a stalled version for code coverage. It will be merged with main when the library is done with breaking changes
This commit is contained in:
Leonardo committed 2019-09-28 14:58:10 -03:00
1 parent dea77b5ca2
commit 4f755f0915
46 files changed
+2222 -237

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label
CVFLAGS = --coverage -O0
INCLUDE = ../../src/
main: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c
dev: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
rm *.gcda *.gcno *.exe
windev: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
del *.gcda *.gcno *.exe
FORCE:
+7
View File
@@ -0,0 +1,7 @@
# codecov
In order to provide a good code coverage, all macros have been expanded and added to `src/*.c`.
* `src` - Since gcov fails to detect code that was expanded by macro, all collections where manually expanded and dumped into their respective source files;
* `unt` - Unit Tests;
* `main.c` - Where all tests are compiled together and called by main().
+35
View File
@@ -0,0 +1,35 @@
#include "unt/deque.c"
#include "unt/hashmap.c"
#include "unt/hashset.c"
#include "unt/heap.c"
#include "unt/linkedlist.c"
#include "unt/list.c"
#include "unt/queue.c"
#include "unt/stack.c"
#include "unt/treemap.c"
#include "unt/treeset.c"
#include "unt/multimap.c"
#include "unt/multiset.c"
int main(void)
{
uintmax_t failed = 0;
failed += deque_test();
failed += hashmap_test();
failed += hashset_test();
failed += heap_test();
failed += linkedlist_test();
failed += list_test();
failed += queue_test();
failed += stack_test();
failed += treemap_test();
failed += treeset_test();
/* ext */
failed += multimap_test();
failed += multiset_test();
return failed;
}
+293
View File
@@ -0,0 +1,293 @@
#include "cmc/deque.h"
//DEQUE_GENERATE(d, deque, , size_t)
typedef struct deque_s
{
size_t *buffer;
size_t capacity;
size_t count;
size_t front;
size_t back;
struct deque_iter_s (*it_start)(struct deque_s *);
struct deque_iter_s (*it_end)(struct deque_s *);
} deque, *deque_ptr;
typedef struct deque_iter_s
{
struct deque_s *target;
size_t cursor;
size_t index;
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);
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_);
size_t d_count(deque *_deque_);
size_t d_capacity(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);
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);
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;
deque *_deque_ = malloc(sizeof(deque));
if (!_deque_)
return NULL;
_deque_->buffer = malloc(sizeof(size_t) * capacity);
if (!_deque_->buffer)
{
free(_deque_);
return NULL;
}
memset(_deque_->buffer, 0, sizeof(size_t) * capacity);
_deque_->capacity = capacity;
_deque_->count = 0;
_deque_->front = 0;
_deque_->back = 0;
_deque_->it_start = d_impl_it_start;
_deque_->it_end = d_impl_it_end;
return _deque_;
}
void d_clear(deque *_deque_)
{
memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity);
_deque_->count = 0;
_deque_->front = 0;
_deque_->back = 0;
}
void d_free(deque *_deque_)
{
free(_deque_->buffer);
free(_deque_);
}
bool d_push_front(deque *_deque_, size_t element)
{
if (d_full(_deque_))
{
if (!d_impl_grow(_deque_))
return false;
}
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1;
_deque_->buffer[_deque_->front] = element;
_deque_->count++;
return true;
}
bool d_push_back(deque *_deque_, size_t element)
{
if (d_full(_deque_))
{
if (!d_impl_grow(_deque_))
return false;
}
_deque_->buffer[_deque_->back] = element;
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1;
_deque_->count++;
return true;
}
bool d_pop_front(deque *_deque_)
{
if (d_empty(_deque_))
return false;
_deque_->buffer[_deque_->front] = d_impl_default_value();
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1;
_deque_->count--;
return true;
}
bool d_pop_back(deque *_deque_)
{
if (d_empty(_deque_))
return false;
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1;
_deque_->buffer[_deque_->back] = d_impl_default_value();
_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;
}
size_t d_front(deque *_deque_)
{
if (d_empty(_deque_))
return d_impl_default_value();
return _deque_->buffer[_deque_->front];
}
size_t d_back(deque *_deque_)
{
if (d_empty(_deque_))
return d_impl_default_value();
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))
{
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++)
{
if (comparator(_deque_->buffer[i], element) == 0)
return true;
}
return false;
}
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; }
deque_iter *d_iter_new(deque *target)
{
deque_iter *iter = malloc(sizeof(deque_iter));
if (!iter)
return NULL;
d_iter_init(iter, target);
return iter;
}
void d_iter_free(deque_iter *iter) { free(iter); }
void d_iter_init(deque_iter *iter, deque *target)
{
iter->target = target;
iter->cursor = target->front;
iter->index = 0;
iter->start = true;
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; }
void d_iter_to_start(deque_iter *iter)
{
iter->cursor = iter->target->front;
iter->index = 0;
iter->start = true;
iter->end = d_empty(iter->target);
}
void d_iter_to_end(deque_iter *iter)
{
if (d_empty(iter->target))
iter->cursor = 0;
else
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1;
iter->index = iter->target->count - 1;
iter->start = d_empty(iter->target);
iter->end = true;
}
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
{
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
iter->index++;
}
return true;
}
bool d_iter_prev(deque_iter *iter)
{
if (iter->start)
return false;
iter->end = d_empty(iter->target);
if (iter->index == 0)
iter->start = true;
else
{
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
iter->index--;
}
return true;
}
size_t d_iter_value(deque_iter *iter)
{
if (d_empty(iter->target))
return d_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *d_iter_rvalue(deque_iter *iter)
{
if (d_empty(iter->target))
return NULL;
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;
d_iter_init(&iter, _deque_);
return iter;
}
static deque_iter d_impl_it_end(deque *_deque_)
{
deque_iter iter;
d_iter_init(&iter, _deque_);
d_iter_to_end(&iter);
return iter;
}
+438
View File
@@ -0,0 +1,438 @@
#include "cmc/hashmap.h"
//HASHMAP_GENERATE(hm, hashmap, , size_t, size_t)
typedef struct hashmap_s
{
struct hashmap_entry_s *buffer;
size_t capacity;
size_t count;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct hashmap_iter_s (*it_start)(struct hashmap_s *);
struct hashmap_iter_s (*it_end)(struct hashmap_s *);
} hashmap, *hashmap_ptr;
typedef struct hashmap_entry_s
{
size_t key;
size_t value;
size_t dist;
enum cmc_entry_state_e state;
} hashmap_entry, *hashmap_entry_ptr;
typedef struct hashmap_iter_s
{
struct hashmap_s *target;
size_t cursor;
size_t index;
size_t first;
size_t last;
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);
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_);
size_t hm_count(hashmap *_map_);
size_t hm_capacity(hashmap *_map_);
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);
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);
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_);
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;
size_t real_capacity = hm_impl_calculate_size(capacity / load);
hashmap *_map_ = malloc(sizeof(hashmap));
if (!_map_)
return NULL;
_map_->buffer = malloc(sizeof(hashmap_entry) * real_capacity);
if (!_map_->buffer)
{
free(_map_);
return NULL;
}
memset(_map_->buffer, 0, sizeof(hashmap_entry) * real_capacity);
_map_->count = 0;
_map_->capacity = real_capacity;
_map_->load = load;
_map_->cmp = compare;
_map_->hash = hash;
_map_->it_start = hm_impl_it_start;
_map_->it_end = hm_impl_it_end;
return _map_;
}
void hm_clear(hashmap *_map_)
{
memset(_map_->buffer, 0, sizeof(hashmap_entry) * _map_->capacity);
_map_->count = 0;
}
void hm_free(hashmap *_map_)
{
free(_map_->buffer);
free(_map_);
}
bool hm_insert(hashmap *_map_, size_t key, size_t value)
{
if ((double)_map_->capacity * _map_->load <= (double)_map_->count)
{
if (!hm_impl_grow(_map_))
return false;
}
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 (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->key = key;
target->value = value;
target->dist = original_pos - pos;
target->state = CMC_ES_FILLED;
}
else
{
while (true)
{
pos++;
target = &(_map_->buffer[pos % _map_->capacity]);
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->key = key;
target->value = value;
target->dist = pos - original_pos;
target->state = CMC_ES_FILLED;
break;
}
else if (target->dist < original_pos - pos)
{
size_t tmp_k = target->key;
size_t tmp_v = target->value;
size_t tmp_dist = target->dist;
target->key = key;
target->value = value;
target->dist = pos - original_pos;
key = tmp_k;
value = tmp_v;
original_pos = pos - tmp_dist;
}
}
}
_map_->count++;
return true;
}
bool hm_remove(hashmap *_map_, size_t key, size_t *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();
result->dist = 0;
result->state = CMC_ES_DELETED;
_map_->count--;
return true;
}
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)
{
if (hm_empty(_map_))
return false;
hashmap_iter iter;
for (hm_iter_init(&iter, _map_); !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)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) > 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
bool hm_min(hashmap *_map_, size_t *key, size_t *value)
{
if (hm_empty(_map_))
return false;
hashmap_iter iter;
for (hm_iter_init(&iter, _map_); !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)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) < 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
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 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 &(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; }
size_t hm_count(hashmap *_map_) { return _map_->count; }
size_t hm_capacity(hashmap *_map_) { return _map_->capacity; }
cmc_string hm_to_string(hashmap *_map_)
{
cmc_string str;
hashmap *m_ = _map_;
const char *name = "hashmap";
snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash);
return str;
}
hashmap_iter *hm_iter_new(hashmap *target)
{
hashmap_iter *iter = malloc(sizeof(hashmap_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = hm_empty(target);
if (!hm_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i].state == CMC_ES_FILLED)
{
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1].state == CMC_ES_FILLED)
{
iter->last = i - 1;
break;
}
}
}
}
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);
}
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;
}
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)
{
iter->end = true;
return false;
}
iter->index++;
while (1)
{
iter->cursor++;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
iter->start = hm_empty(iter->target);
return true;
}
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)
{
iter->start = true;
return false;
}
iter->index--;
while (1)
{
iter->cursor--;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
iter->end = hm_empty(iter->target);
return true;
}
size_t hm_iter_key(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return hm_impl_default_key();
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 iter->target->buffer[iter->cursor].value;
}
size_t *hm_iter_rvalue(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return NULL;
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);
size_t pos = hash % _map_->capacity;
hashmap_entry *target = &(_map_->buffer[pos]);
while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED)
{
if (_map_->cmp(target->key, key) == 0)
return target;
pos++;
target = &(_map_->buffer[pos % _map_->capacity]);
}
return NULL;
}
static size_t hm_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 hashmap_iter hm_impl_it_start(hashmap *_map_)
{
hashmap_iter iter;
hm_iter_init(&iter, _map_);
return iter;
}
static hashmap_iter hm_impl_it_end(hashmap *_map_)
{
hashmap_iter iter;
hm_iter_init(&iter, _map_);
hm_iter_to_end(&iter);
return iter;
}
+512
View File
@@ -0,0 +1,512 @@
#include "cmc/hashset.h"
//HASHSET_GENERATE(hs, hashset, , size_t)
typedef struct hashset_s
{
struct hashset_entry_s *buffer;
size_t capacity;
size_t count;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct hashset_iter_s (*it_start)(struct hashset_s *);
struct hashset_iter_s (*it_end)(struct hashset_s *);
} hashset, *hashset_ptr;
typedef struct hashset_entry_s
{
size_t value;
size_t dist;
enum cmc_entry_state_e state;
} hashset_entry, *hashset_entry_ptr;
typedef struct hashset_iter_s
{
struct hashset_s *target;
size_t cursor;
size_t index;
size_t first;
size_t last;
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_);
size_t hs_count(hashset *_set_);
size_t hs_capacity(hashset *_set_);
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_);
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);
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);
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_);
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;
size_t real_capacity = hs_impl_calculate_size(capacity / load);
hashset *_set_ = malloc(sizeof(hashset));
if (!_set_)
return NULL;
_set_->buffer = malloc(sizeof(hashset_entry) * real_capacity);
if (!_set_->buffer)
{
free(_set_);
return NULL;
}
memset(_set_->buffer, 0, sizeof(hashset_entry) * real_capacity);
_set_->count = 0;
_set_->capacity = real_capacity;
_set_->load = load;
_set_->cmp = compare;
_set_->hash = hash;
_set_->it_start = hs_impl_it_start;
_set_->it_end = hs_impl_it_end;
return _set_;
}
void hs_clear(hashset *_set_)
{
memset(_set_->buffer, 0, sizeof(hashset_entry) * _set_->capacity);
_set_->count = 0;
}
void hs_free(hashset *_set_)
{
free(_set_->buffer);
free(_set_);
}
bool hs_insert(hashset *_set_, size_t element)
{
if ((double)_set_->capacity * _set_->load <= (double)_set_->count)
{
if (!hs_impl_grow(_set_))
return false;
}
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 (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->value = element;
target->dist = pos - original_pos;
target->state = CMC_ES_FILLED;
}
else
{
while (true)
{
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->value = element;
target->dist = pos - original_pos;
target->state = CMC_ES_FILLED;
break;
}
else if (target->dist < pos - original_pos)
{
size_t tmp = target->value;
size_t tmp_dist = target->dist;
target->value = element;
target->dist = pos - original_pos;
element = tmp;
original_pos = pos - tmp_dist;
}
}
}
_set_->count++;
return true;
}
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();
result->dist = 0;
result->state = CMC_ES_DELETED;
_set_->count--;
return true;
}
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)
{
if (hs_empty(_set_))
return false;
hashset_iter iter;
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) > 0)
*value = result;
}
return true;
}
bool hs_min(hashset *_set_, size_t *value)
{
if (hs_empty(_set_))
return false;
hashset_iter iter;
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) < 0)
*value = result;
}
return true;
}
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; }
size_t hs_count(hashset *_set_) { return _set_->count; }
size_t hs_capacity(hashset *_set_) { return _set_->capacity; }
cmc_string hs_to_string(hashset *_set_)
{
cmc_string str;
hashset *s_ = _set_;
const char *name = "hashset";
snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash);
return str;
}
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;
hashset_iter iter1, iter2;
hs_iter_init(&iter1, _set1_);
hs_iter_init(&iter2, _set2_);
for (hs_iter_to_start(&iter1); !hs_iter_end(&iter1); hs_iter_next(&iter1))
{
hs_insert(_set_r_, hs_iter_value(&iter1));
}
for (hs_iter_to_start(&iter2); !hs_iter_end(&iter2); hs_iter_next(&iter2))
{
hs_insert(_set_r_, hs_iter_value(&iter2));
}
return _set_r_;
}
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;
hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
hashset_iter iter;
hs_iter_init(&iter, _set_A_);
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)
hs_insert(_set_r_, value);
}
return _set_r_;
}
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;
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)
hs_insert(_set_r_, value);
}
return _set_r_;
}
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;
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)
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)
hs_insert(_set_r_, value);
}
return _set_r_;
}
bool hs_is_subset(hashset *_set1_, hashset *_set2_)
{
if (hs_count(_set1_) > hs_count(_set2_))
return false;
if (hs_empty(_set1_))
return true;
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 true;
}
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;
if (hs_empty(_set1_))
{
if (!hs_empty(_set2_))
return true;
else
return false;
}
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 true;
}
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;
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 true;
}
hashset_iter *hs_iter_new(hashset *target)
{
hashset_iter *iter = malloc(sizeof(hashset_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = hs_empty(target);
if (!hs_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i].state == CMC_ES_FILLED)
{
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1].state == CMC_ES_FILLED)
{
iter->last = i - 1;
break;
}
}
}
}
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);
}
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;
}
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
{
iter->index++;
while (1)
{
iter->cursor++;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
}
iter->start = hs_empty(iter->target);
return true;
}
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
{
iter->index--;
while (1)
{
iter->cursor--;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
}
iter->end = hs_empty(iter->target);
return true;
}
size_t hs_iter_value(hashset_iter *iter)
{
if (hs_empty(iter->target))
return hs_impl_default_value();
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);
size_t pos = hash % _set_->capacity;
hashset_entry *target = &(_set_->buffer[pos]);
while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED)
{
if (_set_->cmp(target->value, element) == 0)
return target;
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
}
return NULL;
}
static size_t hs_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 hashset_iter hs_impl_it_start(hashset *_set_)
{
hashset_iter iter;
hs_iter_init(&iter, _set_);
return iter;
}
static hashset_iter hs_impl_it_end(hashset *_set_)
{
hashset_iter iter;
hs_iter_init(&iter, _set_);
hs_iter_to_end(&iter);
return iter;
}
+285
View File
@@ -0,0 +1,285 @@
#include "cmc/heap.h"
//HEAP_GENERATE(h, heap, , size_t)
typedef struct heap_s
{
size_t *buffer;
size_t capacity;
size_t count;
enum cmc_heap_order_e HO;
int (*cmp)(size_t, size_t);
struct heap_iter_s (*it_start)(struct heap_s *);
struct heap_iter_s (*it_end)(struct heap_s *);
} heap, *heap_ptr;
typedef struct heap_iter_s
{
struct heap_s *target;
size_t cursor;
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);
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_);
size_t h_count(heap *_heap_);
size_t h_capacity(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);
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);
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 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;
if (HO != cmc_min_heap && HO != cmc_max_heap)
return NULL;
heap *_heap_ = malloc(sizeof(heap));
if (!_heap_)
return NULL;
_heap_->buffer = malloc(sizeof(size_t) * capacity);
if (!_heap_->buffer)
{
free(_heap_);
return NULL;
}
memset(_heap_->buffer, 0, sizeof(size_t) * capacity);
_heap_->capacity = capacity;
_heap_->count = 0;
_heap_->HO = HO;
_heap_->cmp = compare;
_heap_->it_start = h_impl_it_start;
_heap_->it_end = h_impl_it_end;
return _heap_;
}
void h_clear(heap *_heap_)
{
memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity);
_heap_->count = 0;
}
void h_free(heap *_heap_)
{
free(_heap_->buffer);
free(_heap_);
}
bool h_insert(heap *_heap_, size_t element)
{
if (h_full(_heap_))
{
if (!h_impl_grow(_heap_))
return false;
}
if (_heap_->count == 0)
{
_heap_->buffer[_heap_->count++] = element;
return true;
}
_heap_->buffer[_heap_->count++] = element;
if (!h_impl_float_up(_heap_, _heap_->count - 1))
return false;
return true;
}
bool h_remove(heap *_heap_, size_t *result)
{
if (h_empty(_heap_))
return false;
*result = _heap_->buffer[0];
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1];
_heap_->buffer[_heap_->count - 1] = h_impl_default_value();
_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;
}
size_t h_peek(heap *_heap_)
{
if (h_empty(_heap_))
return h_impl_default_value();
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)
{
for (size_t i = 0; i < _heap_->count; i++)
{
if (_heap_->cmp(_heap_->buffer[i], element) == 0)
return true;
}
return false;
}
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; }
heap_iter *h_iter_new(heap *target)
{
heap_iter *iter = malloc(sizeof(heap_iter));
if (!iter)
return NULL;
h_iter_init(iter, target);
return iter;
}
void h_iter_free(heap_iter *iter) { free(iter); }
void h_iter_init(heap_iter *iter, heap *target)
{
iter->target = target;
iter->cursor = 0;
iter->start = true;
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; }
void h_iter_to_start(heap_iter *iter)
{
iter->cursor = 0;
iter->start = true;
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;
}
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;
}
bool h_iter_prev(heap_iter *iter)
{
if (iter->start)
return false;
iter->end = false;
if (iter->cursor == 0)
iter->start = true;
else
iter->cursor--;
return true;
}
size_t h_iter_value(heap_iter *iter)
{
if (h_empty(iter->target))
return h_impl_default_value();
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)
{
size_t C = index;
size_t child = _heap_->buffer[C];
size_t parent = _heap_->buffer[(index - 1) / 2];
int mod = _heap_->HO;
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;
child = _heap_->buffer[C];
parent = _heap_->buffer[(index - 1) / 2];
}
return true;
}
static bool h_impl_float_down(heap *_heap_, size_t index)
{
int mod = _heap_->HO;
while (index < _heap_->count)
{
size_t L = 2 * index + 1;
size_t R = 2 * index + 2;
size_t C = index;
if (L < _heap_->count && _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0)
{
C = L;
}
if (R < _heap_->count && _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0)
{
C = R;
}
if (C != index)
{
size_t tmp = _heap_->buffer[index];
_heap_->buffer[index] = _heap_->buffer[C];
_heap_->buffer[C] = tmp;
index = C;
}
else
break;
}
return true;
}
static heap_iter h_impl_it_start(heap *_heap_)
{
heap_iter iter;
h_iter_init(&iter, _heap_);
h_iter_to_start(&iter);
return iter;
}
static heap_iter h_impl_it_end(heap *_heap_)
{
heap_iter iter;
h_iter_init(&iter, _heap_);
h_iter_to_end(&iter);
return iter;
}
+481
View File
@@ -0,0 +1,481 @@
#include "cmc/linkedlist.h"
//LINKEDLIST_GENERATE(ll, linkedlist, , size_t)
typedef struct linkedlist_s
{
struct linkedlist_node_s *head;
struct linkedlist_node_s *tail;
size_t count;
struct linkedlist_iter_s (*it_start)(struct linkedlist_s *);
struct linkedlist_iter_s (*it_end)(struct linkedlist_s *);
} linkedlist, *linkedlist_ptr;
typedef struct linkedlist_node_s
{
size_t data;
struct linkedlist_node_s *next;
struct linkedlist_node_s *prev;
} linkedlist_node, *linkedlist_node_ptr;
typedef struct linkedlist_iter_s
{
struct linkedlist_s *target;
struct linkedlist_node_s *cursor;
size_t index;
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);
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_);
size_t ll_count(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_);
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);
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);
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;
_list_->count = 0;
_list_->head = NULL;
_list_->tail = NULL;
_list_->it_start = ll_impl_it_start;
_list_->it_end = ll_impl_it_end;
return _list_;
}
void ll_clear(linkedlist *_list_)
{
linkedlist_node *scan = _list_->head;
while (_list_->head != NULL)
{
_list_->head = _list_->head->next;
free(scan);
scan = _list_->head;
}
_list_->count = 0;
_list_->head = NULL;
_list_->tail = NULL;
}
void ll_free(linkedlist *_list_)
{
ll_clear(_list_);
free(_list_);
}
bool ll_push_front(linkedlist *_list_, size_t element)
{
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
if (ll_empty(_list_))
{
_list_->head = _node_;
_list_->tail = _node_;
}
else
{
_node_->next = _list_->head;
_list_->head->prev = _node_;
_list_->head = _node_;
}
_list_->count++;
return true;
}
bool ll_push(linkedlist *_list_, size_t element, size_t index)
{
if (index > _list_->count)
return false;
if (index == 0)
{
return ll_push_front(_list_, element);
}
else if (index == _list_->count)
{
return ll_push_back(_list_, element);
}
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
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;
}
bool ll_push_back(linkedlist *_list_, size_t element)
{
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
if (ll_empty(_list_))
{
_list_->head = _node_;
_list_->tail = _node_;
}
else
{
_node_->prev = _list_->tail;
_list_->tail->next = _node_;
_list_->tail = _node_;
}
_list_->count++;
return true;
}
bool ll_pop_front(linkedlist *_list_)
{
if (ll_empty(_list_))
return false;
linkedlist_node *_node_ = _list_->head;
_list_->head = _list_->head->next;
free(_node_);
if (_list_->head == NULL)
_list_->tail = NULL;
else
_list_->head->prev = NULL;
_list_->count--;
return true;
}
bool ll_pop(linkedlist *_list_, size_t index)
{
if (ll_empty(_list_))
return false;
if (index >= _list_->count)
return false;
if (index == 0)
{
return ll_pop_front(_list_);
}
else if (index == _list_->count - 1)
{
return ll_pop_back(_list_);
}
linkedlist_node *_node_ = ll_get_node(_list_, index);
if (!_node_)
return false;
_node_->next->prev = _node_->prev;
_node_->prev->next = _node_->next;
free(_node_);
_list_->count--;
return true;
}
bool ll_pop_back(linkedlist *_list_)
{
if (ll_empty(_list_))
return false;
linkedlist_node *_node_ = _list_->tail;
_list_->tail = _list_->tail->prev;
free(_node_);
if (_list_->tail == NULL)
_list_->head = NULL;
else
_list_->tail->next = NULL;
_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;
}
size_t ll_front(linkedlist *_list_)
{
if (ll_empty(_list_))
return ll_impl_default_value();
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();
linkedlist_node *scan = ll_get_node(_list_, index);
if (scan == NULL)
return ll_impl_default_value();
return scan->data;
}
size_t *ll_get_ref(linkedlist *_list_, size_t index)
{
if (index >= _list_->count)
return NULL;
if (ll_empty(_list_))
return NULL;
linkedlist_node *scan = ll_get_node(_list_, index);
if (scan == NULL)
return NULL;
return &(scan->data);
}
size_t ll_back(linkedlist *_list_)
{
if (ll_empty(_list_))
return ll_impl_default_value();
return _list_->tail->data;
}
bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t))
{
linkedlist_node *scan = _list_->head;
while (scan != NULL)
{
if (comparator(scan->data, element) == 0)
return true;
scan = scan->next;
}
return false;
}
bool ll_empty(linkedlist *_list_) { return _list_->count == 0; }
size_t ll_count(linkedlist *_list_) { return _list_->count; }
linkedlist_node *ll_new_node(size_t element)
{
linkedlist_node *_node_ = malloc(sizeof(linkedlist_node));
if (!_node_)
return NULL;
_node_->data = element;
_node_->next = NULL;
_node_->prev = NULL;
return _node_;
}
void ll_free_node(linkedlist_node *_node_) { free(_node_); }
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;
if (ll_empty(_list_))
return NULL;
linkedlist_node *_node_ = NULL;
if (index <= _list_->count / 2)
{
_node_ = _list_->head;
for (size_t i = 0; i < index; i++)
{
_node_ = _node_->next;
}
}
else
{
_node_ = _list_->tail;
for (size_t i = _list_->count - 1; i > index; i--)
{
_node_ = _node_->prev;
}
}
return _node_;
}
linkedlist_node *ll_tail(linkedlist *_list_) { return _list_->tail; }
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;
new_node->next = _node_->next;
if (_node_->next != NULL)
_node_->next->prev = new_node;
else
_owner_->tail = new_node;
new_node->prev = _node_;
_node_->next = new_node;
_owner_->count++;
return true;
}
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;
new_node->prev = _node_->prev;
if (_node_->prev != NULL)
_node_->prev->next = new_node;
else
_owner_->head = new_node;
new_node->next = _node_;
_node_->prev = new_node;
_owner_->count++;
return true;
}
bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->next == NULL)
return false;
linkedlist_node *tmp = _node_->next;
if (tmp->next != NULL)
{
_node_->next = _node_->next->next;
_node_->next->prev = _node_;
}
else
_owner_->tail = _node_;
free(tmp);
_owner_->count--;
return true;
}
bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->prev != NULL)
_node_->prev->next = _node_->next;
else
_owner_->head = _node_->next;
if (_node_->next != NULL)
_node_->next->prev = _node_->prev;
else
_owner_->tail = _node_->prev;
free(_node_);
_owner_->count--;
return true;
}
bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->prev == NULL)
return false;
linkedlist_node *tmp = _node_->prev;
if (tmp->prev != NULL)
{
_node_->prev = _node_->prev->prev;
_node_->prev->next = _node_;
}
else
_owner_->head = _node_;
free(tmp);
_owner_->count--;
return true;
}
linkedlist_node *ll_next_node(linkedlist_node *_node_) { return _node_->next; }
linkedlist_node *ll_prev_node(linkedlist_node *_node_) { return _node_->prev; }
linkedlist_iter *ll_iter_new(linkedlist *target)
{
linkedlist_iter *iter = malloc(sizeof(linkedlist_iter));
if (!iter)
return NULL;
ll_iter_init(iter, target);
return iter;
}
void ll_iter_free(linkedlist_iter *iter) { free(iter); }
void ll_iter_init(linkedlist_iter *iter, linkedlist *target)
{
iter->target = target;
iter->cursor = target->head;
iter->index = 0;
iter->start = true;
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; }
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);
}
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;
}
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
{
iter->cursor = iter->cursor->next;
iter->index++;
}
return true;
}
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
{
iter->cursor = iter->cursor->prev;
iter->index--;
}
return true;
}
size_t ll_iter_value(linkedlist_iter *iter)
{
if (ll_empty(iter->target))
return ll_impl_default_value();
return iter->cursor->data;
}
size_t *ll_iter_rvalue(linkedlist_iter *iter)
{
if (ll_empty(iter->target))
return NULL;
return &(iter->cursor->data);
}
size_t ll_iter_index(linkedlist_iter *iter) { return iter->index; }
linkedlist_node *ll_iter_node(linkedlist_iter *iter) { return iter->cursor; }
static linkedlist_iter ll_impl_it_start(linkedlist *_list_)
{
linkedlist_iter iter;
ll_iter_init(&iter, _list_);
ll_iter_to_start(&iter);
return iter;
}
static linkedlist_iter ll_impl_it_end(linkedlist *_list_)
{
linkedlist_iter iter;
ll_iter_init(&iter, _list_);
ll_iter_to_end(&iter);
return iter;
}
+424
View File
@@ -0,0 +1,424 @@
#include "cmc/list.h"
//LIST_GENERATE(l, list, , size_t)
typedef struct list_s
{
size_t *buffer;
size_t capacity;
size_t count;
struct list_iter_s (*it_start)(struct list_s *);
struct list_iter_s (*it_end)(struct list_s *);
} list, *list_ptr;
typedef struct list_iter_s
{
struct list_s *target;
size_t cursor;
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);
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_count(list *_list_);
bool l_fits(list *_list_, size_t size);
size_t l_capacity(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);
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);
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;
list *_list_ = malloc(sizeof(list));
if (!_list_)
return NULL;
_list_->buffer = malloc(capacity * sizeof(size_t));
if (!_list_->buffer)
{
free(_list_);
return NULL;
}
memset(_list_->buffer, 0, capacity * sizeof(size_t));
_list_->capacity = capacity;
_list_->count = 0;
_list_->it_start = l_impl_it_start;
_list_->it_end = l_impl_it_end;
return _list_;
}
list *l_new_from(size_t *elements, size_t size)
{
if (size == 0)
return NULL;
list *_list_ = l_new(size + size / 2);
if (!_list_)
return NULL;
memcpy(_list_->buffer, elements, size * sizeof(size_t));
_list_->count = size;
return _list_;
}
void l_clear(list *_list_)
{
memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity);
_list_->count = 0;
}
void l_free(list *_list_)
{
free(_list_->buffer);
free(_list_);
}
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_empty(_list_))
{
memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(size_t));
}
_list_->buffer[0] = element;
_list_->count++;
return true;
}
bool l_push(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);
}
if (l_full(_list_))
{
if (!l_impl_grow(_list_, _list_->count + 1))
return false;
}
memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t));
_list_->buffer[index] = element;
_list_->count++;
return true;
}
bool l_push_back(list *_list_, size_t element)
{
if (l_full(_list_))
{
if (!l_impl_grow(_list_, _list_->count + 1))
return false;
}
_list_->buffer[_list_->count++] = element;
return true;
}
bool l_pop_front(list *_list_)
{
if (l_empty(_list_))
return false;
memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(size_t));
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
bool l_pop(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_);
}
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t));
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
bool l_pop_back(list *_list_)
{
if (l_empty(_list_))
return false;
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
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)
{
if (size == 0)
return false;
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t));
memcpy(_list_->buffer, elements, size * sizeof(size_t));
_list_->count += size;
return true;
}
bool l_insert(list *_list_, size_t *elements, size_t size, size_t index)
{
if (size == 0 || index > _list_->count)
return false;
if (index == 0)
return l_prepend(_list_, elements, size);
else if (index == _list_->count)
return l_append(_list_, elements, size);
else
{
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
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;
}
bool l_append(list *_list_, size_t *elements, size_t size)
{
if (size == 0)
return false;
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
memcpy(_list_->buffer + _list_->count, elements, size * sizeof(size_t));
_list_->count += size;
return true;
}
bool l_remove(list *_list_, size_t from, size_t to)
{
if (from > to || to >= _list_->count)
return false;
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;
}
list *l_extract(list *_list_, size_t from, size_t to)
{
if (from > to || to >= _list_->count)
return false;
size_t length = to - from + 1;
list *result = l_new_from(_list_->buffer + from, length);
if (!result)
return NULL;
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;
return result;
}
size_t l_front(list *_list_)
{
if (l_empty(_list_))
return l_impl_default_value();
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 _list_->buffer[index];
}
size_t *l_get_ref(list *_list_, size_t index)
{
if (index >= _list_->count)
return NULL;
if (l_empty(_list_))
return NULL;
return &(_list_->buffer[index]);
}
size_t l_back(list *_list_)
{
if (l_empty(_list_))
return l_impl_default_value();
return _list_->buffer[_list_->count - 1];
}
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start)
{
if (from_start)
{
for (size_t i = 0; i < _list_->count; i++)
{
if (comparator(_list_->buffer[i], element) == 0)
return i;
}
}
else
{
for (size_t i = _list_->count; i > 0; i--)
{
if (comparator(_list_->buffer[i - 1], element) == 0)
return i - 1;
}
}
return _list_->count;
}
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 false;
}
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; }
size_t l_capacity(list *_list_) { return _list_->capacity; }
list_iter *l_iter_new(list *target)
{
list_iter *iter = malloc(sizeof(list_iter));
if (!iter)
return NULL;
l_iter_init(iter, target);
return iter;
}
void l_iter_free(list_iter *iter) { free(iter); }
void l_iter_init(list_iter *iter, list *target)
{
iter->target = target;
iter->cursor = 0;
iter->start = true;
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; }
void l_iter_to_start(list_iter *iter)
{
iter->cursor = 0;
iter->start = true;
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;
}
bool l_iter_next(list_iter *iter)
{
if (iter->end)
return false;
iter->start = l_empty(iter->target);
if (iter->cursor == iter->target->count - 1)
iter->end = true;
else
iter->cursor++;
return true;
}
bool l_iter_prev(list_iter *iter)
{
if (iter->start)
return false;
iter->end = l_empty(iter->target);
if (iter->cursor == 0)
iter->start = true;
else
iter->cursor--;
return true;
}
size_t l_iter_value(list_iter *iter)
{
if (l_empty(iter->target))
return l_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *l_iter_rvalue(list_iter *iter)
{
if (l_empty(iter->target))
return NULL;
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;
l_iter_init(&iter, _list_);
l_iter_to_start(&iter);
return iter;
}
static list_iter l_impl_it_end(list *_list_)
{
list_iter iter;
l_iter_init(&iter, _list_);
l_iter_to_end(&iter);
return iter;
}
+539
View File
@@ -0,0 +1,539 @@
#include "ext/multimap.h"
//MULTIMAP_GENERATE(mm, multimap, , size_t, size_t)
typedef struct multimap_s
{
struct multimap_entry_s *(*buffer)[2];
size_t capacity;
size_t count;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct multimap_iter_s (*it_start)(struct multimap_s *);
struct multimap_iter_s (*it_end)(struct multimap_s *);
} multimap, *multimap_ptr;
typedef struct multimap_entry_s
{
size_t key;
size_t value;
struct multimap_entry_s *next;
struct multimap_entry_s *prev;
} multimap_entry, *multimap_entry_ptr;
typedef struct multimap_iter_s
{
struct multimap_s *target;
struct multimap_entry_s *curr_entry;
size_t cursor;
size_t index;
size_t first;
size_t last;
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);
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_);
size_t mm_count(multimap *_map_);
size_t mm_capacity(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);
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);
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);
static multimap_iter mm_impl_it_start(multimap *_map_);
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;
size_t real_capacity = mm_impl_calculate_size(capacity / load);
multimap *_map_ = malloc(sizeof(multimap));
if (!_map_)
return NULL;
_map_->buffer = malloc(sizeof(multimap_entry_ptr[2]) * real_capacity);
if (!_map_->buffer)
{
free(_map_);
return NULL;
}
memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * real_capacity);
_map_->count = 0;
_map_->capacity = real_capacity;
_map_->load = load;
_map_->cmp = compare;
_map_->hash = hash;
return _map_;
}
void mm_clear(multimap *_map_)
{
size_t index = 0;
multimap_entry *scan;
while (index < _map_->capacity)
{
scan = _map_->buffer[index][0];
if (scan != NULL)
{
if (scan->next == NULL && scan->prev == NULL)
free(scan);
else
{
while (scan != NULL)
{
multimap_entry *tmp = scan;
scan = scan->next;
free(tmp);
}
}
}
index++;
}
memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * _map_->capacity);
_map_->count = 0;
}
void mm_free(multimap *_map_)
{
mm_clear(_map_);
free(_map_->buffer);
free(_map_);
}
bool mm_insert(multimap *_map_, size_t key, size_t value)
{
if ((double)_map_->capacity * _map_->load <= (double)_map_->count)
{
if (!mm_impl_grow(_map_))
return false;
}
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)
{
_map_->buffer[pos][0] = entry;
_map_->buffer[pos][1] = entry;
}
else
{
entry->prev = _map_->buffer[pos][1];
_map_->buffer[pos][1]->next = entry;
_map_->buffer[pos][1] = entry;
}
_map_->count++;
return true;
}
bool mm_remove(multimap *_map_, size_t key, size_t *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;
multimap_entry *entry = *head;
if (entry->next == NULL && entry->prev == NULL)
{
if (_map_->cmp(entry->key, key) == 0)
{
*head = NULL;
*tail = NULL;
*value = entry->value;
}
else
return false;
}
else
{
bool found = false;
while (entry != NULL)
{
if (_map_->cmp(entry->key, key) == 0)
{
if (*head == entry)
*head = entry->next;
if (*tail == entry)
*tail = entry->prev;
if (entry->prev != NULL)
entry->prev->next = entry->next;
if (entry->next != NULL)
entry->next->prev = entry->prev;
*value = entry->value;
found = true;
break;
}
else
entry = entry->next;
}
if (!found)
return false;
}
free(entry);
_map_->count--;
return true;
}
size_t mm_remove_all(multimap *_map_, size_t key)
{
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;
multimap_entry *entry = *head;
if (entry->next == NULL)
{
*head = NULL;
*tail = NULL;
free(entry);
total++;
}
else
{
while (entry != NULL)
{
if (_map_->cmp(entry->key, key) == 0)
{
if (*head == entry)
*head = entry->next;
if (*tail == entry)
*tail = entry->prev;
multimap_entry *temp = entry->next;
if (entry->prev != NULL)
entry->prev->next = entry->next;
if (entry->next != NULL)
entry->next->prev = entry->prev;
free(entry);
entry = temp;
total++;
}
else
entry = entry->next;
}
}
_map_->count -= total;
return total;
}
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)
{
if (mm_empty(_map_))
return false;
multimap_iter iter;
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
{
size_t result_key = mm_iter_key(&iter);
size_t result_value = mm_iter_value(&iter);
size_t index = mm_iter_index(&iter);
if (index == 0)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) > 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
bool mm_min(multimap *_map_, size_t *key, size_t *value)
{
if (mm_empty(_map_))
return false;
multimap_iter iter;
for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter))
{
size_t result_key = mm_iter_key(&iter);
size_t result_value = mm_iter_value(&iter);
size_t index = mm_iter_index(&iter);
if (index == 0)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) < 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
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 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 &(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; }
size_t mm_count(multimap *_map_) { return _map_->count; }
size_t mm_capacity(multimap *_map_) { return _map_->capacity; }
multimap_iter *mm_iter_new(multimap *target)
{
multimap_iter *iter = malloc(sizeof(multimap_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = mm_empty(target);
if (!mm_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i][0] != NULL)
{
iter->curr_entry = target->buffer[i][0];
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1][0] != NULL)
{
iter->last = i - 1;
break;
}
}
}
}
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];
}
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];
}
bool mm_iter_next(multimap_iter *iter)
{
if (iter->end)
return false;
if (iter->curr_entry->next != NULL)
{
iter->curr_entry = iter->curr_entry->next;
iter->index++;
}
else
{
if (iter->cursor == iter->last)
{
iter->end = true;
return false;
}
else
{
iter->cursor++;
while (iter->target->buffer[iter->cursor][0] == NULL)
iter->cursor++;
iter->curr_entry = iter->target->buffer[iter->cursor][0];
iter->index++;
}
}
iter->start = mm_empty(iter->target);
return true;
}
bool mm_iter_prev(multimap_iter *iter)
{
if (iter->start)
return false;
if (iter->curr_entry->prev != NULL)
{
iter->curr_entry = iter->curr_entry->prev;
iter->index--;
}
else
{
if (iter->cursor == iter->first)
{
iter->start = true;
return false;
}
else
{
iter->cursor--;
while (iter->target->buffer[iter->cursor][1] == NULL)
iter->cursor--;
iter->curr_entry = iter->target->buffer[iter->cursor][1];
iter->index--;
}
}
iter->end = mm_empty(iter->target);
return true;
}
size_t mm_iter_key(multimap_iter *iter)
{
if (mm_empty(iter->target))
return mm_impl_default_key();
return iter->curr_entry->key;
}
size_t mm_iter_value(multimap_iter *iter)
{
if (mm_empty(iter->target))
return mm_impl_default_value();
return iter->curr_entry->value;
}
size_t *mm_iter_rvalue(multimap_iter *iter)
{
if (mm_empty(iter->target))
return NULL;
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;
entry->key = key;
entry->value = value;
entry->next = NULL;
entry->prev = NULL;
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)
{
if (_map_->cmp(entry->key, key) == 0)
return entry;
entry = entry->next;
}
return NULL;
}
size_t mm_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 multimap_iter mm_impl_it_start(multimap *_map_)
{
multimap_iter iter;
mm_iter_init(&iter, _map_);
return iter;
}
static multimap_iter mm_impl_it_end(multimap *_map_)
{
multimap_iter iter;
mm_iter_init(&iter, _map_);
mm_iter_to_end(&iter);
return iter;
}
+655
View File
@@ -0,0 +1,655 @@
#include "ext/multiset.h"
//MULTISET_GENERATE(ms, multiset, , size_t)
typedef struct multiset_s
{
struct multiset_entry_s *buffer;
size_t capacity;
size_t count;
size_t cardinality;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct multiset_iter_s (*it_start)(struct multiset_s *);
struct multiset_iter_s (*it_end)(struct multiset_s *);
} multiset, *multiset_ptr;
typedef struct multiset_entry_s
{
size_t value;
size_t multiplicity;
size_t dist;
enum cmc_entry_state_e state;
} multiset_entry, *multiset_entry_ptr;
typedef struct multiset_iter_s
{
struct multiset_s *target;
size_t cursor;
size_t index;
size_t first;
size_t last;
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);
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);
size_t ms_multiplicity_of(multiset *_set_, size_t element);
bool ms_contains(multiset *_set_, size_t element);
bool ms_empty(multiset *_set_);
size_t ms_count(multiset *_set_);
size_t ms_cardinality(multiset *_set_);
size_t ms_capacity(multiset *_set_);
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_);
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);
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);
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_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_);
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;
size_t real_capacity = ms_impl_calculate_size(capacity / load);
multiset *_set_ = malloc(sizeof(multiset));
if (!_set_)
return NULL;
_set_->buffer = malloc(sizeof(multiset_entry) * real_capacity);
if (!_set_->buffer)
{
free(_set_);
return NULL;
}
memset(_set_->buffer, 0, sizeof(multiset_entry) * real_capacity);
_set_->count = 0;
_set_->cardinality = 0;
_set_->capacity = real_capacity;
_set_->load = load;
_set_->cmp = compare;
_set_->hash = hash;
_set_->it_start = ms_impl_it_start;
_set_->it_end = ms_impl_it_end;
return _set_;
}
void ms_clear(multiset *_set_)
{
memset(_set_->buffer, 0, sizeof(multiset_entry) * _set_->capacity);
_set_->count = 0;
}
void ms_free(multiset *_set_)
{
free(_set_->buffer);
free(_set_);
}
bool ms_insert(multiset *_set_, size_t element)
{
bool new_node;
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
if (!entry)
return false;
if (!new_node)
entry->multiplicity++;
_set_->cardinality++;
return true;
}
bool ms_insert_many(multiset *_set_, size_t element, size_t count)
{
if (count == 0)
return true;
bool new_node;
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
if (!entry)
return false;
if (new_node)
entry->multiplicity = count;
else
entry->multiplicity += count;
_set_->cardinality += count;
return true;
}
bool ms_update(multiset *_set_, size_t element, size_t multiplicity)
{
if (multiplicity == 0)
return ms_remove_all(_set_, element);
bool new_node;
multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node);
if (!entry)
return false;
if (new_node)
_set_->cardinality++;
_set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity;
entry->multiplicity = multiplicity;
return true;
}
bool ms_remove(multiset *_set_, size_t element)
{
multiset_entry *result = ms_impl_get_entry(_set_, element);
if (result == NULL)
return false;
if (result->multiplicity > 1)
result->multiplicity--;
else
{
result->value = ms_impl_default_value();
result->multiplicity = 0;
result->dist = 0;
result->state = CMC_ES_DELETED;
_set_->count--;
}
_set_->cardinality--;
return true;
}
size_t ms_remove_all(multiset *_set_, size_t element)
{
multiset_entry *result = ms_impl_get_entry(_set_, element);
if (result == NULL)
return 0;
size_t removed = result->multiplicity;
result->value = ms_impl_default_value();
result->multiplicity = 0;
result->dist = 0;
result->state = CMC_ES_DELETED;
_set_->count--;
_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)
{
if (ms_empty(_set_))
return false;
multiset_iter iter;
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
{
size_t result = ms_iter_value(&iter);
size_t index = ms_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) > 0)
*value = result;
}
return true;
}
bool ms_min(multiset *_set_, size_t *value)
{
if (ms_empty(_set_))
return false;
multiset_iter iter;
for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter))
{
size_t result = ms_iter_value(&iter);
size_t index = ms_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) < 0)
*value = result;
}
return true;
}
size_t ms_multiplicity_of(multiset *_set_, size_t element)
{
multiset_entry *entry = ms_impl_get_entry(_set_, element);
if (!entry)
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; }
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; }
cmc_string ms_to_string(multiset *_set_)
{
cmc_string str;
multiset *s_ = _set_;
const char *name = "multiset";
snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, name, s_, s_->buffer, s_->capacity, s_->count, s_->cardinality, s_->load, s_->cmp, s_->hash);
return str;
}
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;
multiset_iter iter1, iter2;
ms_iter_init(&iter1, _set1_);
ms_iter_init(&iter2, _set2_);
for (ms_iter_to_start(&iter1); !ms_iter_end(&iter1); ms_iter_next(&iter1))
{
size_t value = ms_iter_value(&iter1);
size_t m1 = ms_iter_multiplicity(&iter1);
size_t m2 = ms_multiplicity_of(_set2_, value);
size_t max_ = m1 > m2 ? m1 : m2;
ms_update(_set_r_, value, max_);
}
for (ms_iter_to_start(&iter2); !ms_iter_end(&iter2); ms_iter_next(&iter2))
{
size_t value = ms_iter_value(&iter2);
size_t m1 = ms_multiplicity_of(_set1_, value);
size_t m2 = ms_iter_multiplicity(&iter2);
size_t max_ = m1 > m2 ? m1 : m2;
ms_update(_set_r_, value, max_);
}
return _set_r_;
}
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;
multiset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
multiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
multiset_iter iter;
ms_iter_init(&iter, _set_A_);
for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter))
{
size_t value = ms_iter_value(&iter);
size_t m1 = ms_iter_multiplicity(&iter);
size_t m2 = ms_multiplicity_of(_set_B_, value);
size_t max_ = m1 < m2 ? m1 : m2;
ms_update(_set_r_, value, max_);
}
return _set_r_;
}
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;
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);
size_t m1 = ms_iter_multiplicity(&iter);
size_t m2 = ms_multiplicity_of(_set2_, value);
if (m1 > m2)
ms_update(_set_r_, value, m1 - m2);
}
return _set_r_;
}
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;
multiset_iter iter1, iter2;
ms_iter_init(&iter1, _set1_);
ms_iter_init(&iter2, _set2_);
for (ms_iter_to_start(&iter1); !ms_iter_end(&iter1); ms_iter_next(&iter1))
{
ms_insert_many(_set_r_, ms_iter_value(&iter1), ms_iter_multiplicity(&iter1));
}
for (ms_iter_to_start(&iter2); !ms_iter_end(&iter2); ms_iter_next(&iter2))
{
ms_insert_many(_set_r_, ms_iter_value(&iter2), ms_iter_multiplicity(&iter2));
}
return _set_r_;
}
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;
ms_iter_init(&iter1, _set1_);
ms_iter_init(&iter2, _set2_);
for (ms_iter_to_start(&iter1); !ms_iter_end(&iter1); ms_iter_next(&iter1))
{
size_t value = ms_iter_value(&iter1);
size_t m1 = ms_iter_multiplicity(&iter1);
size_t m2 = ms_multiplicity_of(_set2_, value);
if (m1 != m2)
{
if (m1 > m2)
ms_update(_set_r_, value, m1 - m2);
else
ms_update(_set_r_, value, m2 - m1);
}
}
for (ms_iter_to_start(&iter2); !ms_iter_end(&iter2); ms_iter_next(&iter2))
{
size_t value = ms_iter_value(&iter2);
size_t m1 = ms_multiplicity_of(_set1_, value);
size_t m2 = ms_iter_multiplicity(&iter2);
if (m1 != m2)
{
if (m1 > m2)
ms_update(_set_r_, value, m1 - m2);
else
ms_update(_set_r_, value, m2 - m1);
}
}
return _set_r_;
}
bool ms_is_subset(multiset *_set1_, multiset *_set2_)
{
if (ms_count(_set1_) > ms_count(_set2_))
return false;
if (ms_empty(_set1_))
return true;
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);
size_t m1 = ms_iter_multiplicity(&iter);
size_t m2 = ms_multiplicity_of(_set2_, value);
if (m1 > m2)
return false;
}
return true;
}
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;
if (ms_empty(_set1_))
{
if (!ms_empty(_set2_))
return true;
else
return false;
}
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);
size_t m1 = ms_iter_multiplicity(&iter);
size_t m2 = ms_multiplicity_of(_set2_, value);
if (m1 >= m2)
return false;
}
return true;
}
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;
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 true;
}
multiset_iter *ms_iter_new(multiset *target)
{
multiset_iter *iter = malloc(sizeof(multiset_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = ms_empty(target);
if (!ms_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i].state == CMC_ES_FILLED)
{
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1].state == CMC_ES_FILLED)
{
iter->last = i - 1;
break;
}
}
}
}
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);
}
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;
}
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
{
iter->index++;
while (1)
{
iter->cursor++;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
}
iter->start = ms_empty(iter->target);
return true;
}
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
{
iter->index--;
while (1)
{
iter->cursor--;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == CMC_ES_FILLED)
break;
}
}
iter->end = ms_empty(iter->target);
return true;
}
size_t ms_iter_value(multiset_iter *iter)
{
if (ms_empty(iter->target))
return ms_impl_default_value();
return iter->target->buffer[iter->cursor].value;
}
size_t ms_iter_multiplicity(multiset_iter *iter)
{
if (ms_empty(iter->target))
return 0;
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)
{
*new_node = false;
multiset_entry *entry = ms_impl_get_entry(_set_, element);
if (entry != NULL)
return entry;
*new_node = true;
if ((double)_set_->capacity * _set_->load <= (double)_set_->count)
{
if (!ms_impl_grow(_set_))
return NULL;
}
size_t hash = _set_->hash(element);
size_t original_pos = hash % _set_->capacity;
size_t pos = original_pos;
size_t curr_mul = 1;
multiset_entry *target = &(_set_->buffer[pos]);
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->value = element;
target->multiplicity = curr_mul;
target->dist = pos - original_pos;
target->state = CMC_ES_FILLED;
}
else
{
while (true)
{
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED)
{
target->value = element;
target->multiplicity = curr_mul;
target->dist = pos - original_pos;
target->state = CMC_ES_FILLED;
break;
}
else if (target->dist < pos - original_pos)
{
size_t tmp = target->value;
size_t tmp_dist = target->dist;
size_t tmp_mul = target->multiplicity;
target->value = element;
target->dist = pos - original_pos;
target->multiplicity = curr_mul;
element = tmp;
original_pos = pos - tmp_dist;
curr_mul = tmp_mul;
}
}
}
_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);
size_t pos = hash % _set_->capacity;
multiset_entry *target = &(_set_->buffer[pos]);
while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED)
{
if (_set_->cmp(target->value, element) == 0)
return target;
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
}
return NULL;
}
static size_t ms_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 multiset_iter ms_impl_it_start(multiset *_set_)
{
multiset_iter iter;
ms_iter_init(&iter, _set_);
return iter;
}
static multiset_iter ms_impl_it_end(multiset *_set_)
{
multiset_iter iter;
ms_iter_init(&iter, _set_);
ms_iter_to_end(&iter);
return iter;
}
+250
View File
@@ -0,0 +1,250 @@
#include "cmc/queue.h"
//QUEUE_GENERATE(q, queue, , size_t)
typedef struct queue_s
{
size_t *buffer;
size_t capacity;
size_t count;
size_t front;
size_t rear;
struct queue_iter_s (*it_start)(struct queue_s *);
struct queue_iter_s (*it_end)(struct queue_s *);
} queue, *queue_ptr;
typedef struct queue_iter_s
{
struct queue_s *target;
size_t cursor;
size_t index;
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);
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_);
size_t q_count(queue *_queue_);
size_t q_capacity(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);
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);
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;
queue *_queue_ = malloc(sizeof(queue));
if (!_queue_)
return NULL;
_queue_->buffer = malloc(sizeof(size_t) * capacity);
if (!_queue_->buffer)
{
free(_queue_);
return NULL;
}
memset(_queue_->buffer, 0, sizeof(size_t) * capacity);
_queue_->capacity = capacity;
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
_queue_->it_start = q_impl_it_start;
_queue_->it_end = q_impl_it_end;
return _queue_;
}
void q_clear(queue *_queue_)
{
memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity);
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
}
void q_free(queue *_queue_)
{
free(_queue_->buffer);
free(_queue_);
}
bool q_enqueue(queue *_queue_, size_t element)
{
if (q_full(_queue_))
{
if (!q_impl_grow(_queue_))
return false;
}
_queue_->buffer[_queue_->rear] = element;
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1;
_queue_->count++;
return true;
}
bool q_dequeue(queue *_queue_)
{
if (q_empty(_queue_))
return false;
_queue_->buffer[_queue_->front] = q_impl_default_value();
_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;
}
size_t q_peek(queue *_queue_)
{
if (q_empty(_queue_))
return q_impl_default_value();
return _queue_->buffer[_queue_->front];
}
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++)
{
if (comparator(_queue_->buffer[i], element) == 0)
return true;
}
return false;
}
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; }
queue_iter *q_iter_new(queue *target)
{
queue_iter *iter = malloc(sizeof(queue_iter));
if (!iter)
return NULL;
q_iter_init(iter, target);
return iter;
}
void q_iter_free(queue_iter *iter) { free(iter); }
void q_iter_init(queue_iter *iter, queue *target)
{
iter->target = target;
iter->cursor = target->front;
iter->index = 0;
iter->start = true;
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; }
void q_iter_to_start(queue_iter *iter)
{
iter->cursor = iter->target->front;
iter->index = 0;
iter->start = true;
iter->end = q_empty(iter->target);
}
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;
iter->index = iter->target->count - 1;
iter->start = q_empty(iter->target);
iter->end = true;
}
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
{
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
iter->index++;
}
return true;
}
bool q_iter_prev(queue_iter *iter)
{
if (iter->start)
return false;
iter->end = q_empty(iter->target);
if (iter->index == 0)
iter->start = true;
else
{
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
iter->index--;
}
return true;
}
size_t q_iter_value(queue_iter *iter)
{
if (q_empty(iter->target))
return q_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *q_iter_rvalue(queue_iter *iter)
{
if (q_empty(iter->target))
return NULL;
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;
q_iter_init(&iter, _queue_);
q_iter_to_start(&iter);
return iter;
}
static queue_iter q_impl_it_end(queue *_queue_)
{
queue_iter iter;
q_iter_init(&iter, _queue_);
q_iter_to_end(&iter);
return iter;
}
+234
View File
@@ -0,0 +1,234 @@
#include "cmc/stack.h"
//STACK_GENERATE(s, stack, , size_t)
typedef struct stack_s
{
size_t *buffer;
size_t capacity;
size_t count;
struct stack_iter_s (*it_start)(struct stack_s *);
struct stack_iter_s (*it_end)(struct stack_s *);
} stack, *stack_ptr;
typedef struct stack_iter_s
{
struct stack_s *target;
size_t cursor;
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);
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_);
size_t s_count(stack *_stack_);
size_t s_capacity(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);
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);
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;
stack *_stack_ = malloc(sizeof(stack));
if (!_stack_)
return NULL;
_stack_->buffer = malloc(sizeof(size_t) * capacity);
if (!_stack_->buffer)
{
free(_stack_);
return NULL;
}
memset(_stack_->buffer, 0, sizeof(size_t) * capacity);
_stack_->capacity = capacity;
_stack_->count = 0;
_stack_->it_start = s_impl_it_start;
_stack_->it_end = s_impl_it_end;
return _stack_;
}
void s_clear(stack *_stack_)
{
memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity);
_stack_->count = 0;
}
void s_free(stack *_stack_)
{
free(_stack_->buffer);
free(_stack_);
}
bool s_push(stack *_stack_, size_t element)
{
if (s_full(_stack_))
{
if (!s_impl_grow(_stack_))
return false;
}
_stack_->buffer[_stack_->count++] = element;
return true;
}
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;
}
size_t s_top(stack *_stack_)
{
if (s_empty(_stack_))
return s_impl_default_value();
return _stack_->buffer[_stack_->count - 1];
}
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 false;
}
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; }
stack_iter *s_iter_new(stack *target)
{
stack_iter *iter = malloc(sizeof(stack_iter));
if (!iter)
return NULL;
s_iter_init(iter, target);
return iter;
}
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->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; }
void s_iter_to_start(stack_iter *iter)
{
iter->cursor = iter->target->count - 1;
iter->start = true;
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;
}
bool s_iter_next(stack_iter *iter)
{
if (iter->end)
return false;
iter->start = s_empty(iter->target);
if (iter->cursor == 0)
{
iter->end = true;
return false;
}
else
iter->cursor--;
return true;
}
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)
{
iter->start = true;
return false;
}
else
iter->cursor++;
return true;
}
size_t s_iter_value(stack_iter *iter)
{
if (s_empty(iter->target))
return s_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *s_iter_rvalue(stack_iter *iter)
{
if (s_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t s_iter_index(stack_iter *iter)
{
if (s_empty(iter->target))
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;
s_iter_init(&iter, _stack_);
s_iter_to_start(&iter);
return iter;
}
static stack_iter s_impl_it_end(stack *_stack_)
{
stack_iter iter;
s_iter_init(&iter, _stack_);
s_iter_to_end(&iter);
return iter;
}
+599
View File
@@ -0,0 +1,599 @@
#include "cmc/treemap.h"
//TREEMAP_GENERATE(tm, treemap, , size_t, size_t)
typedef struct treemap_s
{
struct treemap_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treemap_iter_s (*it_start)(struct treemap_s *);
struct treemap_iter_s (*it_end)(struct treemap_s *);
} treemap, *treemap_ptr;
typedef struct treemap_node_s
{
size_t key;
size_t value;
unsigned char height;
struct treemap_node_s *right;
struct treemap_node_s *left;
struct treemap_node_s *parent;
} treemap_node, *treemap_node_ptr;
typedef struct treemap_iter_s
{
struct treemap_s *target;
struct treemap_node_s *cursor;
struct treemap_node_s *first;
struct treemap_node_s *last;
size_t index;
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);
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_);
size_t tm_count(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);
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);
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);
static unsigned char tm_impl_hupdate(treemap_node *node);
static void tm_impl_rotate_right(treemap_node **Z);
static void tm_impl_rotate_left(treemap_node **Z);
static void tm_impl_rebalance(treemap *_map_, treemap_node *node);
static treemap_iter tm_impl_it_start(treemap *_map_);
static treemap_iter tm_impl_it_end(treemap *_map_);
treemap *tm_new(int (*compare)(size_t, size_t))
{
treemap *_map_ = malloc(sizeof(treemap));
if (!_map_)
return NULL;
_map_->count = 0;
_map_->root = NULL;
_map_->cmp = compare;
_map_->it_start = tm_impl_it_start;
_map_->it_end = tm_impl_it_end;
return _map_;
}
void tm_clear(treemap *_map_)
{
treemap_node *scan = _map_->root;
treemap_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treemap_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treemap_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_map_->count = 0;
_map_->root = NULL;
}
void tm_free(treemap *_map_)
{
tm_clear(_map_);
free(_map_);
}
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;
}
else
{
treemap_node *scan = _map_->root;
treemap_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return false;
}
treemap_node *node;
if (_map_->cmp(parent->key, key) > 0)
{
parent->left = tm_impl_new_node(key, value);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = tm_impl_new_node(key, value);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
tm_impl_rebalance(_map_, node);
}
_map_->count++;
return true;
}
bool tm_remove(treemap *_map_, size_t key, size_t *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)
{
if (is_root)
_map_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_map_->root = node->right;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_map_->root = node->left;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
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->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->key = temp_key;
node->value = temp_val;
}
if (unbalanced != NULL)
tm_impl_rebalance(_map_, unbalanced);
_map_->count--;
if (_map_->count == 0)
_map_->root = NULL;
return true;
}
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)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->right != NULL)
scan = scan->right;
*key = scan->key;
*value = scan->value;
return true;
}
bool tm_min(treemap *_map_, size_t *key, size_t *value)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->left != NULL)
scan = scan->left;
*key = scan->key;
*value = scan->value;
return true;
}
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 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 &(node->value);
}
bool tm_contains(treemap *_map_, size_t key)
{
treemap_node *scan = _map_->root;
while (scan != NULL)
{
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 false;
}
bool tm_empty(treemap *_map_) { return _map_->count == 0; }
size_t tm_count(treemap *_map_) { return _map_->count; }
treemap_iter *tm_iter_new(treemap *target)
{
treemap_iter *iter = malloc(sizeof(treemap_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->index = 0;
iter->start = true;
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;
}
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;
}
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;
}
bool tm_iter_next(treemap_iter *iter)
{
if (iter->end)
return false;
iter->start = false;
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
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;
}
iter->cursor = iter->cursor->parent;
}
}
bool tm_iter_prev(treemap_iter *iter)
{
if (iter->start)
return false;
iter->end = false;
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
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;
}
iter->cursor = iter->cursor->parent;
}
}
size_t tm_iter_key(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_key();
return iter->cursor->key;
}
size_t tm_iter_value(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_value();
return iter->cursor->value;
}
size_t *tm_iter_rvalue(treemap_iter *iter)
{
if (tm_empty(iter->target))
return NULL;
return &(iter->cursor->value);
}
size_t tm_iter_index(treemap_iter *iter) { return iter->index; }
static treemap_node *tm_impl_new_node(size_t key, size_t value)
{
treemap_node *node = malloc(sizeof(treemap_node));
if (!node)
return NULL;
node->key = key;
node->value = value;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key)
{
if (tm_empty(_map_))
return NULL;
treemap_node *scan = _map_->root;
while (scan != NULL)
{
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char tm_impl_h(treemap_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char tm_impl_hupdate(treemap_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = tm_impl_h(node->left);
unsigned char h_r = tm_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
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->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
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->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
static void tm_impl_rebalance(treemap *_map_, treemap_node *node)
{
treemap_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = tm_impl_hupdate(scan);
balance = tm_impl_h(scan->right) - tm_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (tm_impl_h(child->right) < tm_impl_h(child->left))
tm_impl_rotate_right(&(scan->right));
tm_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (tm_impl_h(child->left) < tm_impl_h(child->right))
tm_impl_rotate_left(&(scan->left));
tm_impl_rotate_right(&scan);
}
if (is_root)
{
_map_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treemap_iter tm_impl_it_start(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
return iter;
}
static treemap_iter tm_impl_it_end(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
tm_iter_to_end(&iter);
return iter;
}
+690
View File
@@ -0,0 +1,690 @@
#include "cmc/treeset.h"
//TREESET_GENERATE(ts, treeset, , size_t)
typedef struct treeset_s
{
struct treeset_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treeset_iter_s (*it_start)(struct treeset_s *);
struct treeset_iter_s (*it_end)(struct treeset_s *);
} treeset, *treeset_ptr;
typedef struct treeset_node_s
{
size_t value;
unsigned char height;
struct treeset_node_s *right;
struct treeset_node_s *left;
struct treeset_node_s *parent;
} treeset_node, *treeset_node_ptr;
typedef struct treeset_iter_s
{
struct treeset_s *target;
struct treeset_node_s *cursor;
struct treeset_node_s *first;
struct treeset_node_s *last;
size_t index;
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_);
size_t ts_count(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_);
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);
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);
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)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static treeset_node *ts_impl_new_node(size_t element);
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element);
static unsigned char ts_impl_h(treeset_node *node);
static unsigned char ts_impl_hupdate(treeset_node *node);
static void ts_impl_rotate_right(treeset_node **Z);
static void ts_impl_rotate_left(treeset_node **Z);
static void ts_impl_rebalance(treeset *_set_, treeset_node *node);
static treeset_iter ts_impl_it_start(treeset *_set_);
static treeset_iter ts_impl_it_end(treeset *_set_);
treeset *ts_new(int (*compare)(size_t, size_t))
{
treeset *_set_ = malloc(sizeof(treeset));
if (!_set_)
return NULL;
_set_->count = 0;
_set_->root = NULL;
_set_->cmp = compare;
_set_->it_start = ts_impl_it_start;
_set_->it_end = ts_impl_it_end;
return _set_;
}
void ts_clear(treeset *_set_)
{
treeset_node *scan = _set_->root;
treeset_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treeset_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treeset_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_set_->count = 0;
_set_->root = NULL;
}
void ts_free(treeset *_set_)
{
ts_clear(_set_);
free(_set_);
}
bool ts_insert(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
{
_set_->root = ts_impl_new_node(element);
if (!_set_->root)
return false;
}
else
{
treeset_node *scan = _set_->root;
treeset_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return false;
}
treeset_node *node;
if (_set_->cmp(parent->value, element) > 0)
{
parent->left = ts_impl_new_node(element);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = ts_impl_new_node(element);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
ts_impl_rebalance(_set_, node);
}
_set_->count++;
return true;
}
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)
{
if (is_root)
_set_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_set_->root = node->right;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_set_->root = node->left;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
temp = temp->left;
size_t temp_value = temp->value;
unbalanced = temp->parent;
if (temp->left == NULL && temp->right == NULL)
{
if (temp->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->value = temp_value;
}
if (unbalanced != NULL)
ts_impl_rebalance(_set_, unbalanced);
_set_->count--;
if (_set_->count == 0)
_set_->root = NULL;
return true;
}
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)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->right != NULL)
scan = scan->right;
*value = scan->value;
return true;
}
bool ts_min(treeset *_set_, size_t *value)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->left != NULL)
scan = scan->left;
*value = scan->value;
return true;
}
bool ts_contains(treeset *_set_, size_t element)
{
treeset_node *scan = _set_->root;
while (scan != NULL)
{
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 false;
}
bool ts_empty(treeset *_set_) { return _set_->count == 0; }
size_t ts_count(treeset *_set_) { return _set_->count; }
treeset *ts_union(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return NULL;
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))
{
ts_insert(_set_r_, ts_iter_value(&iter1));
}
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
{
ts_insert(_set_r_, ts_iter_value(&iter2));
}
return _set_r_;
}
treeset *ts_intersection(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return NULL;
treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
treeset_iter iter;
ts_iter_init(&iter, _set_A_);
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)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return NULL;
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)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return NULL;
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)
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)
ts_insert(_set_r_, value);
}
return _set_r_;
}
bool ts_is_subset(treeset *_set1_, treeset *_set2_)
{
if (ts_count(_set1_) > ts_count(_set2_))
return false;
if (ts_empty(_set1_))
return true;
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 true;
}
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;
if (ts_empty(_set1_))
{
if (!ts_empty(_set2_))
return true;
else
return false;
}
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 true;
}
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;
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 true;
}
treeset_iter *ts_iter_new(treeset *target)
{
treeset_iter *iter = malloc(sizeof(treeset_iter));
if (!iter)
return NULL;
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)
{
iter->target = target;
iter->index = 0;
iter->start = true;
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;
}
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;
}
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;
}
bool ts_iter_next(treeset_iter *iter)
{
if (iter->end)
return false;
iter->start = ts_empty(iter->target);
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
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;
}
iter->cursor = iter->cursor->parent;
}
}
bool ts_iter_prev(treeset_iter *iter)
{
if (iter->start)
return false;
iter->end = ts_empty(iter->target);
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
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;
}
iter->cursor = iter->cursor->parent;
}
}
size_t ts_iter_value(treeset_iter *iter)
{
if (ts_empty(iter->target))
return ts_impl_default_value();
return iter->cursor->value;
}
size_t ts_iter_index(treeset_iter *iter) { return iter->index; }
static treeset_node *ts_impl_new_node(size_t element)
{
treeset_node *node = malloc(sizeof(treeset_node));
if (!node)
return NULL;
node->value = element;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
return NULL;
treeset_node *scan = _set_->root;
while (scan != NULL)
{
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char ts_impl_h(treeset_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char ts_impl_hupdate(treeset_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = ts_impl_h(node->left);
unsigned char h_r = ts_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
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->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
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->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
static void ts_impl_rebalance(treeset *_set_, treeset_node *node)
{
treeset_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = ts_impl_hupdate(scan);
balance = ts_impl_h(scan->right) - ts_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (ts_impl_h(child->right) < ts_impl_h(child->left))
ts_impl_rotate_right(&(scan->right));
ts_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (ts_impl_h(child->left) < ts_impl_h(child->right))
ts_impl_rotate_left(&(scan->left));
ts_impl_rotate_right(&scan);
}
if (is_root)
{
_set_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treeset_iter ts_impl_it_start(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
return iter;
}
static treeset_iter ts_impl_it_end(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
ts_iter_to_end(&iter);
return iter;
}
+61
View File
@@ -0,0 +1,61 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/deque.c"
CMC_CREATE_UNIT(deque_test, false, {
CMC_CREATE_TEST(new, {
deque *d = d_new(1000000);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert_not_equals(ptr, NULL, d->buffer);
cmc_assert_equals(size_t, 1000000, d->capacity);
cmc_assert_equals(size_t, 0, d_count(d));
d_free(d);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
deque *d = d_new(0);
cmc_assert_equals(ptr, NULL, d);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
deque *d = d_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, d);
});
CMC_CREATE_TEST(clear[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
d_clear(d);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_equals(size_t, 100, d_capacity(d));
d_free(d);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
deque *d = d_new(1);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
d_free(d);
});
});
+48
View File
@@ -0,0 +1,48 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashmap.c"
#include "utl.c"
CMC_CREATE_UNIT(hashmap_test, false, {
CMC_CREATE_TEST(new, {
hashmap *map = hm_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, hm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map));
hm_free(map);
});
CMC_CREATE_TEST(new[edge_case: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_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(clear[count capacity], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
hm_insert(map, i, i);
cmc_assert_equals(size_t, 50, hm_count(map));
hm_clear(map);
cmc_assert_equals(size_t, 0, hm_count(map));
hm_free(map);
});
});
+48
View File
@@ -0,0 +1,48 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashset.c"
#include "utl.c"
CMC_CREATE_UNIT(hashset_test, false, {
CMC_CREATE_TEST(new, {
hashset *set = hs_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_not_equals(ptr, NULL, set->buffer);
cmc_assert_equals(size_t, 0, hs_count(set));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hs_capacity(set));
hs_free(set);
});
CMC_CREATE_TEST(new[edge_case: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_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(clear[count capacity], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
hs_insert(set, i);
cmc_assert_equals(size_t, 50, hs_count(set));
hs_clear(set);
cmc_assert_equals(size_t, 0, hs_count(set));
hs_free(set);
});
});
+62
View File
@@ -0,0 +1,62 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/heap.c"
#include "utl.c"
CMC_CREATE_UNIT(heap_test, false, {
CMC_CREATE_TEST(new, {
heap *h = h_new(1000000, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
cmc_assert_not_equals(ptr, NULL, h->buffer);
cmc_assert_equals(size_t, 1000000, h_capacity(h));
cmc_assert_equals(size_t, 0, h_count(h));
h_free(h);
});
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], {
heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp);
cmc_assert_equals(ptr, NULL, h);
});
CMC_CREATE_TEST(clear[count capacity], {
heap *h = h_new(100, 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_equals(size_t, 50, h_count(h));
h_clear(h);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_equals(size_t, 100, h_capacity(h));
h_free(h);
});
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_equals(size_t, 50, h_count(h));
h_free(h);
});
});
+74
View File
@@ -0,0 +1,74 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/linkedlist.c"
CMC_CREATE_UNIT(linkedlist_test, false, {
CMC_CREATE_TEST(new, {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
cmc_assert_equals(ptr, NULL, ll->head);
cmc_assert_equals(ptr, NULL, ll->tail);
ll_free(ll);
});
CMC_CREATE_TEST(clear[count capacity], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 50; i++)
ll_push_back(ll, i);
cmc_assert_equals(size_t, 50, ll_count(ll));
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(clear[edge_case:count = 0], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(push_front[count], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_push_front(ll, 1);
cmc_assert_not_equals(ptr, NULL, ll->head);
cmc_assert_not_equals(ptr, NULL, ll->tail);
cmc_assert_equals(size_t, 1, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(push_front[item_preservation], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 200; i++)
ll_push_front(ll, i);
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);
});
});
+335
View File
@@ -0,0 +1,335 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/list.c"
CMC_CREATE_UNIT(list_test, false, {
CMC_CREATE_TEST(new, {
list *l = l_new(1000000);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert_not_equals(ptr, NULL, l->buffer);
cmc_assert_equals(size_t, 1000000, l_capacity(l));
cmc_assert_equals(size_t, 0, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
list *l = l_new(0);
cmc_assert_equals(ptr, NULL, l);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
list *l = l_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, l);
});
CMC_CREATE_TEST(new_from[count item_preservation], {
size_t v[5];
for (size_t i = 0; i < 5; i++)
{
v[i] = i;
}
list *l = l_new_from(v, 5);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 5; i++)
cmc_assert_equals(size_t, i, l_get(l, i));
l_free(l);
});
CMC_CREATE_TEST(new_from[edge_case:size = 1], {
size_t a = 10;
size_t *values = &a;
list *l = l_new_from(values, 1);
cmc_assert_not_equals(ptr, NULL, l);
l_free(l);
});
CMC_CREATE_TEST(clear[count capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 50; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 50, l_count(l));
l_clear(l);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_equals(size_t, 100, l_capacity(l));
l_free(l);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
list *l = l_new(1);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 100; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 100, l_count(l));
for (size_t i = 0; i < 100; i++)
cmc_assert_equals(size_t, i, l_get(l, i));
l_free(l);
});
CMC_CREATE_TEST(push_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_front[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
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);
});
CMC_CREATE_TEST(push[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
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_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
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_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
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));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i);
l_free(l);
});
CMC_CREATE_TEST(push_back[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_back[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_back[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i);
l_free(l);
});
CMC_CREATE_TEST(pop_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
cmc_assert(l_pop_front(l));
l_free(l);
});
CMC_CREATE_TEST(pop_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
cmc_assert(l_pop_front(l));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i + 1);
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_front(l));
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case: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);
});
CMC_CREATE_TEST(pop_front[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_front(l, 2));
cmc_assert(l_pop_front(l));
cmc_assert_equals(size_t, 0, l->buffer[1]);
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop(l, 1));
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case: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_equals(size_t, 0, l->buffer[0]);
l_free(l);
});
CMC_CREATE_TEST(pop[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));
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_back(l));
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case: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);
});
})
+151
View File
@@ -0,0 +1,151 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multimap.c"
#include "utl.c"
CMC_CREATE_UNIT(multimap_test, false, {
CMC_CREATE_TEST(new, {
multimap *map = mm_new(943722, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, mm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.8), mm_capacity(map));
mm_free(map);
});
CMC_CREATE_TEST(new[edge_case: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_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(clear[count capacity], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
cmc_assert(mm_insert(map, i, i));
cmc_assert_equals(size_t, 50, mm_count(map));
mm_clear(map);
cmc_assert_equals(size_t, 0, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(insert[count], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 200, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(remove[count], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
size_t r;
for (size_t i = 0; i < 60; i++)
cmc_assert(mm_remove(map, i % 20, &r));
cmc_assert_equals(size_t, 140, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(remove[edge_case:count = 0], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
size_t r;
cmc_assert(!mm_remove(map, 10, &r));
mm_free(map);
});
CMC_CREATE_TEST(remove[edge_case:count = 1], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
size_t r;
cmc_assert(mm_insert(map, 10, 11));
cmc_assert(mm_remove(map, 10, &r));
mm_free(map);
});
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], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
/* Assert that the value 100 is accessed before the value 101 for the
* same key */
cmc_assert(mm_insert(map, 10, 100));
cmc_assert(mm_insert(map, 20, 102));
cmc_assert(mm_insert(map, 10, 101));
cmc_assert_equals(size_t, 100, mm_get(map, 10));
mm_free(map);
});
});
+86
View File
@@ -0,0 +1,86 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multiset.c"
#include "utl.c"
CMC_CREATE_UNIT(multiset_test, false, {
CMC_CREATE_TEST(new, {
multiset *set = ms_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_not_equals(ptr, NULL, set->buffer);
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);
});
CMC_CREATE_TEST(new[edge_case: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_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(clear[count capacity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
cmc_assert(ms_insert(set, i));
cmc_assert_equals(size_t, 50, ms_count(set));
ms_clear(set);
cmc_assert_equals(size_t, 0, ms_count(set));
ms_free(set);
});
CMC_CREATE_TEST(insert[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));
ms_free(set);
});
CMC_CREATE_TEST(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, i % 20));
cmc_assert_equals(size_t, 20, ms_count(set));
cmc_assert_equals(size_t, 100, ms_cardinality(set));
for (size_t i = 0; i < 20; i++)
cmc_assert_equals(size_t, 5, ms_multiplicity_of(set, i));
ms_free(set);
});
});
+61
View File
@@ -0,0 +1,61 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/queue.c"
CMC_CREATE_UNIT(queue_test, false, {
CMC_CREATE_TEST(new, {
queue *q = q_new(1000000);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert_not_equals(ptr, NULL, q->buffer);
cmc_assert_equals(size_t, 1000000, q_capacity(q));
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_not_equals(ptr, NULL, q->buffer);
q_free(q);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
queue *q = q_new(0);
cmc_assert_equals(ptr, NULL, q);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
queue *q = q_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, q);
});
CMC_CREATE_TEST(clear[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
q_clear(q);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_equals(size_t, 100, q_capacity(q));
q_free(q);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
queue *q = q_new(1);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
q_free(q);
});
});
+628
View File
@@ -0,0 +1,628 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/stack.c"
#include "utl.c"
CMC_CREATE_UNIT(stack_test, false, {
CMC_CREATE_TEST(new, {
stack *s = s_new(1000000);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_not_equals(ptr, NULL, s->buffer);
cmc_assert_equals(size_t, 1000000, s_capacity(s));
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_not_equals(ptr, NULL, s->buffer);
s_free(s);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
stack *s = s_new(0);
cmc_assert_equals(ptr, NULL, s);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
stack *s = s_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, s);
});
CMC_CREATE_TEST(clear[count capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
s_clear(s);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_equals(size_t, 100, s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 250, s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
for (size_t i = 0; i < s_count(s); i++)
cmc_assert_equals(size_t, i, s->buffer[i]);
s_free(s);
});
CMC_CREATE_TEST(pop[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 249, s_count(s));
s_free(s);
});
CMC_CREATE_TEST(pop[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(pop[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
for (size_t i = 0; i < s_count(s); i++)
cmc_assert_equals(size_t, i, s->buffer[i]);
s_free(s);
});
CMC_CREATE_TEST(pop[edge_case: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);
});
CMC_CREATE_TEST(top, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 247, s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 1));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, 1, s_count(s));
cmc_assert_equals(size_t, 10, s_top(s));
s_free(s);
});
CMC_CREATE_TEST(contains, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 150; i++)
cmc_assert(s_push(s, i));
for (size_t i = 0; i < 150; i++)
cmc_assert(s_contains(s, i, cmp));
s_free(s);
});
CMC_CREATE_TEST(contains[edge_case: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);
});
CMC_CREATE_TEST(empty, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(empty[after_io], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_pop(s));
cmc_assert(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(full, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < s_capacity(s); i++)
cmc_assert(s_push(s, i));
cmc_assert(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(iter_alloc, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter *iter = s_iter_new(s);
cmc_assert_not_equals(ptr, NULL, iter);
s_iter_free(iter);
s_free(s);
});
CMC_CREATE_TEST(iter_init[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(ptr, iter.target, s);
cmc_assert_equals(size_t, iter.cursor, 0);
cmc_assert(iter.start);
cmc_assert(iter.end);
s_free(s);
});
CMC_CREATE_TEST(iter_start[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert(s_iter_start(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_end[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert(s_iter_end(&iter));
s_free(s);
});
CMC_CREATE_TEST(iteration, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 1; i <= 200; i++)
cmc_assert(s_push(s, i));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 20100, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 40200, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[while loop], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 1; i <= 200; i++)
cmc_assert(s_push(s, i));
size_t total = 0;
stack_iter it = s->it_start(s);
do
{
total += s_iter_value(&it);
} while (s_iter_next(&it));
cmc_assert_equals(size_t, 20100, total);
it = s->it_end(s);
do
{
total += s_iter_value(&it);
} while (s_iter_prev(&it));
cmc_assert_equals(size_t, 40200, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 20, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[edge_case:count = capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
while (!s_full(s))
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, s_capacity(s), s_count(s));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 1000, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += *s_iter_rvalue(&it);
}
cmc_assert_equals(size_t, 2000, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
stack_iter it1;
stack_iter it2;
memset(&it1, 0, sizeof(stack_iter));
memset(&it2, 0, sizeof(stack_iter));
s_iter_init(&it2, s);
it1 = s->it_start(s);
s_iter_to_start(&it2);
cmc_assert_equals(ptr, it1.target, it2.target);
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
it1 = s->it_end(s);
s_iter_to_end(&it2);
cmc_assert_equals(ptr, it1.target, it2.target);
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
s_free(s);
});
CMC_CREATE_TEST(iteration[boundaries:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
s_free(s);
});
CMC_CREATE_TEST(iteration[boundaries:count > 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 200; i++)
cmc_assert(s_push(s, i));
stack_iter iter;
s_iter_init(&iter, s);
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_value[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(size_t, s_impl_default_value(), s_iter_value(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_rvalue[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(ptr, NULL, s_iter_rvalue(&iter));
s_free(s);
});
CMC_CREATE_TEST(index, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 10; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 10, s_count(s));
size_t total = 0;
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; )
{
cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it));
}
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_index(&it);
}
cmc_assert_equals(size_t, 45, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_index(&it);
}
cmc_assert_equals(size_t, 90, total);
s_free(s);
});
CMC_CREATE_TEST(index[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(size_t, 0, s_iter_index(&iter));
s_free(s);
});
});
+34
View File
@@ -0,0 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treemap.c"
#include "utl.c"
CMC_CREATE_UNIT(treemap_test, false, {
CMC_CREATE_TEST(new, {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
tm_free(map);
});
CMC_CREATE_TEST(clear[count], {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
tm_insert(map, i, i);
cmc_assert_equals(size_t, 50, tm_count(map));
tm_clear(map);
cmc_assert_equals(size_t, 0, tm_count(map));
cmc_assert_equals(ptr, NULL, map->root);
tm_free(map);
});
});
+34
View File
@@ -0,0 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treeset.c"
#include "utl.c"
CMC_CREATE_UNIT(treeset_test, false, {
CMC_CREATE_TEST(new, {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
ts_free(set);
});
CMC_CREATE_TEST(clear[count], {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
ts_insert(set, i);
cmc_assert_equals(size_t, 50, ts_count(set));
ts_clear(set);
cmc_assert_equals(size_t, 0, ts_count(set));
cmc_assert_equals(ptr, NULL, set->root);
ts_free(set);
});
});
+23
View File
@@ -0,0 +1,23 @@
/* Utility file to be included in the unit tests */
#ifndef CMC_UNIT_TEST_UTL__
#define CMC_UNIT_TEST_UTL__
#include <stdlib.h>
int cmp(size_t a, size_t b)
{
return (a > b) - (a < b);
}
size_t hash(size_t a)
{
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
#endif /* CMC_UNIT_TEST_UTL__ */