diff options
-rw-r--r-- | err.h | 2 | ||||
-rw-r--r-- | linked_list.h | 6 | ||||
-rw-r--r-- | linked_list.inc.h | 3 | ||||
-rw-r--r-- | macro.h | 28 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | parse.c | 38 | ||||
-rw-r--r-- | parse.h | 3 | ||||
-rw-r--r-- | strbuf.c | 12 | ||||
-rw-r--r-- | strbuf.h | 22 | ||||
-rw-r--r-- | trie.h | 5 | ||||
-rw-r--r-- | trie.inc.h | 2 | ||||
-rw-r--r-- | vcal.c | 24 | ||||
-rw-r--r-- | vcal.h | 9 |
13 files changed, 102 insertions, 54 deletions
@@ -2,8 +2,10 @@ #define ERR_H #include <stdio.h> + #define RED "\x1B[0;31m" #define RESET "\x1b[m" + #define ERR(msg) fprintf(stderr, RED "ERR" RESET " (%s:%i) %s\n", __FILE__, __LINE__, #msg) #define ERR_F(fmt, ...) fprintf(stderr, RED "ERR" RESET " (%s:%i) " fmt "\n", \ __FILE__, __LINE__, ##__VA_ARGS__) diff --git a/linked_list.h b/linked_list.h index 515fa4af..5f9e2711 100644 --- a/linked_list.h +++ b/linked_list.h @@ -26,6 +26,12 @@ typedef struct { #define LAST(lst) (lst)->tail->before INIT_F ( LLIST(TYPE) ); + +/* + * NOTE freeing a linked list alsa FFREE's all its contents. + * TODO some form of shared pointer to ensure nothing is free'd twice + * would be a good idea. + */ FREE_F ( LLIST(TYPE) ); INIT_F ( LINK(TYPE) ); diff --git a/linked_list.inc.h b/linked_list.inc.h index 1522a685..e91cdc9f 100644 --- a/linked_list.inc.h +++ b/linked_list.inc.h @@ -17,15 +17,12 @@ INIT_F ( LLIST(TYPE) ) { FREE_F (LINK(TYPE)) { if (this->before != NULL) this->before->after = NULL; if (this->after != NULL) this->after->before = NULL; - // TODO how much of value do I really wanna free? - // Should I implement some form of shared pointer? if (this->value != NULL) FFREE(TYPE, this->value); return 0; } FREE_F( LLIST(TYPE) ) { - LINK(TYPE) *n, *next; n = this->head; while ( n != NULL ) { @@ -24,9 +24,17 @@ #define VA_ARGS_NUM(...) VA_ARGS_NUM_PRIV(-1, ## __VA_ARGS__, 5, 4, 3, 2, 1, 0) /* - * Templetize - * TODO actuall documentatino - * ᐸElementTᐳ + * Templatization macros. Forms symbols on the from name<T>, which + * looks really good in debuggers and the like. Unicode characters + * written in \U notation since C apparently doesn't support unicode + * literals. + * + * Can be nested (useful for container types). + * + * Doesn't use ASCII <>, but rather some other ᐸᐳ, meaning that it's + * not a reserved character. + * + * nameᐸTᐳ */ #define TEMPL(name, T) TP4(name, \U00001438 , T, \U00001433 ) #define TEMPL_N(name, T, argcount) TP6(name, \U00001438 , T, _, argcount, \U00001433 ) @@ -38,7 +46,11 @@ #define INIT_F(T, ...) \ int __INIT_T(T, VA_ARGS_NUM(__VA_ARGS__)) (T* this __VA_OPT__(,) __VA_ARGS__) -/* Call the constructor of an object */ +/* + * Call the constructor of an object + * `int` part of the macro, to ensure that any attempt to call this + * function results in an error. + */ #define INIT(T, N, ...) \ __INIT_T(T, VA_ARGS_NUM(__VA_ARGS__)) (N __VA_OPT__(,) __VA_ARGS__) @@ -47,6 +59,9 @@ T* N = malloc(sizeof(*N)); \ INIT(T, N, __VA_ARGS__); +/* + * Reconstructs a object. Use with caution. + */ #define RENEW(T, N, ...) do { \ N = malloc(sizeof(*N)); \ INIT(T, N, __VA_ARGS__); \ @@ -67,6 +82,11 @@ /* Declare destructor */ #define FREE_F(T) int FREE(T) (T* this) +/* + * General functions that different container types may implement. + * Actuall implementation and type signature is mostly left to + * individual implementations. + */ #define DEEP_COPY(T) TEMPL(deep_copy , T) #define RESOLVE(T) TEMPL(resolve , T) #define APPEND(T) TEMPL(append , T) @@ -42,7 +42,6 @@ int main (int argc, char* argv[argc]) { printf("%3lu | %s | %s\n", i + 1, filename, - // get_property(cal.events[i], "SUMMARY")->val.mem); get_property(cal.events[i], "SUMMARY")->vals.cur->value->mem); } } else if (strcmp(args.argv[0], "-g") == 0) { @@ -55,7 +54,6 @@ int main (int argc, char* argv[argc]) { strcat(target, ".dot"); create_graph(cal.events[i], target); } - // create_graph(cal.events[0], "graph.dot"); } else { create_graph(cal.events[0], args.argv[0]); } @@ -18,25 +18,19 @@ int parse_file(char* fname, FILE* f, vcalendar* cal) { .scope = s_none, .skip_to = &skip }; - // scope_context s_ctx = s_none; int keylen = 100; int vallen = 100; int line = 0; - // NEW(vevent, ev, fname); vevent* ev = NULL; SNEW(content_line, cline, keylen, vallen); - /* - * TODO - * When a file ends with CRLF then ctx_scope == s_none, leading to - * END:VEVENT erroring as bad start of calendar. - * */ char c; while ( (c = fgetc(f)) != EOF) { + /* * A carrige return means that the current line is at an * end. The following character should always be \n. @@ -69,19 +63,24 @@ int parse_file(char* fname, FILE* f, vcalendar* cal) { } continue; } else { + /* Actuall end of line, handle values. */ + + /* Push back the last written character to the stream, + * since it's part of the next line. + */ if (ungetc(s[1], f) != s[1]) { ERR_F("%s, %i", "Failed to put character back on FILE", line); exit (2); } - /* At TRUE end of line */ if (str.ptr + 1 > vallen) { vallen = str.ptr + 1; strbuf_realloc(cline.vals.cur->value, vallen); } strbuf_copy(cline.vals.cur->value, &str); + /* TODO when do I actualy cap? */ // strbuf_cap(cline.vals.cur->value); ++line; @@ -89,8 +88,6 @@ int parse_file(char* fname, FILE* f, vcalendar* cal) { switch (handle_kv(cal, ev, &cline, line, &ctx)) { case s_event: RENEW(vevent, ev, fname); - // ev = malloc(sizeof(*ev)); - // INIT(vevent, ev, fname); break; } strbuf_soft_reset(&str); @@ -105,7 +102,16 @@ int parse_file(char* fname, FILE* f, vcalendar* cal) { } else if (p_ctx == p_key && c == ':') { if (str.ptr + 1 > keylen) { keylen = str.ptr + 1; - // TODO this might break everything + /* + * Allow for key's longer than 100 octets. It + * currently is of no use, since key's can't be + * folded. + * TODO check if everything should be unfolded at 75 + * octets, or if that is only for values. + * + * TODO earlier there was a bug here. Test if that is + * fixed and reenable this line. + */ // strbuf_realloc(&cline.key, keylen); } strbuf_copy(&cline.key, &str); @@ -149,7 +155,6 @@ int handle_kv( vevent* ev, content_line* cline, int line, - // scope_context* s_ctx parse_ctx* ctx ) { switch (ctx->scope) { @@ -157,7 +162,6 @@ int handle_kv( case s_skip: if (strbuf_c(&cline->key, "END") && strbuf_cmp(cline->vals.cur->value, ctx->skip_to)) { ctx->scope = s_calendar; - // FREE(strbuf)(ctx->skip_to); } break; @@ -176,9 +180,15 @@ int handle_kv( return ctx->scope; break; } else { - // ERR("Unsupported start", line); + + /* + * Here we found the start of some form of block + * we don't understand. Just skip everything until + * we find the matching END + */ ctx->scope = s_skip; strbuf_copy(ctx->skip_to, cline->vals.cur->value); + } } else if (strbuf_c(&cline->key, "END")) { if (strbuf_c(cline->vals.cur->value, "VCALENDAR")) { @@ -37,8 +37,7 @@ int handle_kv( vevent* ev, content_line* cline, int line, - // scope_context* s_ctx - parse_ctx* ctx + parse_ctx* ctx ); int parse_file(char* fname, FILE* f, vcalendar* cal); @@ -24,9 +24,12 @@ INIT_F(strbuf, size_t len) { int strbuf_realloc(strbuf* str, size_t len) { #ifdef SAFE_STR - if (str->mem == NULL /*|| str->alloc == -1*/) { + if (str->mem == NULL) { + /* NOTE + * this isn't an error, since + * realloc(NULL, 10) ≡ malloc(10) + */ ERR("String memory not initialized"); - // return 1; } #endif str->mem = realloc(str->mem, len); @@ -34,7 +37,6 @@ int strbuf_realloc(strbuf* str, size_t len) { return 0; } -// int strbuf_free(strbuf* str) { FREE_F(strbuf) { #ifdef SAFE_STR if (this->mem == NULL) return 1; @@ -46,9 +48,6 @@ FREE_F(strbuf) { return 0; } -/* - * TODO this should do bounds check - */ int strbuf_append(strbuf* s, char c) { #ifdef SAFE_STR if (s->len > s->alloc) { @@ -75,6 +74,7 @@ int strbuf_copy(strbuf* dest, strbuf* src) { #endif dest->len = src->len; memcpy(dest->mem, src->mem, src->len); + // TODO should this be here? strbuf_cap(dest); return 0; @@ -4,6 +4,14 @@ #include <stdlib.h> #include "macro.h" +/* + * A high level string type which holds it's own length, how much + * memmory it has allocated for itself, and a seek pointer into the + * string. + * + * Also comes with a number of functions which allow for safe(er) + * access to the memmory. + */ typedef struct { char* mem; /* TODO add support for negative ptr */ @@ -33,7 +41,6 @@ int strbuf_realloc(strbuf* str, size_t len); /* * Free's contents of str, but keeps str. */ -// int strbuf_free(strbuf* str); FREE_F(strbuf); /* @@ -57,8 +64,21 @@ int strbuf_append(strbuf* s, char c); * Calls strbuf_append with NULL. */ int strbuf_cap(strbuf* s); + +/* + * Resets the seek for strbuf to 0. + */ int strbuf_reset(strbuf* s); + +/* + * Returns a pointer to character at index. Allows mutation of the + * value pointed to by the return address. + */ char* charat(strbuf* s, unsigned int idx); + +/* + * Same as `charat`, But returns the current character. + */ char* strbuf_cur(strbuf* s); /* @@ -8,6 +8,11 @@ #define TRIE(T) TEMPL(trie, T) #define TRIE_NODE(T) TEMPL(trie_node, T) +/* + * TODO + * The DOT functions are for generating graphviz framgments. They + * realy should be moved away from here. + */ #define TRIE_DOT(T) TP(trie_to_dot__, T) #define TRIE_DOT_HELP(T) TP(trie_to_dot_helper__, T) @@ -36,7 +36,6 @@ int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val ) { cur = last->child; char* subkey = key; - // -------------------------------------------------- while (1) { if (cur == NULL) { @@ -56,7 +55,6 @@ int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val ) { subkey++; } else if (subkey[0] == '\0') { /* Key finished */ - // last->value = val; last->value = RESOLVE(TYPE)(last->value, val); return 0; } else if (cur->next != NULL) { @@ -23,12 +23,6 @@ INIT_F(vevent, char* filename) { return 0; } -/* - * Resolves a collision in some form of structure (probably a hash-map - * or a trie). If dest is NULL just return new. Otherwise mutates dest - * to have the correct form, and returns it. Destroying new in the - * process. - */ content_line* RESOLVE(content_line) (content_line* dest, content_line* new) { @@ -53,44 +47,46 @@ content_line* get_property (vevent* ev, char* key) { INIT_F(content_line) { INIT(strbuf, &this->key); - // INIT(strbuf, &this->val); INIT( LLIST(strbuf), &this->vals ); + // TODO remaining fields + return 0; } INIT_F(content_line, int keylen, int vallen) { INIT(strbuf, &this->key, keylen); - // INIT(strbuf, &this->val, vallen); INIT( LLIST(strbuf), &this->vals ); NEW(strbuf, s, vallen); PUSH(LLIST(strbuf))(&this->vals, s); + // TODO remaining fields + return 0; } int content_line_copy (content_line* dest, content_line* src) { - //strbuf_init_copy(&dest->key, &src->key); DEEP_COPY(strbuf)(&dest->key, &src->key); - // strbuf_init_copy(&dest->val, &src->val); DEEP_COPY(LLIST(strbuf))(&dest->vals, &src->vals); + // TODO remaining fields + return 0; } FREE_F(content_line) { FREE(strbuf)(&this->key); - // FREE(strbuf)(&this->val); - // LLIST_FREE(strbuf)(&this->vals); FREE(LLIST(strbuf))(&this->vals); // TODO remaining fields + return 0; } FREE_F(vevent) { if (this->filename != NULL) free(this->filename); + if (FREE(TRIE(content_line))(&this->clines) != 0) { fprintf(stderr, "Error freeing vevent belonging to file \n %s \n", this->filename); @@ -99,9 +95,6 @@ FREE_F(vevent) { return 0; } -/* - * TODO change this into PUSH(VCALENDAR) (vevent*) ? - */ int push_event(vcalendar* cal, vevent* ev) { ev->calendar = cal; @@ -112,7 +105,6 @@ int push_event(vcalendar* cal, vevent* ev) { cal->events = realloc(cal->events, sizeof(*cal->events) * cal->alloc); } - // vevent_init_copy(&cal->events[cal->n_events], ev); cal->events[cal->n_events] = ev; cal->n_events++; @@ -29,15 +29,15 @@ INIT_F(content_line); INIT_F(content_line, int keylen, int vallen); /* - * This takes two content lines, and return a content line that is the - * merge of the two. - * The function also cleans up the unused memmory between the two. + * Resolves a collision in some form of structure (probably a hash-map + * or a trie). If dest is NULL just return new. Otherwise mutates dest + * to have the correct form, and returns it. Destroying new in the + * process. */ content_line* RESOLVE(content_line) (content_line* dest, content_line* new); #define TYPE content_line -// #include "hash.h" #include "trie.h" #undef TYPE @@ -70,6 +70,7 @@ int free_vcalendar (vcalendar* cal); /* * Appends ev to cal. Doesn't copy ev. So make sure that it wont go * out of scope. + * TODO change this into PUSH(VCALENDAR) (vevent*) ? */ int push_event(vcalendar* cal, vevent* ev); |