From 2c2bdb8b66e386e14b5cc1a35abfbf242dcf2018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 4 Feb 2019 00:36:57 +0100 Subject: Work on propper memmory management for linked lists. --- linked_list.h | 7 +++--- linked_list.inc.h | 72 ++++++++++++++++++++++++++++++++++++++++++------------- macro.h | 2 ++ main.c | 2 +- strbuf.c | 5 ++++ trie.inc.h | 6 +++-- vcal.c | 17 ++++++++++++- vcal.h | 10 ++++++++ 8 files changed, 97 insertions(+), 24 deletions(-) diff --git a/linked_list.h b/linked_list.h index 666524be..a76c3443 100644 --- a/linked_list.h +++ b/linked_list.h @@ -6,8 +6,6 @@ #define LLIST(T) TP(llist__, T) #define LINK(T) TP(llist_link__, T) -#define LLIST_INIT(T) CONSTRUCTOR_GEN(llist, T, 0); -#define LLIST_FREE(T) TP(llist_free__, T) #define LLIST_CONS(T) TP(llist_cons__, T) #endif /* LINKED_LIST_H */ @@ -27,12 +25,15 @@ typedef struct { } LLIST(TYPE); int CONSTRUCTOR_DECL ( LLIST(TYPE) ); -int LLIST_FREE(TYPE) ( LLIST(TYPE)* ); +int FREE_DECL( LLIST(TYPE) ); int CONSTRUCTOR_DECL ( LINK(TYPE) ); +int CONSTRUCTOR_DECL ( LINK(TYPE), TYPE* val ); int LLIST_CONS(TYPE) ( LLIST(TYPE)* lst, TYPE* val); int DEEP_COPY(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* src ); +int APPEND(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* new ); + #endif /* TYPE */ diff --git a/linked_list.inc.h b/linked_list.inc.h index 260eaf0d..a878d075 100644 --- a/linked_list.inc.h +++ b/linked_list.inc.h @@ -4,21 +4,29 @@ int CONSTRUCTOR_DECL ( LLIST(TYPE) ) { this->length = 0; - this->head = NULL; - this->tail = NULL; - this->cur = NULL; + NEW(LINK(TYPE), head); + NEW(LINK(TYPE), tail); + this->head = head; + this->tail = tail; + head->after = tail; + tail->before = head; + this->cur = head; return 0; } -int LLIST_FREE(TYPE) (LLIST(TYPE)* this ) { +int FREE_DECL( LLIST(TYPE) ) { LINK(TYPE) *node, *next; - node = this->head; - while (node != NULL) { + node = this->head->after; + while (node->after != NULL) { next = node->after; - FFREE(TYPE, node->value); - free(node); + if (node->value != NULL) { + FFREE(TYPE, node->value); + } + // free(node); node = next; } + free (this->head); + free (this->tail); this->length = 0; return 0; } @@ -30,25 +38,32 @@ int CONSTRUCTOR_DECL ( LINK(TYPE) ) { return 0; } +int CONSTRUCTOR_DECL ( LINK(TYPE), TYPE* val ) { + this->before = NULL; + this->after = NULL; + this->value = val; + return 0; +} + int LLIST_CONS(TYPE) ( LLIST(TYPE)* lst, TYPE* val) { - NEW(LINK(TYPE), l); - l->after = lst->head; - if (l->after != NULL) { - l->after->before = l; - } - lst->head = l; - l->value = val; + NEW(LINK(TYPE), l, val); + + l->after = lst->head->after; + lst->head->after = l; + l->after->before = l; + l->before = lst->head; ++lst->length; + // TODO do I want to change that? lst->cur = l; return 0; } int DEEP_COPY(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* src ) { - LINK(TYPE)* n = src->head; + LINK(TYPE)* n = src->head->after; - while (n != NULL) { + while (n->after != NULL) { NEW(TYPE, cpy); DEEP_COPY(TYPE)(cpy, n->value); LLIST_CONS(TYPE) ( dest, cpy ); @@ -58,4 +73,27 @@ int DEEP_COPY(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* src ) { return 0; } +/* + * TODO + * this or cons links wrong, creating infinite loops. + */ +int APPEND(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* new ) { + + dest->tail->before->after = new->head->after; + new->head->after->before = dest->tail->before; + LINK(TYPE)* old_tail = dest->tail; + dest->tail = new->tail; + dest->length += new->length; + + // free(old_tail); + // free(new->head); + + /* + * TODO `new` can now be handled as an empty husk. + * Somehow it needs to be collected + */ + + return 0; +} + #endif /* TYPE */ diff --git a/macro.h b/macro.h index 8a0a725b..a62d12d1 100644 --- a/macro.h +++ b/macro.h @@ -73,5 +73,7 @@ #define FREE_DECL(T) TP(T, __free) (T* this) #define DEEP_COPY(T) TP(deep_copy__, T) +#define RESOLVE(T) TP(resolve__, T) +#define APPEND(T) TP(append__, T) #endif /* MACRO_H */ diff --git a/main.c b/main.c index f1298431..1d1b20ed 100644 --- a/main.c +++ b/main.c @@ -43,7 +43,7 @@ int main (int argc, char* argv[argc]) { i + 1, filename, // get_property(cal.events[i], "SUMMARY")->val.mem); - get_property(cal.events[i], "SUMMARY")->vals.head->value->mem); + get_property(cal.events[i], "SUMMARY")->vals.cur->value->mem); } } else if (strcmp(args.argv[0], "-g") == 0) { if (arg_shift(&args) == 0) { diff --git a/strbuf.c b/strbuf.c index e2b8d689..e4dfb803 100644 --- a/strbuf.c +++ b/strbuf.c @@ -114,6 +114,11 @@ int strbuf_init_copy(strbuf* dest, strbuf* src) { ERR("Dest already allocated"); return 1; } + + if (src == NULL) { + ERR("Attempting to copy NULL strbuf"); + return 2; + } #endif CONSTRUCT(strbuf, dest, src->len + 1); diff --git a/trie.inc.h b/trie.inc.h index b839a7e8..61dc3701 100644 --- a/trie.inc.h +++ b/trie.inc.h @@ -46,7 +46,8 @@ int TRIE_PUT(TYPE) ( TRIE(TYPE)* trie, char* key, TYPE* val ) { last->child = t; last = t; } - last->value = val; + RESOLVE(TYPE)(&last->value, val); + // last->value = val; return 0; } else if (cur->c == subkey[0]) { /* This node belongs to the key, @@ -56,7 +57,8 @@ int TRIE_PUT(TYPE) ( TRIE(TYPE)* trie, char* key, TYPE* val ) { subkey++; } else if (subkey[0] == '\0') { /* Key finished */ - last->value = val; + // last->value = val; + RESOLVE(TYPE)(&last->value, val); return 0; } else if (cur->next != NULL) { /* This node was not part of the set, but it's sibling might */ diff --git a/vcal.c b/vcal.c index 0371a35b..73158aeb 100644 --- a/vcal.c +++ b/vcal.c @@ -26,6 +26,20 @@ int CONSTRUCTOR_DECL(vevent, char* filename) { return 0; } +int RESOLVE(content_line) + (content_line** dest, content_line* new) { + if (*dest == NULL) *dest = new; + + if (strbuf_cmp(&(*dest)->key, &new->key) != 0) { + ERR("Can't resolve between these two types"); + return 1; + } + + // printf("len = %i\n", dest->vals.length); + APPEND(LLIST(strbuf))(&(*dest)->vals, &new->vals); + return 0; +} + content_line* get_property (vevent* ev, char* key) { return TRIE_GET(content_line)(&ev->clines, key); } @@ -67,7 +81,8 @@ int content_line_copy (content_line* dest, content_line* src) { int FREE_DECL(content_line) { FREE(strbuf)(&this->key); // FREE(strbuf)(&this->val); - LLIST_FREE(strbuf)(&this->vals); + // LLIST_FREE(strbuf)(&this->vals); + FREE(LLIST(strbuf))(&this->vals); for (int i = 0; i < cline_ptr; i++) { if (clines[i] == this) { clines[i] = NULL; diff --git a/vcal.h b/vcal.h index 91eed471..a5144992 100644 --- a/vcal.h +++ b/vcal.h @@ -28,6 +28,9 @@ typedef struct { int CONSTRUCTOR_DECL(content_line); int CONSTRUCTOR_DECL(content_line, int keylen, int vallen); +int RESOLVE(content_line) + (content_line** orig, content_line* new); + #define TYPE content_line // #include "hash.h" #include "trie.h" @@ -65,6 +68,13 @@ int free_vcalendar (vcalendar* cal); */ int push_event(vcalendar* cal, vevent* ev); +/* + * NOTE + * these create a very basic garbage collector. It shouldn't be used, + * but is useful for finding lost memmory during debugging. + * TODO + * remove it. + */ extern content_line** clines; extern int cline_ptr; -- cgit v1.2.3