Compare commits

...

10 Commits

4 changed files with 154 additions and 53 deletions

View File

@@ -7,7 +7,8 @@ Example of working with a singly linked list (sll):
```c ```c
char *a = "one"; char *a = "one";
char *b = "two"; char *b = "two";
ds_sll_t *ll = ds_sll_new_node(a); // [ "one" ] ds_sll_t *ll = ds_sll_init();
ds_sll_insert(ll, a); // [ "one" ]
ds_sll_insert(ll, b); // [ "one", "two" ] ds_sll_insert(ll, b); // [ "one", "two" ]
ds_ll_foreach(ds_sll_t, ll) { ds_ll_foreach(ds_sll_t, ll) {
puts(cur->data); puts(cur->data);
@@ -22,28 +23,28 @@ datatypes.
## Hash Map ## Hash Map
```c ```c
struct complex { typedef struct {
int num; int num;
char *str; char *str;
}; } complex ;
struct complex *a = calloc(1, sizeof(struct complex)); complex *a = calloc(1, sizeof(complex));
a->num = 1; a->num = 1;
a->str = "abc"; a->str = "abc";
struct complex *b = calloc(1, sizeof(struct complex)); complex *b = calloc(1, sizeof(complex));
b->num = 2; b->num = 2;
b->str = "def"; b->str = "def";
ds_hmp_t *hmp = ds_hmp_init(101); ds_hmp_t *hmp = ds_hmp_init(101);
ds_hmp_insert(hmp, a->str, a); // [ (23)[ [ a->str, a ] ] ] ds_hmp_insert(hmp, a->str, a); // [ (23)[ [ a->str, a ] ] ]
ds_hmp_insert(hmp, b->str, b); // [ (23)[ [ a->str, a ] ], (58)[ [ b->str, b ] ] ds_hmp_insert(hmp, b->str, b); // [ (23)[ [ a->str, a ] ], (58)[ [ b->str, b ] ]
struct complex *pa = ds_hmp_remove(hmp, a->str); // a complex *pa = ds_hmp_remove(hmp, a->str); // a
free(pa->str); free(pa->str);
free(pa); free(pa);
ds_hmp_free(&hmp); ds_hmp_free(&hmp, NULL);
free(b); free(b);
``` ```
# TODO # TODO
- [ ] more data structures - [ ] more data structures
- [ ] tests - [x] tests

75
ds.c
View File

@@ -3,6 +3,18 @@
#include "ds.h" #include "ds.h"
ds_sll_t
*ds_sll_init(void)
{
return ds_sll_new_node(NULL);
}
ds_dll_t
*ds_dll_init(void)
{
return ds_dll_new_node(NULL);
}
ds_sll_t ds_sll_t
*ds_sll_new_node(void *data) *ds_sll_new_node(void *data)
{ {
@@ -27,33 +39,45 @@ ds_dll_t
return node; return node;
} }
void int
ds_sll_insert(ds_sll_t *ll, void *data) ds_sll_insert(ds_sll_t *ll, void *data)
{ {
if (!ll || !data) {
return -1;
}
ds_ll_foreach(ds_sll_t, ll) { ds_ll_foreach(ds_sll_t, ll) {
if (!cur->data) { if (!cur->data) {
cur->data = data; cur->data = data;
return; return 0;
} else if (!cur->next) { } else if (!cur->next) {
cur->next = ds_sll_new_node(data); cur->next = ds_sll_new_node(data);
return; return 0;
} }
} }
return -1;
} }
void int
ds_dll_insert(ds_dll_t *ll, void *data) ds_dll_insert(ds_dll_t *ll, void *data)
{ {
if (!ll || !data) {
return -1;
}
ds_ll_foreach(ds_dll_t, ll) { ds_ll_foreach(ds_dll_t, ll) {
if (!cur->data) { if (!cur->data) {
cur->data = data; cur->data = data;
return; return 0;
} else if (!cur->next) { } else if (!cur->next) {
cur->next = ds_dll_new_node(data); cur->next = ds_dll_new_node(data);
cur->next->prev = cur; cur->next->prev = cur;
return; return 0;
} }
} }
return -1;
} }
void void
@@ -63,6 +87,7 @@ void
void *data; void *data;
ds_sll_t *cur, *rm; ds_sll_t *cur, *rm;
rm = NULL;
if (!ll || !*ll) { if (!ll || !*ll) {
return NULL; return NULL;
} }
@@ -102,11 +127,12 @@ void
void *data; void *data;
ds_dll_t *cur, *rm; ds_dll_t *cur, *rm;
rm = NULL;
if (!ll || !*ll) { if (!ll || !*ll) {
return NULL; return NULL;
} }
for (i = -1, cur = *ll;; i++, cur = cur->next) { for (i = -1, cur = *ll; cur; i++, cur = cur->next) {
if (i + 1 == idx) { if (i + 1 == idx) {
if (idx == 0) { if (idx == 0) {
rm = cur; rm = cur;
@@ -145,6 +171,10 @@ ds_hmp_t
{ {
ds_hmp_t *hmp; ds_hmp_t *hmp;
if (!data_len) {
return NULL;
}
hmp = calloc(1, sizeof(ds_hmp_t)); hmp = calloc(1, sizeof(ds_hmp_t));
hmp->data_len = data_len; hmp->data_len = data_len;
hmp->data = calloc(data_len, sizeof(ds_sll_t **)); hmp->data = calloc(data_len, sizeof(ds_sll_t **));
@@ -152,7 +182,7 @@ ds_hmp_t
return hmp; return hmp;
} }
void int
ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv)) ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv))
{ {
int i; int i;
@@ -160,7 +190,7 @@ ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv))
ds_sll_t *ll; ds_sll_t *ll;
if (!hmp || !*hmp) { if (!hmp || !*hmp) {
return; return -1;
} }
for (i = 0; i < (*hmp)->data_len; i++) { for (i = 0; i < (*hmp)->data_len; i++) {
@@ -179,6 +209,8 @@ ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv))
} }
free((*hmp)->data); free((*hmp)->data);
free(*hmp); free(*hmp);
return 0;
} }
int int
@@ -194,25 +226,36 @@ _ds_hmp_gen_hash(char *str)
return hash; return hash;
} }
void int
ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data) ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data)
{ {
_ds_hmp_kv_t *kv; _ds_hmp_kv_t *kv;
ds_sll_t *ll; ds_sll_t *ll;
unsigned hash_pos; unsigned hash_pos;
if (!hmp || !key || !data) {
return -1;
}
kv = malloc(sizeof(_ds_hmp_kv_t)); kv = malloc(sizeof(_ds_hmp_kv_t));
kv->key = key; kv->key = key;
kv->val = data; kv->val = data;
hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len;
if (!hmp->data[hash_pos]) { if (!hmp->data[hash_pos]) {
hmp->data[hash_pos] = calloc(1, sizeof(ds_sll_t)); hmp->data[hash_pos] = ds_sll_init();
if (!hmp->data[hash_pos]) {
return -1;
}
} }
/* get the ll and put the data into it */ /* get the ll and put the data into it */
ll = hmp->data[hash_pos]; ll = hmp->data[hash_pos];
ds_sll_insert(ll, kv); if (ds_sll_insert(ll, kv) != 0) {
return -1;
}
return 0;
} }
void void
@@ -221,6 +264,10 @@ void
ds_sll_t *cur, *ll; ds_sll_t *cur, *ll;
unsigned hash_pos; unsigned hash_pos;
if (!hmp || !key) {
return NULL;
}
hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len;
ll = hmp->data[hash_pos]; ll = hmp->data[hash_pos];
if (!ll) { if (!ll) {
@@ -245,6 +292,10 @@ void
ds_sll_t *ll, *cur; ds_sll_t *ll, *cur;
_ds_hmp_kv_t *kv; _ds_hmp_kv_t *kv;
if (!hmp || !key) {
return NULL;
}
hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len; hash_pos = _ds_hmp_gen_hash(key) % hmp->data_len;
ll = hmp->data[hash_pos]; ll = hmp->data[hash_pos];
if (!ll) { if (!ll) {

26
ds.h
View File

@@ -24,6 +24,20 @@ typedef struct {
#define ds_ll_foreach(t, ll) for (t *cur = ll; cur; cur = cur->next) #define ds_ll_foreach(t, ll) for (t *cur = ll; cur; cur = cur->next)
/**
* @brief initialize a new singly linked list
*
* @return the new linked list
*/
ds_sll_t *ds_sll_init(void);
/**
* @brief initialize a new doubly linked list
*
* @return the new linked list
*/
ds_dll_t *ds_dll_init(void);
/** /**
* @brief create a new allocated node for a singly linked list * @brief create a new allocated node for a singly linked list
* *
@@ -46,8 +60,9 @@ ds_dll_t *ds_dll_new_node(void *data);
* *
* @param ll singly linked list * @param ll singly linked list
* @param data data you want to add * @param data data you want to add
* @return 0 on success
*/ */
void ds_sll_insert(ds_sll_t *ll, void *data); int ds_sll_insert(ds_sll_t *ll, void *data);
/** /**
* @brief data to insert into a doubly linked list. This will use * @brief data to insert into a doubly linked list. This will use
@@ -55,8 +70,9 @@ void ds_sll_insert(ds_sll_t *ll, void *data);
* *
* @param ll doubly linked list * @param ll doubly linked list
* @param data data you want to add * @param data data you want to add
* @return 0 on success
*/ */
void ds_dll_insert(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 * @brief remove an index from a singly linked list
@@ -88,8 +104,9 @@ ds_hmp_t *ds_hmp_init(int data_len);
* @brief free all data allocated by ds_hmp_init and ds_hmp_insert * @brief free all data allocated by ds_hmp_init and ds_hmp_insert
* *
* @param hmp pointer to the hashmap * @param hmp pointer to the hashmap
* @return 0 on success
*/ */
void ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv)); int ds_hmp_free(ds_hmp_t **hmp, void kv_callback(_ds_hmp_kv_t *kv));
/** /**
* @brief generate a numerical hash from a given string. You shouldn't need to * @brief generate a numerical hash from a given string. You shouldn't need to
@@ -107,8 +124,9 @@ int _ds_hmp_gen_hash(char *str);
* @param hmp the hashmap to insert into * @param hmp the hashmap to insert into
* @param key the key * @param key the key
* @param data the data * @param data the data
* @return 0 on success
*/ */
void ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data); int ds_hmp_insert(ds_hmp_t *hmp, char *key, void *data);
/** /**
* @brief get something from a hashmap using it's key * @brief get something from a hashmap using it's key

89
test.c
View File

@@ -1,42 +1,73 @@
#include "ds.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
struct complex { #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 it(message, test) do { \
_tests++; \
if (!(test)) { \
printf("%s %s FAILED\n", _test_name, message); \
_tests_passed--; \
} \
} while (0)
typedef struct {
int num; int num;
char *str; char *str;
}; } complex;
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *a = "one"; test("sll",
char *b = "two"; char *a = "one";
ds_sll_t *ll = ds_sll_new_node(a); // [ "one" ]
ds_sll_insert(ll, b); // [ "one", "two" ]
ds_ll_foreach(ds_sll_t, ll) {
puts(cur->data);
}
ds_sll_remove(&ll, 1234);
char *pa = ds_sll_remove(&ll, 0); // [ "two" ]
char *pb = ds_sll_remove(&ll, 0); // [ ]
struct complex *a2 = calloc(1, sizeof(struct complex)); ds_sll_t *tmp;
a2->num = 1; it("ensures creates a new linked list", tmp = ds_sll_init());
a2->str = "abc"; free(tmp);
struct complex *b2 = calloc(1, sizeof(struct complex));
b2->num = 2;
b2->str = "def";
ds_hmp_t *hmp = ds_hmp_init(101); ds_sll_t *ll = ds_sll_new_node(a);
ds_hmp_insert(hmp, a2->str, a2); // [ (23)[ [ a->str, a ] ] ] it("inserts an invalid item", ds_sll_insert(ll, NULL) == -1);
ds_hmp_insert(hmp, b2->str, b2); // [ (23)[ [ a->str, a ] ], (58)[ [ b->str, b ] ] it("removes an invalid index", ds_sll_remove(&ll, 1234) == NULL);
struct complex *pa2 = ds_hmp_remove(hmp, a2->str); // [ (23)[ [ a->str, a ] ] it("removes an item", a == ds_sll_remove(&ll, 0));
struct complex *pb2 = ds_hmp_remove(hmp, b2->str); // [ (58)[ [ b->str, b ] ] );
ds_hmp_free(&hmp);
puts(pa2->str);
puts(pb2->str);
free(pa2); test("dll",
free(pb2); char *a = "one";
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("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";
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);
);
} }