diff --git a/.gitignore b/.gitignore index 2101ef7..9daeafb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ test -.cache -compile_commands.json diff --git a/README.md b/README.md index 1affa24..e8a3568 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Example of working with a singly linked list (sll): char *a = "one"; char *b = "two"; ds_sll_t *ll = ds_sll_init(); -ds_sll_append(ll, a); // [ "one" ] -ds_sll_append(ll, b); // [ "one", "two" ] +ds_sll_insert(ll, a); // [ "one" ] +ds_sll_insert(ll, b); // [ "one", "two" ] ds_ll_foreach(ds_sll_t, ll) { puts(cur->data); // one @@ -45,20 +45,6 @@ ds_hmp_free(&hmp, NULL); free(b); ``` -## Stack -```c -char *a = "a"; -char *b = "b"; - -ds_stack_t *stack = ds_stack_init(); -ds_stack_push(stack, a); // [ "a" ] -ds_stack_push(stack, b); // [ "b", "a" ] -ds_stack_peek(stack, 0); // "b" -ds_stack_pop(stack); // "b" -ds_stack_pop(stack); // "a" -free(stack); -``` - # TODO - [ ] more data structures - [x] tests diff --git a/ds.c b/ds.c index 73ab51a..53ef37b 100644 --- a/ds.c +++ b/ds.c @@ -6,13 +6,13 @@ ds_sll_t *ds_sll_init(void) { - return ds_sll_new_node(NULL); + return ds_sll_new_node(NULL); } ds_dll_t *ds_dll_init(void) { - return ds_dll_new_node(NULL); + return ds_dll_new_node(NULL); } ds_sll_t @@ -40,227 +40,167 @@ ds_dll_t } int -ds_sll_add(ds_sll_t **ll, void *data, unsigned x) +ds_sll_insert(ds_sll_t *ll, void *data) { - int i; - ds_sll_t *cur, *prev, *new; - if (!ll || !data) { - return -1; - } + if (!ll || !data) { + return -1; + } - for (i = 0, cur = *ll; cur; prev = cur, cur = cur->next, i++) { - if (i == x) { - if (!cur->data) { - cur->data = data; - return 0; - } - new = ds_sll_new_node(data); - new->next = cur; - if (i == 0) { - *ll = new; - } else { - prev->next = new; - } - return 0; - } - } + ds_ll_foreach(ds_sll_t, ll) { + if (!cur->data) { + cur->data = data; + return 0; + } else if (!cur->next) { + cur->next = ds_sll_new_node(data); + return 0; + } + } - return -1; + return -1; } int -ds_dll_add(ds_dll_t **ll, void *data, unsigned x) +ds_dll_insert(ds_dll_t *ll, void *data) { - int i; - ds_dll_t *cur, *new; - if (!ll || !data) { - return -1; - } + if (!ll || !data) { + return -1; + } - for (i = 0, cur = *ll; cur; cur = cur->next, i++) { - if (i == x) { - if (!cur->data) { - cur->data = data; - return 0; - } - new = ds_dll_new_node(data); - new->next = cur; - new->prev = cur->prev; - cur->prev = new; - if (i == 0) { - *ll = new; - } else { - cur->prev->next = new; - } - return 0; - } - } + ds_ll_foreach(ds_dll_t, ll) { + if (!cur->data) { + cur->data = data; + return 0; + } else if (!cur->next) { + cur->next = ds_dll_new_node(data); + cur->next->prev = cur; + return 0; + } + } - return -1; -} - -int -ds_sll_append(ds_sll_t *ll, void *data) -{ - if (!ll || !data) { - return -1; - } - - ds_ll_foreach(ds_sll_t, ll) { - if (!cur->data) { - cur->data = data; - return 0; - } else if (!cur->next) { - cur->next = ds_sll_new_node(data); - return 0; - } - } - - return -1; -} - -int -ds_dll_append(ds_dll_t *ll, void *data) -{ - if (!ll || !data) { - return -1; - } - - ds_ll_foreach(ds_dll_t, ll) { - if (!cur->data) { - cur->data = data; - return 0; - } else if (!cur->next) { - cur->next = ds_dll_new_node(data); - cur->next->prev = cur; - return 0; - } - } - - return -1; + return -1; } void *ds_sll_remove(ds_sll_t **ll, unsigned idx) { - int i; - void *data; - ds_sll_t *cur, *rm; + int i; + void *data; + ds_sll_t *cur, *rm; - rm = NULL; - if (!ll || !*ll) { - return NULL; - } + rm = NULL; + if (!ll || !*ll) { + return NULL; + } - if (idx == 0) { - rm = *ll; - *ll = rm->next; - } else { - for (i = -1, cur = *ll; cur; i++, cur = cur->next) { - if (idx == i + 1) { - rm = cur->next; - break; - } - } + if (idx == 0) { + rm = *ll; + *ll = rm->next; + } else { + for (i = -1, cur = *ll; cur; i++, cur = cur->next) { + if (idx == i + 1) { + rm = cur->next; + break; + } + } - if (!rm) { - return NULL; - } + if (!rm) { + return NULL; + } - cur->next = rm->next; - } + cur->next = rm->next; + } - data = rm->data; - free(rm); - return data; + data = rm->data; + free(rm); + return data; } void *ds_dll_remove(ds_dll_t **ll, unsigned idx) { - int i; - void *data; - ds_dll_t *cur, *rm; + int i; + void *data; + ds_dll_t *cur, *rm; - rm = NULL; - if (!ll || !*ll) { - return NULL; - } + rm = NULL; + if (!ll || !*ll) { + return NULL; + } - if (idx == 0) { - rm = *ll; - *ll = rm->next; - if (rm->next) { - rm->next->prev = NULL; - } - } else { - for (i = 0, cur = *ll; cur; i++, cur = cur->next) { - if (i == idx) { - rm = cur; - break; - } - } + if (idx == 0) { + rm = *ll; + *ll = rm->next; + if (rm->next) { + rm->next->prev = NULL; + } + } else { + for (i = 0, cur = *ll; cur; i++, cur = cur->next) { + if (i == idx) { + rm = cur; + break; + } + } - if (!rm) { - return NULL; - } + if (!rm) { + return NULL; + } - rm->prev->next = rm->next; - if (rm->next) { - rm->next->prev = rm->prev; - } - } + rm->prev->next = rm->next; + if (rm->next) { + rm->next->prev = rm->prev; + } + } - data = rm->data; - free(rm); - return data; + data = rm->data; + free(rm); + return data; } ds_hmp_t *ds_hmp_init(int data_len) { - ds_hmp_t *hmp; + ds_hmp_t *hmp; - if (!data_len) { - return NULL; - } + if (!data_len) { + return NULL; + } - hmp = calloc(1, sizeof(ds_hmp_t)); - hmp->data_len = data_len; - hmp->data = calloc(data_len, sizeof(ds_sll_t **)); + hmp = calloc(1, sizeof(ds_hmp_t)); + hmp->data_len = data_len; + hmp->data = calloc(data_len, sizeof(ds_sll_t **)); - return hmp; + return hmp; } int ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv)) { - int i; - _ds_hmp_kv_t *kv; - ds_sll_t *ll; + int i; + _ds_hmp_kv_t *kv; + ds_sll_t *ll; - if (!hmp || !*hmp) { - return -1; - } + if (!hmp || !*hmp) { + return -1; + } - for (i = 0; i < (*hmp)->data_len; i++) { - ll = (*hmp)->data[i]; - while (ll && ll->data) { - if ((kv = ds_sll_remove(&ll, 0))) { - if (kv_callback) { - kv_callback(kv); - } - free(kv); - } - } - if (ll) { - free(ll); - } - } - free((*hmp)->data); - free(*hmp); + for (i = 0; i < (*hmp)->data_len; i++) { + ll = (*hmp)->data[i]; + while (ll && ll->data) { + if ((kv = ds_sll_remove(&ll, 0))) { + if (kv_callback) { + kv_callback(kv); + } + free(kv); + } + } + if (ll) { + free(ll); + } + } + free((*hmp)->data); + free(*hmp); - return 0; + return 0; } int @@ -279,144 +219,91 @@ _ds_hmp_gen_hash(char *str) int ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data) { - _ds_hmp_kv_t *kv; - ds_sll_t *ll; - unsigned hash_pos; + _ds_hmp_kv_t *kv; + ds_sll_t *ll; + unsigned hash_pos; - if (!hmp || !key || !data) { - return -1; - } + if (!hmp || !key || !data) { + return -1; + } - kv = malloc(sizeof(_ds_hmp_kv_t)); - kv->key = key; - kv->val = data; + kv = malloc(sizeof(_ds_hmp_kv_t)); + kv->key = key; + kv->val = data; - hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; - if (!hmp->data[hash_pos]) { - hmp->data[hash_pos] = ds_sll_init(); - if (!hmp->data[hash_pos]) { - return -1; - } - } + hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; + if (!hmp->data[hash_pos]) { + hmp->data[hash_pos] = ds_sll_init(); + if (!hmp->data[hash_pos]) { + return -1; + } + } - /* get the ll and put the data into it */ - ll = hmp->data[hash_pos]; - if (ds_sll_append(ll, kv) != 0) { - return -1; - } + /* get the ll and put the data into it */ + ll = hmp->data[hash_pos]; + if (ds_sll_insert(ll, kv) != 0) { + return -1; + } - return 0; + return 0; } void *ds_hmp_get(ds_hmp_t *hmp, char *key) { - ds_sll_t *cur, *ll; - unsigned hash_pos; + ds_sll_t *cur, *ll; + unsigned hash_pos; - if (!hmp || !key) { - return NULL; - } + if (!hmp || !key) { + return NULL; + } - hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; - ll = hmp->data[hash_pos]; - if (!ll) { - return NULL; - } + hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; + ll = hmp->data[hash_pos]; + if (!ll) { + return NULL; + } - ds_ll_foreach(ds_sll_t, ll) { - if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { - return ((_ds_hmp_kv_t *)cur->data)->val; - } - } + ds_ll_foreach(ds_sll_t, ll) { + if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { + return ((_ds_hmp_kv_t *)cur->data)->val; + } + } - return NULL; + return NULL; } void *ds_hmp_remove(ds_hmp_t *hmp, char *key) { - int i; - void *data; - unsigned hash_pos; - ds_sll_t *ll, *cur; - _ds_hmp_kv_t *kv; + int i; + void *data; + unsigned hash_pos; + ds_sll_t *ll, *cur; + _ds_hmp_kv_t *kv; - if (!hmp || !key) { - return NULL; - } + if (!hmp || !key) { + return NULL; + } - hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; - ll = hmp->data[hash_pos]; - if (!ll) { - return NULL; - } + hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; + ll = hmp->data[hash_pos]; + if (!ll) { + return NULL; + } - for (i = 0, cur = ll; cur; i++, cur = cur->next) { - if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { - kv = ds_sll_remove(&ll, i); - hmp->data[hash_pos] = ll; - if (!kv) { - return NULL; - } - data = kv->val; - free(kv); - return data; - } - } + for (i = 0, cur = ll; cur; i++, cur = cur->next) { + if (strcmp(((_ds_hmp_kv_t *)cur->data)->key, key) == 0) { + kv = ds_sll_remove(&ll, i); + hmp->data[hash_pos] = ll; + if (!kv) { + return NULL; + } + data = kv->val; + free(kv); + return data; + } + } - return NULL; -} - -ds_stack_t -*ds_stack_init(void) -{ - ds_stack_t *stack = malloc(sizeof(ds_stack_t)); - stack->n = 0; - - return stack; -} - -int -ds_stack_push(ds_stack_t *stack, void *data) -{ - if (stack->n == 0) { - stack->items = ds_sll_new_node(data); - stack->n++; - return 0; - } - int r = ds_sll_add(&stack->items, data, 0); - if (!r) { - stack->n++; - } - return r; -} - -void -*ds_stack_pop(ds_stack_t *stack) -{ - void *r = ds_sll_remove(&stack->items, 0); - if (r != NULL) { - stack->n--; - } - return r; -} - -void -*ds_stack_peek(ds_stack_t *stack, unsigned x) -{ - int i; - ds_sll_t *cur; - - if (x > stack->n) { - return NULL; - } - - for (cur = stack->items, i = 0; cur; cur = cur->next, i++) { - if (i == x) { - return cur->data; - } - } - - return NULL; + return NULL; } diff --git a/ds.h b/ds.h index 7db0049..a8fbb3f 100644 --- a/ds.h +++ b/ds.h @@ -14,19 +14,14 @@ typedef struct _ds_dll { typedef struct { ds_sll_t **data; - unsigned data_len; + unsigned data_len; } ds_hmp_t; typedef struct { - char *key; - void *val; + char *key; + void *val; } _ds_hmp_kv_t; -typedef struct { - unsigned n; - ds_sll_t *items; -} ds_stack_t; - #define ds_ll_foreach(t, ll) for (t *cur = ll; cur; cur = cur->next) /** @@ -60,46 +55,24 @@ ds_sll_t *ds_sll_new_node(void *data); ds_dll_t *ds_dll_new_node(void *data); /** - * @brief data to add at x of a singly linked list. This will use + * @brief data to insert into a singly linked list. This will use * ds_sll_new_node to create the node for you. * * @param ll singly linked list * @param data data you want to add - * @param x the position to add it at * @return 0 on success */ -int ds_sll_add(ds_sll_t **ll, void *data, unsigned x); +int ds_sll_insert(ds_sll_t *ll, void *data); /** - * @brief data to add at x of a doubly linked list. This will use - * ds_dll_new_node to create the node for you. + * @brief data to insert into a doubly linked list. This will use + * ds_sll_new_node to create the node for you. * * @param ll doubly linked list * @param data data you want to add - * @param x the position to add it at * @return 0 on success */ -int ds_dll_add(ds_dll_t **ll, void *data, unsigned x); - -/** - * @brief data to append to the end of a singly linked list. This will use - * ds_sll_new_node to create the node for you. - * - * @param ll singly linked list - * @param data data you want to append - * @return 0 on success - */ -int ds_sll_append(ds_sll_t *ll, void *data); - -/** - * @brief data to append to the end of a doubly linked list. This will use - * ds_dll_new_node to create the node for you. - * - * @param ll doubly linked list - * @param data data you want to append - * @return 0 on success - */ -int ds_dll_append(ds_dll_t *ll, void *data); +int ds_dll_insert(ds_dll_t *ll, void *data); /** * @brief remove an index from a singly linked list @@ -173,37 +146,4 @@ void *ds_hmp_get(ds_hmp_t *hmp, char *key); */ void *ds_hmp_remove(ds_hmp_t *hmp, char *key); -/** - * @brief initialize a new stack - * - * @return the stack - */ -ds_stack_t *ds_stack_init(void); - -/** - * @brief push new data onto the stack - * - * @param stack the stack - * @param data the data - * @return 0 on success - */ -int ds_stack_push(ds_stack_t *stack, void *data); - -/** - * @brief pop the data off the top of the stack - * - * @param stack the stack - * @return the data - */ -void *ds_stack_pop(ds_stack_t *stack); - -/** - * @brief peek forward x items - * - * @param stack the stack - * @param x how many items to look ahead - * @return the data or NULL if out of range - */ -void *ds_stack_peek(ds_stack_t *stack, unsigned x); - #endif diff --git a/test.c b/test.c index 32942a6..30c9fcb 100644 --- a/test.c +++ b/test.c @@ -1,102 +1,73 @@ -#include #include #include #include #include "ds.h" -#define test(name, tests) do { \ - const char *_test_name = name; \ - int _tests_passed = 0; \ - int _tests = 0; \ - tests \ - _tests_passed += _tests; \ - printf("%s: %d/%d tests passed\n", name, _tests_passed, _tests); \ -} while (0) +#define test(name, tests) do { \ + const char *_test_name = name; \ + int _tests_passed = 0; \ + int _tests = 0; \ + tests \ + _tests_passed += _tests; \ + printf("%s: %d/%d tests passed\n", name, _tests_passed, _tests); \ + } while (0) -#define it(message, test) do { \ - _tests++; \ - if (!(test)) { \ - printf("%s %s FAILED @ %s:%d\n", _test_name, message, __FILE__, __LINE__); \ - printf(" -> test condition: (%s)\n", #test); \ - _tests_passed--; \ - } \ +#define it(message, test) do { \ + _tests++; \ + if (!(test)) { \ + printf("%s %s FAILED\n", _test_name, message); \ + _tests_passed--; \ + } \ } while (0) typedef struct { - int num; - char *str; + int num; + char *str; } complex; int main(int argc, char *argv[]) { - test("sll", - char *a = "a"; - char *b = "b"; + test("sll", + char *a = "one"; - ds_sll_t *tmp; - it("creates a new linked list", tmp = ds_sll_init()); - free(tmp); + ds_sll_t *tmp; + it("ensures creates a new linked list", tmp = ds_sll_init()); + free(tmp); - ds_sll_t *ll = ds_sll_new_node(a); - it("appends an invalid item", ds_sll_append(ll, NULL) == -1); - it("removes an invalid index", ds_sll_remove(&ll, 1234) == NULL); - it("adds an item to the beginning", ds_sll_add(&ll, b, 0) == 0); - it("removes an item", b == ds_sll_remove(&ll, 0)); - ds_sll_remove(&ll, 0); - ); + ds_sll_t *ll = ds_sll_new_node(a); + it("inserts an invalid item", ds_sll_insert(ll, NULL) == -1); + it("removes an invalid index", ds_sll_remove(&ll, 1234) == NULL); + it("removes an item", a == ds_sll_remove(&ll, 0)); + ); - test("dll", - char *a = "a"; - char *b = "b"; + test("dll", + char *a = "one"; - ds_dll_t *tmp; - it("creates a new linked list", tmp = ds_dll_init()); - free(tmp); + ds_dll_t *tmp; + it("ensures creates a new linked list", tmp = ds_dll_init()); + free(tmp); - ds_dll_t *ll = ds_dll_new_node(a); - it("appends an invalid item", ds_dll_append(ll, NULL) == -1); - it("removes an invalid index", ds_dll_remove(&ll, 1234) == NULL); - it("adds an item to the beginning", ds_dll_add(&ll, b, 0) == 0); - it("removes an item", b == ds_dll_remove(&ll, 0)); - ds_dll_remove(&ll, 0); - ); + ds_dll_t *ll = ds_dll_new_node(a); + it("inserts an invalid item", ds_dll_insert(ll, NULL) == -1); + it("removes an invalid index", ds_dll_remove(&ll, 1234) == NULL); + it("removes an item", a == ds_dll_remove(&ll, 0)); + ); - test("hmp", - complex *a = calloc(1, sizeof(complex)); - a->num = 1; - a->str = "abc"; + test("hmp", + complex *a = calloc(1, sizeof(complex)); + a->num = 1; + a->str = "abc"; - ds_hmp_t *hmp = ds_hmp_init(101); - it("inserts an item", ds_hmp_insert(hmp, a->str, a) == 0); - it("generates a hash", _ds_hmp_gen_hash("a") == 177670); - it("removes a non-existent item", ds_hmp_remove(hmp, "???") == NULL); - it("removes an invalid item", ds_hmp_remove(hmp, NULL) == NULL); - it("removes an item", a == ds_hmp_remove(hmp, a->str)); - ds_hmp_free(&hmp, NULL); + ds_hmp_t *hmp = ds_hmp_init(101); + it("inserts an item", ds_hmp_insert(hmp, a->str, a) == 0); + it("generates a hash", _ds_hmp_gen_hash("a") == 177670); + it("removes a non-existent item", ds_hmp_remove(hmp, "???") == NULL); + it("removes an invalid item", ds_hmp_remove(hmp, NULL) == NULL); + it("removes an item", a == ds_hmp_remove(hmp, a->str)); + ds_hmp_free(&hmp, NULL); - free(a); - ); - - test("stack", - char *a = "a"; - char *b = "b"; - char *c = "c"; - - ds_stack_t *stack = ds_stack_init(); - it("pushes an item", ds_stack_push(stack, a) == 0); - it("pops an item", ds_stack_pop(stack) == a); - - ds_stack_push(stack, b); - ds_stack_push(stack, c); - - it("peeks ahead", ds_stack_peek(stack, 0) == c); - it("peeks past the stack", ds_stack_peek(stack, INT_MAX) == NULL); - - ds_stack_pop(stack); - ds_stack_pop(stack); - - free(stack); - ); + free(a); + ); }