From 5a485445edfed4d2f967ab404fba5959e599c7f7 Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 02:19:31 -0500 Subject: [PATCH 1/7] fix(test): remove extra word --- test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.c b/test.c index 30c9fcb..919b0a4 100644 --- a/test.c +++ b/test.c @@ -33,7 +33,7 @@ main(int argc, char *argv[]) char *a = "one"; ds_sll_t *tmp; - it("ensures creates a new linked list", tmp = ds_sll_init()); + it("creates a new linked list", tmp = ds_sll_init()); free(tmp); ds_sll_t *ll = ds_sll_new_node(a); @@ -46,7 +46,7 @@ main(int argc, char *argv[]) char *a = "one"; ds_dll_t *tmp; - it("ensures creates a new linked list", tmp = ds_dll_init()); + it("creates a new linked list", tmp = ds_dll_init()); free(tmp); ds_dll_t *ll = ds_dll_new_node(a); From a56daaf6b810bc607e83427432a9fdd52a48efc8 Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 02:19:58 -0500 Subject: [PATCH 2/7] fix(formatting): :retab --- ds.c | 360 ++++++++++++++++++++++++++++----------------------------- test.c | 98 ++++++++-------- 2 files changed, 229 insertions(+), 229 deletions(-) diff --git a/ds.c b/ds.c index 53ef37b..661b482 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 @@ -42,165 +42,165 @@ ds_dll_t int ds_sll_insert(ds_sll_t *ll, void *data) { - if (!ll || !data) { - return -1; - } + 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; - } - } + 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_insert(ds_dll_t *ll, void *data) { - if (!ll || !data) { - return -1; - } + 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; - } - } + 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 @@ -219,91 +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_insert(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; + return NULL; } diff --git a/test.c b/test.c index 919b0a4..2e99a9a 100644 --- a/test.c +++ b/test.c @@ -4,70 +4,70 @@ #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\n", _test_name, message); \ - _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 = "one"; + 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("creates a new linked list", tmp = ds_sll_init()); + free(tmp); - 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)); - ); + 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 = "one"; + 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("creates a new linked list", tmp = ds_dll_init()); + free(tmp); - 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)); - ); + 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); - ); + free(a); + ); } From 46b0219ab47d7adb1b5787ace748a9c0ed991a07 Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 02:20:39 -0500 Subject: [PATCH 3/7] fix(gitignore): add some more artifacts to ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9daeafb..2101ef7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ test +.cache +compile_commands.json From 69dc1dcb457089a94792fa255d992a70ccf487bb Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 21:39:57 -0500 Subject: [PATCH 4/7] feat(ll)!: add new ll function and rename insert ds_*ll_insert -> ds_*ll_append to better reflect what it does and there is now ds_*ll_add to add data anywhere in the ll. --- README.md | 4 ++-- ds.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- ds.h | 32 ++++++++++++++++++++++----- test.c | 18 ++++++++++----- 4 files changed, 104 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e8a3568..650a3c6 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_insert(ll, a); // [ "one" ] -ds_sll_insert(ll, b); // [ "one", "two" ] +ds_sll_append(ll, a); // [ "one" ] +ds_sll_append(ll, b); // [ "one", "two" ] ds_ll_foreach(ds_sll_t, ll) { puts(cur->data); // one diff --git a/ds.c b/ds.c index 661b482..25f36b3 100644 --- a/ds.c +++ b/ds.c @@ -40,7 +40,67 @@ ds_dll_t } int -ds_sll_insert(ds_sll_t *ll, void *data) +ds_sll_add(ds_sll_t **ll, void *data, unsigned x) +{ + int i; + ds_sll_t *cur, *prev, *new; + 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; + } + } + + return -1; +} + +int +ds_dll_add(ds_dll_t **ll, void *data, unsigned x) +{ + int i; + ds_dll_t *cur, *new; + 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; + } + } + + return -1; +} + +int +ds_sll_append(ds_sll_t *ll, void *data) { if (!ll || !data) { return -1; @@ -60,7 +120,7 @@ ds_sll_insert(ds_sll_t *ll, void *data) } int -ds_dll_insert(ds_dll_t *ll, void *data) +ds_dll_append(ds_dll_t *ll, void *data) { if (!ll || !data) { return -1; @@ -241,7 +301,7 @@ ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data) /* get the ll and put the data into it */ ll = hmp->data[hash_pos]; - if (ds_sll_insert(ll, kv) != 0) { + if (ds_sll_append(ll, kv) != 0) { return -1; } diff --git a/ds.h b/ds.h index a8fbb3f..93e99db 100644 --- a/ds.h +++ b/ds.h @@ -55,24 +55,46 @@ ds_sll_t *ds_sll_new_node(void *data); ds_dll_t *ds_dll_new_node(void *data); /** - * @brief data to insert into a singly linked list. This will use + * @brief data to add at x 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 add + * @param x the position to add it at * @return 0 on success */ -int ds_sll_insert(ds_sll_t *ll, void *data); +int ds_sll_add(ds_sll_t **ll, void *data, unsigned x); /** - * @brief data to insert into a doubly linked list. This will use - * ds_sll_new_node to create the node for you. + * @brief data to add at x 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 add + * @param x the position to add it at * @return 0 on success */ -int ds_dll_insert(ds_dll_t *ll, void *data); +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); /** * @brief remove an index from a singly linked list diff --git a/test.c b/test.c index 2e99a9a..dc84bc9 100644 --- a/test.c +++ b/test.c @@ -30,29 +30,35 @@ int main(int argc, char *argv[]) { test("sll", - char *a = "one"; + char *a = "a"; + char *b = "b"; ds_sll_t *tmp; it("creates a new linked list", tmp = ds_sll_init()); free(tmp); ds_sll_t *ll = ds_sll_new_node(a); - it("inserts an invalid item", ds_sll_insert(ll, NULL) == -1); + it("appends an invalid item", ds_sll_append(ll, NULL) == -1); it("removes an invalid index", ds_sll_remove(&ll, 1234) == NULL); - it("removes an item", a == ds_sll_remove(&ll, 0)); + 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); ); test("dll", - char *a = "one"; + char *a = "a"; + char *b = "b"; ds_dll_t *tmp; it("creates a new linked list", tmp = ds_dll_init()); free(tmp); ds_dll_t *ll = ds_dll_new_node(a); - it("inserts an invalid item", ds_dll_insert(ll, NULL) == -1); + it("appends an invalid item", ds_dll_append(ll, NULL) == -1); it("removes an invalid index", ds_dll_remove(&ll, 1234) == NULL); - it("removes an item", a == ds_dll_remove(&ll, 0)); + 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); ); test("hmp", From 945343daa08986878de0476bce56817b450a3278 Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 21:47:45 -0500 Subject: [PATCH 5/7] feat(stack): introduce a stack ds, internally this uses a sll --- README.md | 14 ++++++++++++++ ds.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ds.h | 38 ++++++++++++++++++++++++++++++++++++++ test.c | 22 ++++++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/README.md b/README.md index 650a3c6..1affa24 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,20 @@ 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 25f36b3..73ab51a 100644 --- a/ds.c +++ b/ds.c @@ -367,3 +367,56 @@ void 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; +} diff --git a/ds.h b/ds.h index 93e99db..e7bec5c 100644 --- a/ds.h +++ b/ds.h @@ -22,6 +22,11 @@ typedef struct { 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) /** @@ -168,4 +173,37 @@ 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 dc84bc9..1031eb4 100644 --- a/test.c +++ b/test.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -76,4 +77,25 @@ main(int argc, char *argv[]) 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); + ); } From edbe9ba3b8206909742cc8784ccf55f2221f1d3d Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 21:48:41 -0500 Subject: [PATCH 6/7] fix(test): improve testing macros --- test.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/test.c b/test.c index 1031eb4..32942a6 100644 --- a/test.c +++ b/test.c @@ -5,21 +5,22 @@ #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\n", _test_name, message); \ - _tests_passed--; \ - } \ +#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--; \ + } \ } while (0) typedef struct { From 9daffd4ed1883ea50ae94b14275b46937cc348ce Mon Sep 17 00:00:00 2001 From: Squibid Date: Sat, 15 Nov 2025 21:49:00 -0500 Subject: [PATCH 7/7] fix: minor formatting --- ds.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ds.h b/ds.h index e7bec5c..7db0049 100644 --- a/ds.h +++ b/ds.h @@ -14,12 +14,12 @@ 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 {