diff options
| author | @syxhe <https://t.me/syxhe> | 2025-03-24 15:02:03 -0500 |
|---|---|---|
| committer | @syxhe <https://t.me/syxhe> | 2025-03-24 15:02:03 -0500 |
| commit | 7083f1d8f72d4e45a82fd40cd4822356429f0e23 (patch) | |
| tree | 5d7ce6c9ab478f4d3e297fa3d66fa129cb5b1928 /src | |
| parent | b3bd3df103a5a75d267b2b79e85558768b1dc4bb (diff) | |
Refactor a bunch of the linked list implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 8 | ||||
| -rw-r--r-- | src/ll.c | 166 | ||||
| -rw-r--r-- | src/ll.h | 36 |
3 files changed, 154 insertions, 56 deletions
diff --git a/src/Makefile b/src/Makefile index 4a0d316..d12eb72 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -20,11 +20,11 @@ BINARIES := main encryption | |||
| 20 | 20 | ||
| 21 | all: main | 21 | all: main |
| 22 | 22 | ||
| 23 | main: main.o shared.o | 23 | main: main.o shared.o ll.o arena.o |
| 24 | 24 | ||
| 25 | ll.o: ll.c ll.h | 25 | ll.o: ll.c ll.h shared.h |
| 26 | main.o: main.c | 26 | main.o: main.c shared.h |
| 27 | arena.o: arena.c arena.h | 27 | arena.o: arena.c arena.h shared.h |
| 28 | shared.o: shared.c shared.h | 28 | shared.o: shared.c shared.h |
| 29 | 29 | ||
| 30 | encryption: encryption.c encryption.h shared.o shared.h | 30 | encryption: encryption.c encryption.h shared.o shared.h |
| @@ -3,6 +3,49 @@ | |||
| 3 | 3 | ||
| 4 | #include <stddef.h> | 4 | #include <stddef.h> |
| 5 | #include <stdlib.h> | 5 | #include <stdlib.h> |
| 6 | #include <errno.h> | ||
| 7 | |||
| 8 | typedef struct dll { | ||
| 9 | void *data; | ||
| 10 | dlinkedlist_freecallback dfreecb; | ||
| 11 | |||
| 12 | struct dll *next; | ||
| 13 | struct dll *prev; | ||
| 14 | } dllnode; | ||
| 15 | |||
| 16 | typedef struct dlinkedlist { | ||
| 17 | dllnode *start; | ||
| 18 | dllnode *end; | ||
| 19 | size_t size; | ||
| 20 | } dlinkedlist; | ||
| 21 | |||
| 22 | dllnode* dllnode_init(void *data, dlinkedlist_freecallback dfreecb) { | ||
| 23 | dllnode *n = xcalloc(1, sizeof(*n)); | ||
| 24 | n->next = NULL; | ||
| 25 | n->prev = NULL; | ||
| 26 | n->data = data; | ||
| 27 | n->dfreecb = dfreecb; | ||
| 28 | |||
| 29 | return n; | ||
| 30 | } | ||
| 31 | |||
| 32 | int dllnode_free(dllnode **n) { | ||
| 33 | if(!n) { | ||
| 34 | errno = EINVAL; | ||
| 35 | return -1; | ||
| 36 | } | ||
| 37 | if(!(*n)) { | ||
| 38 | errno = EINVAL; | ||
| 39 | return -1; | ||
| 40 | } | ||
| 41 | |||
| 42 | if((*n)->dfreecb != NULL) | ||
| 43 | (*n)->dfreecb((*n)->data); | ||
| 44 | free(*n); | ||
| 45 | *n = NULL; | ||
| 46 | |||
| 47 | return 0; | ||
| 48 | } | ||
| 6 | 49 | ||
| 7 | void dlinkedlist_init(dlinkedlist **ll) { | 50 | void dlinkedlist_init(dlinkedlist **ll) { |
| 8 | (*ll) = xcalloc(1, sizeof(**ll)); | 51 | (*ll) = xcalloc(1, sizeof(**ll)); |
| @@ -18,11 +61,7 @@ void dlinkedlist_free(dlinkedlist **ll) { | |||
| 18 | dllnode *p = (*ll)->start, *n; | 61 | dllnode *p = (*ll)->start, *n; |
| 19 | while(p != NULL) { | 62 | while(p != NULL) { |
| 20 | n = p->next; | 63 | n = p->next; |
| 21 | 64 | dllnode_free(&p); | |
| 22 | if(p->dfreecb != NULL) | ||
| 23 | p->dfreecb(p->data); | ||
| 24 | free(p); | ||
| 25 | |||
| 26 | p = n; | 65 | p = n; |
| 27 | } | 66 | } |
| 28 | 67 | ||
| @@ -31,17 +70,15 @@ void dlinkedlist_free(dlinkedlist **ll) { | |||
| 31 | return; | 70 | return; |
| 32 | } | 71 | } |
| 33 | 72 | ||
| 34 | int dlinkedlist_firstitem(dlinkedlist * const ll, void *data, int (*dfreecb)(void*)) { | 73 | int dlinkedlist_firstitem(dlinkedlist * const ll, void *data, dlinkedlist_freecallback dfreecb) { |
| 35 | if(!ll) | 74 | if(!ll) { |
| 75 | errno = EINVAL; | ||
| 36 | return -1; | 76 | return -1; |
| 77 | } | ||
| 37 | if(ll->size != 0) | 78 | if(ll->size != 0) |
| 38 | return 0; | 79 | return 0; |
| 39 | 80 | ||
| 40 | dllnode *n = xcalloc(1, sizeof(*n)); | 81 | dllnode *n = dllnode_init(data, dfreecb); |
| 41 | n->next = NULL; | ||
| 42 | n->prev = NULL; | ||
| 43 | n->data = data; | ||
| 44 | n->dfreecb = dfreecb; | ||
| 45 | 82 | ||
| 46 | ll->start = n; | 83 | ll->start = n; |
| 47 | ll->end = n; | 84 | ll->end = n; |
| @@ -50,15 +87,15 @@ int dlinkedlist_firstitem(dlinkedlist * const ll, void *data, int (*dfreecb)(voi | |||
| 50 | return 1; | 87 | return 1; |
| 51 | } | 88 | } |
| 52 | 89 | ||
| 53 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, int (*dfreecb)(void*)) { | 90 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dlinkedlist_freecallback dfreecb) { |
| 54 | if(!ll) | 91 | if(!ll) { |
| 92 | errno = EINVAL; | ||
| 55 | return -1; | 93 | return -1; |
| 94 | } | ||
| 56 | if(dlinkedlist_firstitem(ll, data, dfreecb) > 0) | 95 | if(dlinkedlist_firstitem(ll, data, dfreecb) > 0) |
| 57 | return 0; | 96 | return 0; |
| 58 | 97 | ||
| 59 | dllnode *n = xcalloc(1, sizeof(*n)); | 98 | dllnode *n = dllnode_init(data, dfreecb); |
| 60 | n->data = data; | ||
| 61 | n->dfreecb = dfreecb; | ||
| 62 | n->prev = NULL; | 99 | n->prev = NULL; |
| 63 | n->next = ll->start; | 100 | n->next = ll->start; |
| 64 | 101 | ||
| @@ -69,15 +106,15 @@ int dlinkedlist_insert(dlinkedlist * const ll, void *data, int (*dfreecb)(void*) | |||
| 69 | return 0; | 106 | return 0; |
| 70 | } | 107 | } |
| 71 | 108 | ||
| 72 | int dlinkedlist_append(dlinkedlist * const ll, void *data, int (*dfreecb)(void*)) { | 109 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dlinkedlist_freecallback dfreecb) { |
| 73 | if(!ll) | 110 | if(!ll) { |
| 111 | errno = EINVAL; | ||
| 74 | return -1; | 112 | return -1; |
| 113 | } | ||
| 75 | if(dlinkedlist_firstitem(ll, data, dfreecb) > 0) | 114 | if(dlinkedlist_firstitem(ll, data, dfreecb) > 0) |
| 76 | return 0; | 115 | return 0; |
| 77 | 116 | ||
| 78 | dllnode *n = xcalloc(1, sizeof(*n)); | 117 | dllnode *n = dllnode_init(data, dfreecb); |
| 79 | n->data = data; | ||
| 80 | n->dfreecb = dfreecb; | ||
| 81 | n->prev = ll->end; | 118 | n->prev = ll->end; |
| 82 | n->next = NULL; | 119 | n->next = NULL; |
| 83 | 120 | ||
| @@ -88,12 +125,89 @@ int dlinkedlist_append(dlinkedlist * const ll, void *data, int (*dfreecb)(void*) | |||
| 88 | return 0; | 125 | return 0; |
| 89 | } | 126 | } |
| 90 | 127 | ||
| 91 | dllnode *dlinkedlist_get(const dlinkedlist * const ll, size_t index) { | 128 | dllnode *dlinkedlist_getnode(const dlinkedlist * const ll, size_t index) { |
| 92 | if(index >= ll->size) | 129 | if(!ll) { |
| 130 | errno = EINVAL; | ||
| 93 | return NULL; | 131 | return NULL; |
| 132 | } | ||
| 133 | if(index >= ll->size) { | ||
| 134 | errno = EINVAL; | ||
| 135 | return NULL; | ||
| 136 | } | ||
| 137 | |||
| 138 | // No need to loop if the desired indices are either the first or last | ||
| 139 | if(index == 0) | ||
| 140 | return ll->start->data; | ||
| 141 | if(index == (ll->size - 1)) | ||
| 142 | return ll->end->data; | ||
| 94 | 143 | ||
| 95 | dllnode *p = ll->start; | 144 | int spoint = (index < (ll->size / 2)); |
| 96 | for(size_t i = 0; i < index && p != NULL; i++, p = p->next); | 145 | dllnode *p = (spoint) ? ll->start : ll->end; |
| 146 | size_t i = (spoint) ? 0 : ll->size-1; | ||
| 147 | |||
| 148 | // This should (theoretically) cut down on fetch times | ||
| 149 | for(; ((spoint) ? (i < index) : (i > index)) && p != NULL; ((spoint) ? i++ : i--), p = ((spoint) ? p->next : p->prev)); | ||
| 150 | |||
| 151 | // old imp (above is untested) | ||
| 152 | // for(size_t i = 0; i < index && p != NULL; i++, p = p->next); | ||
| 97 | 153 | ||
| 98 | return p; | 154 | return p; |
| 155 | } | ||
| 156 | |||
| 157 | void *dlinkedlist_get(const dlinkedlist * const ll, size_t index) { | ||
| 158 | dllnode *n = dlinkedlist_getnode(ll, index); | ||
| 159 | if(!n) | ||
| 160 | return NULL; | ||
| 161 | |||
| 162 | return n->data; | ||
| 163 | } | ||
| 164 | |||
| 165 | void *dlinkedlist_getfirst(const dlinkedlist * const ll) { | ||
| 166 | return dlinkedlist_get(ll, 0); | ||
| 167 | } | ||
| 168 | |||
| 169 | void *dlinkedlist_getlast(const dlinkedlist * const ll) { | ||
| 170 | return dlinkedlist_get(ll, ll->size - 1); | ||
| 171 | } | ||
| 172 | |||
| 173 | int dlinkedlist_remove(dlinkedlist * const ll, size_t index) { | ||
| 174 | if(!ll) { | ||
| 175 | errno = EINVAL; | ||
| 176 | return -1; | ||
| 177 | } | ||
| 178 | if(index >= ll->size) { | ||
| 179 | errno = EINVAL; | ||
| 180 | return -1; | ||
| 181 | } | ||
| 182 | |||
| 183 | dllnode *current = dlinkedlist_getnode(ll, index); | ||
| 184 | if(!current) { | ||
| 185 | /* gcc is halucinating an error where there isn't one, claiming that the size of the linked list could, somehow, magically | ||
| 186 | // grow in the time it takes to grab the desired node, and thus return NULL and cause a NULL Dereference. I am willing to | ||
| 187 | // be humble and state that the compiler is probably smarter than me, and there is MAYBE an edge case where is COULD occur, | ||
| 188 | // and thus I should do this check, but I'm unconvinced */ | ||
| 189 | errno = ENOTRECOVERABLE; | ||
| 190 | return -2; | ||
| 191 | } | ||
| 192 | |||
| 193 | // Handle special cases of removing the start or end | ||
| 194 | if(index == 0) { | ||
| 195 | ll->start = current->next; | ||
| 196 | ll->start->prev = NULL; | ||
| 197 | } else if(index == (ll->size - 1)) { | ||
| 198 | ll->end = current->prev; | ||
| 199 | ll->end->next = NULL; | ||
| 200 | } else { | ||
| 201 | // Set the prior's next to the next, set the next's prior to the prior, delete the current one | ||
| 202 | dllnode *prev = current->prev; | ||
| 203 | dllnode *next = current->next; | ||
| 204 | prev->next = next; | ||
| 205 | next->prev = prev; | ||
| 206 | } | ||
| 207 | // Wow, I genuinely can't think of the last time I've needed to use an if-elif-else block | ||
| 208 | |||
| 209 | dllnode_free(¤t); | ||
| 210 | ll->size--; | ||
| 211 | |||
| 212 | return 0; | ||
| 99 | } \ No newline at end of file | 213 | } \ No newline at end of file |
| @@ -1,35 +1,19 @@ | |||
| 1 | #ifndef __VXGG_REWRITE___SHARED_H___28542989122405___ | 1 | #ifndef __VXGG_REWRITE___LL_H___305861098005___ |
| 2 | #define __VXGG_REWRITE___SHARED_H___28542989122405___ | 2 | #define __VXGG_REWRITE___LL_H___305861098005___ |
| 3 | 3 | ||
| 4 | #include <stddef.h> | 4 | #include <stddef.h> |
| 5 | 5 | ||
| 6 | typedef struct dll { | 6 | typedef int (*dlinkedlist_freecallback)(void*); |
| 7 | void *data; | 7 | typedef struct dlinkedlist dlinkedlist; |
| 8 | int (*dfreecb)(void*); | ||
| 9 | 8 | ||
| 10 | struct dll *next; | ||
| 11 | struct dll *prev; | ||
| 12 | } dllnode; | ||
| 13 | |||
| 14 | typedef struct { | ||
| 15 | dllnode *start; | ||
| 16 | dllnode *end; | ||
| 17 | size_t size; | ||
| 18 | } dlinkedlist; | ||
| 19 | |||
| 20 | // Initialize a dlinkedlist | ||
| 21 | void dlinkedlist_init(dlinkedlist **ll); | 9 | void dlinkedlist_init(dlinkedlist **ll); |
| 22 | |||
| 23 | // Free a dlinkedlist and its elements | ||
| 24 | void dlinkedlist_free(dlinkedlist **ll); | 10 | void dlinkedlist_free(dlinkedlist **ll); |
| 25 | 11 | ||
| 26 | // Insert an element to the beginning of the list | 12 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dlinkedlist_freecallback dfreecb); |
| 27 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, int (*dfreecb)(void*)); | 13 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dlinkedlist_freecallback dfreecb); |
| 28 | 14 | void *dlinkedlist_get(const dlinkedlist * const ll, size_t index); | |
| 29 | // Insert an element to the end of the list | 15 | void *dlinkedlist_getfirst(const dlinkedlist * const ll); |
| 30 | int dlinkedlist_append(dlinkedlist * const ll, void *data, int (*dfreecb)(void*)); | 16 | void *dlinkedlist_getlast(const dlinkedlist * const ll); |
| 31 | 17 | int dlinkedlist_remove(dlinkedlist * const ll, size_t index); | |
| 32 | // Get the element from a dlinkedlist at index | ||
| 33 | dllnode *dlinkedlist_get(const dlinkedlist * const ll, size_t index); | ||
| 34 | 18 | ||
| 35 | #endif \ No newline at end of file | 19 | #endif \ No newline at end of file |
