aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2019-02-19 00:27:43 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2019-02-19 00:27:43 +0100
commitaae3b8bfb83abec0f1bb8e4c854c156c03be5ca8 (patch)
tree305f1287a8cc6a896318a4de5f2b43686e7223b3
parentMade to compile as C++. (diff)
downloadcalp-aae3b8bfb83abec0f1bb8e4c854c156c03be5ca8.tar.gz
calp-aae3b8bfb83abec0f1bb8e4c854c156c03be5ca8.tar.xz
Started full rewrite in C++.
-rw-r--r--Makefile8
-rw-r--r--calendar.cpp (renamed from calendar.c)0
-rw-r--r--err.h4
-rw-r--r--linked_list.cpp38
-rw-r--r--linked_list.h58
-rw-r--r--linked_list.inc.h23
-rw-r--r--macro.h131
-rw-r--r--parse.cpp (renamed from parse.c)83
-rw-r--r--parse.h31
-rw-r--r--strbuf.c138
-rw-r--r--strbuf.cpp26
-rw-r--r--strbuf.h106
-rw-r--r--trie.cpp134
-rw-r--r--trie.h68
-rw-r--r--trie.inc.h166
-rw-r--r--vcal.c130
-rw-r--r--vcal.cpp14
-rw-r--r--vcal.h132
18 files changed, 420 insertions, 870 deletions
diff --git a/Makefile b/Makefile
index 0ae2ccc0..e72ba47c 100644
--- a/Makefile
+++ b/Makefile
@@ -10,14 +10,14 @@ CFLAGS = -std=gnu++11 -Wall -Wextra \
LDFLAGS = -fPIC $(shell guile-config link)
H_FILES = $(wildcard *.h)
-C_FILES = $(wildcard *.c)
+C_FILES = $(wildcard *.cpp)
SCM_C_FILES = $(wildcard *.scm.c)
-X_FILES = $(SCM_C_FILES:.scm.c=.x)
+X_FILES = $(SCM_C_FILES:.scm.cpp=.x)
.SECONDARY: $(X_FILES)
-O_FILES = $(addprefix obj/,$(C_FILES:.c=.o))
+O_FILES = $(addprefix obj/,$(C_FILES:.cpp=.o))
all: parse libguile-calendar.so
@@ -32,7 +32,7 @@ $(O_FILES): | $(OBJDIR)
$(OBJDIR)/%.scm.o : %.scm.c %.x
$(CC) -c $(CFLAGS) -o $@ $<
-$(OBJDIR)/%.o : %.c # $(H_FILES) $(X_FILES)
+$(OBJDIR)/%.o : %.cpp # $(H_FILES) $(X_FILES)
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR):
diff --git a/calendar.c b/calendar.cpp
index d0476583..d0476583 100644
--- a/calendar.c
+++ b/calendar.cpp
diff --git a/err.h b/err.h
index d9d19ec7..ca5b09ef 100644
--- a/err.h
+++ b/err.h
@@ -3,8 +3,6 @@
#include <stdio.h>
-#include "macro.h"
-
#define _RESET "\x1b[m"
#define _BLACK "\x1B[0;30m"
#define _RED "\x1B[0;31m"
@@ -27,6 +25,7 @@
#define INFO_F(fmt, ...) fprintf(stderr, _BLUE "INFO" _RESET " (%s:%i) " fmt "\n", \
__FILE__, __LINE__, ##__VA_ARGS__)
+#if 0
#define LINE(len) do { \
printf(_GREEN); \
FOR(int, i, len) printf("_"); \
@@ -38,5 +37,6 @@
FMT(T)(v, buf); \
INFO_F("%s", buf); \
} while (0)
+#endif
#endif /* ERR_H */
diff --git a/linked_list.cpp b/linked_list.cpp
new file mode 100644
index 00000000..bd49510e
--- /dev/null
+++ b/linked_list.cpp
@@ -0,0 +1,38 @@
+#include "linked_list.h"
+
+template <typename T>
+llist<T>::llist () {
+ this->length = 0;
+ this->cur = this->head = new link<T>;
+ this->tail = new link<T>;
+
+ head->after = tail;
+ tail->before = head;
+}
+
+template <typename T>
+link<T>::~link () {
+ this.unlink();
+}
+
+template <typename T>
+void link<T>::unlink () {
+ if (this->before != nullptr) this->before->after = this->after;
+ if (this->after != nullptr) this->after->before = this->before;
+}
+
+template <typename T>
+void llist<T>::push(T& val) {
+ auto l = new link<T>(val);
+
+ l->after = FIRST(this);
+ FIRST(this) = l;
+
+ l->after->before = l;
+ l->before = this->head;
+
+ ++this->length;
+
+ // TODO do I want to change that?
+ this->cur = l;
+}
diff --git a/linked_list.h b/linked_list.h
index a17bd797..7d11ca81 100644
--- a/linked_list.h
+++ b/linked_list.h
@@ -1,54 +1,48 @@
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
-#include "macro.h"
-#define LLIST(T) TEMPL(llist, T)
-#define LINK(T) TEMPL(llist_link, T)
+template <typename T>
+struct link {
+ link<T>* before = nullptr;
+ link<T>* after = nullptr;
+ T* value;
-#define UNLINK(T) TEMPL(unlink, T)
+ link ();
+ link (T* val) : value(val) { }
+ ~link ();
-#endif /* LINKED_LIST_H */
-#ifdef TYPE
-
-typedef struct LINK(TYPE) {
- struct LINK(TYPE)* before;
- struct LINK(TYPE)* after;
- TYPE* value;
-} LINK(TYPE);
+ void unlink ();
+};
-#define L(link) (link)->value
+// #define L(link) (link)->value
-typedef struct {
- LINK(TYPE)* head;
- LINK(TYPE)* tail;
- LINK(TYPE)* cur;
+template <typename T>
+struct llist {
+ link<T>* head;
+ link<T>* tail;
+ link<T>* cur;
int length;
-} LLIST(TYPE);
+
+ llist ();
+
+ void push ( T& );
+ T& peek ();
+ T& pop ();
+
+ llist& operator += (llist& other);
+};
#define FIRST(lst) (lst)->head->after
#define FIRST_V(lst) (lst)->head->after->value
#define LAST(lst) (lst)->tail->before
#define LAST_V(lst) (lst)->tail->before->value
-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) );
-INIT_F ( LINK(TYPE), TYPE* val );
-FREE_F ( LINK(TYPE) );
-
-int UNLINK(LINK(TYPE)) ( LINK(TYPE)* );
-
-int PUSH(LLIST(TYPE)) ( LLIST(TYPE)*, TYPE* );
-TYPE* PEEK(LLIST(TYPE)) ( LLIST(TYPE)* );
-TYPE* POP(LLIST(TYPE)) ( LLIST(TYPE)* );
int DEEP_COPY(LLIST(TYPE)) ( LLIST(TYPE)* dest, LLIST(TYPE)* src );
@@ -85,4 +79,4 @@ FMT_F(LLIST(TYPE));
// #define __NXT_LLIST(T, l, set) l = L(__INTER(l) = __INTER(l)->after)
#define NXT_LLIST(T) __NXT_LLIST
-#endif /* TYPE */
+#endif /* LINKED_LIST_H */
diff --git a/linked_list.inc.h b/linked_list.inc.h
index 8ae720ba..410fddba 100644
--- a/linked_list.inc.h
+++ b/linked_list.inc.h
@@ -1,26 +1,3 @@
-#ifndef TYPE
-#error "Set TYPE before including self file"
-#else
-
-INIT_F ( LLIST(TYPE) ) {
- self->length = 0;
- NEW(LINK(TYPE), head);
- NEW(LINK(TYPE), tail);
- self->head = head;
- self->tail = tail;
- head->after = tail;
- tail->before = head;
- self->cur = head;
- return 0;
-}
-
-FREE_F (LINK(TYPE)) {
- UNLINK(LINK(TYPE))(self);
-
- if (self->value != NULL) FFREE(TYPE, self->value);
- return 0;
-}
-
FREE_F( LLIST(TYPE) ) {
LINK(TYPE) *n, *next;
n = self->head;
diff --git a/macro.h b/macro.h
deleted file mode 100644
index 6421b2fd..00000000
--- a/macro.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef MACRO_H
-#define MACRO_H
-
-/*
- * Token paste
- */
-#define TP(a, b) a ## b
-#define TP3(a, b, c) a ## b ## c
-#define TP4(a, b, c, d) a ## b ## c ## d
-#define TP5(a, b, c, d, e) a ## b ## c ## d ## e
-#define TP6(a, b, c, d, e, f) a ## b ## c ## d ## e ## f
-
-/*
- * Get length of __VA_ARGS__
- * Borrowed fram:
- * https://stackoverflow.com/a/35986932
- */
-#define VA_ARGS_NUM_PRIV(P1, P2, P3, P4, P5, P6, Pn, ...) Pn
-#define VA_ARGS_NUM(...) VA_ARGS_NUM_PRIV(-1, ## __VA_ARGS__, 5, 4, 3, 2, 1, 0)
-
-/*
- * 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 TEMPL2(name, T, V) TP6(name, \U00001438\U00001438 , T , \U00001433_\U00001438 , V, \U00001433\U00001433)
-#define TEMPL_N(name, T, argcount) TP6(name, \U00001438 , T, _, argcount, \U00001433 )
-
-/* Constructor type name */
-#define __INIT_T(T, C) TEMPL_N(init, T, C)
-
-/* Returns full type of constructor */
-#define INIT_F(T, ...) \
- int __INIT_T(T, VA_ARGS_NUM(__VA_ARGS__)) (T* self, ## __VA_ARGS__)
-
-/*
- * Call the constructor of an object
- * `int` part of the macro, to ensure that any attempt to call self
- * function results in an error.
- */
-#define INIT(T, N, ...) \
- __INIT_T(T, VA_ARGS_NUM(__VA_ARGS__)) (N, ## __VA_ARGS__)
-
-/* Allocate a new_ object on the HEAP */
-#define NEW(T, N, ...) \
- T* N = (T*) malloc(sizeof(*N)); \
- INIT(T, N, ## __VA_ARGS__);
-
-/*
- * Reconstructs a object. Use with caution.
- */
-#define RENEW(T, N, ...) do { \
- N = (T*) malloc(sizeof(*N)); \
- INIT(T, N, ## __VA_ARGS__); \
-} while (0)
-
-
-/* Allocate a new_ object on the STACK */
-#define SNEW(T, N, ...) \
- T N; \
- INIT(T, & N, ## __VA_ARGS__);
-
-/* Destructor for type */
-#define FREE(T) TEMPL(free, T)
-
-/* Call destructor for type, and free object */
-#define FFREE(T, N) do { FREE(T)(N); free(N); } while (0)
-
-/* Declare destructor */
-#define FREE_F(T) int FREE(T) (T* self)
-
-/* generate reusable internal symbol */
-#define __INTER(s) TP3(__, s, __internal)
-
-/* Iterator macros. */
-#define FOR(CONT_T, T, var, set) \
- PRE_FOR_ ## CONT_T (T) (T, var, set); \
- for( BEG_ ## CONT_T (T) (T, var, set); \
- END_ ## CONT_T (T) (T, var, set); \
- NXT_ ## CONT_T (T) (T, var, set))
-
-/* Example int implementation
- * FOR(int, i, 10) { } */
-
-#define PRE_FOR_int(i, set)
-#define BEG_int(i, set) int i = 0
-#define NXT_int(i, set) i++
-#define END_int(i, set) i < set
-
-/*
- * General functions that different container types may implement.
- * Actuall implementation and type signature is mostly left to
- * individual implementations.
- */
-#define DEEP_COPY(T) TEMPL(copy , T)
-#define RESOLVE(T) TEMPL(resolve , T)
-#define APPEND(T) TEMPL(append , T)
-#define SIZE(T) TEMPL(size , T)
-#define EMPTY(T) TEMPL(empty , T)
-#define PUSH(T) TEMPL(push , T)
-#define PEEK(T) TEMPL(peek , T)
-#define POP(T) TEMPL(pop , T)
-#define GET(T) TEMPL(get , T)
-#define RESET(T) TEMPL(reset , T)
-
-/*
- * Formatting macros.
- * Transform objects into string representation of themselves.
- * buf should be a suffisiently large memmory location, if it's to
- * small then bad stuff might happen.
- *
- * Should return the number of bytes written (like sprintf).
- */
-
-#define FMT_T(T) TEMPL(format , T)
-#define FMT_F(T) int FMT_T(T)(T* self, char* buf, ...)
-// TODO change order of buf and item
-#define __FMT_HELP(item, buf, ...) ((item), (buf), VA_ARGS_NUM(__VA_ARGS__), ## __VA_ARGS__)
-#define FMT(T) FMT_T(T) __FMT_HELP
-#define fmtf(...) seek += sprintf(buf + seek, __VA_ARGS__)
-
-#endif /* MACRO_H */
diff --git a/parse.c b/parse.cpp
index 8f7a9102..310ab7fe 100644
--- a/parse.c
+++ b/parse.cpp
@@ -4,32 +4,21 @@
#include <string.h>
#include <assert.h>
-#include "macro.h"
#include "vcal.h"
+#include "strbuf.h"
#include "err.h"
-#define TYPE vcomponent
-#include "linked_list.inc.h"
-#undef TYPE
-
-#define T strbuf
-#define V strbuf
-#include "pair.h"
-#include "pair.inc.h"
-#undef T
-#undef V
-
/*
* name *(";" param) ":" value CRLF
*/
-int parse_file(char* filename, FILE* f, vcomponent* root) {
+int parse_file(char* filename, FILE* f, vcomponent& root) {
part_context p_ctx = p_key;
- SNEW(parse_ctx, ctx, filename);
- PUSH(LLIST(vcomponent))(&ctx.comp_stack, root);
+ parse_ctx ctx(filename);
+ ctx.comp_stack.push(root);
- SNEW(content_line, cline);
+ content_line cline;
char c;
while ( (c = fgetc(f)) != EOF) {
@@ -40,11 +29,16 @@ int parse_file(char* filename, FILE* f, vcomponent* root) {
if (fold(f, &ctx, c) > 0) {
/* Actuall end of line, handle value */
- strbuf* target = CLINE_CUR_VAL(&cline);
+ // std::string& target = CLINE_CUR_VAL(&cline);
+ // TODO solve current;
+ // std::string& target = cline
- DEEP_COPY(strbuf)(target, &ctx.str);
- strbuf_cap(target);
- strbuf_soft_reset(&ctx.str);
+ strbuf target = ctx.str;
+ // DEEP_COPY(strbuf)(target, &ctx.str);
+ target.cap();
+ // strbuf_cap(target);
+ ctx.str.soft_reset();
+ // strbuf_soft_reset(&ctx.str);
handle_kv(&cline, &ctx);
@@ -86,7 +80,8 @@ int parse_file(char* filename, FILE* f, vcomponent* root) {
}
/* save escapade character as a normal character */
- strbuf_append(&ctx.str, target);
+ // strbuf_append(&ctx.str, target);
+ ctx.str += target;
++ctx.column;
++ctx.pcolumn;
@@ -94,12 +89,15 @@ int parse_file(char* filename, FILE* f, vcomponent* root) {
/* Border between param {key, value} */
} else if (p_ctx == p_param_name && c == '=') {
- LLIST(param_set)* params = CLINE_CUR_PARAMS(&cline);
-
- NEW(param_set, ps);
- DEEP_COPY(strbuf)(&ps->key, &ctx.str);
- strbuf_cap(&ps->key);
- strbuf_soft_reset(&ctx.str);
+ // LLIST(param_set)* params = CLINE_CUR_PARAMS(&cline);
+ std::list<param_set>* params = cline.second.second;
+
+ // NEW(param_set, ps);
+ auto ps = new param_set;
+ // TODO make sure this is a deep copy
+ ps->first = ctx.str;
+ ps->first.cap();
+ ctx.str.soft_reset();
PUSH(LLIST(param_set))(params, ps);
p_ctx = p_param_value;
@@ -269,34 +267,3 @@ int fold(FILE* f, parse_ctx* ctx, char c) {
return retval;
}
-
-
-INIT_F(parse_ctx, char* filename) {
- INIT(LLIST(strbuf), &self->key_stack);
- INIT(LLIST(vcomponent), &self->comp_stack);
- self->filename = (char*) calloc(sizeof(*filename), strlen(filename) + 1);
- strcpy(self->filename, filename);
-
- self->line = 0;
- self->column = 0;
-
- self->pline = 1;
- self->pcolumn = 1;
-
- INIT(strbuf, &self->str);
-
- return 0;
-}
-
-FREE_F(parse_ctx) {
-
- FREE(LLIST(strbuf))(&self->key_stack);
- FREE(LLIST(vcomponent))(&self->comp_stack);
- free(self->filename);
-
- self->line = 0;
- self->column = 0;
- FREE(strbuf)(&self->str);
-
- return 0;
-}
diff --git a/parse.h b/parse.h
index b69bcfa5..6ab98bfd 100644
--- a/parse.h
+++ b/parse.h
@@ -4,12 +4,17 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string>
+#include <stack>
+
#include "strbuf.h"
#include "vcal.h"
+#if 0
#define TYPE vcomponent
#include "linked_list.h"
#undef TYPE
+#endif
/*
* The standard says that no line should be longer than 75 octets.
@@ -18,32 +23,32 @@
*/
#define SEGSIZE 75
-typedef enum {
+enum part_context {
p_key, p_value, p_param_name, p_param_value, p_escape
-} part_context;
+};
/*
* Struct holding most state information needed while parsing.
* Kept together for simplicity.
*/
-typedef struct {
- char* filename;
- LLIST(strbuf) key_stack;
- LLIST(vcomponent) comp_stack;
+struct parse_ctx {
+ std::string filename;
+ std::stack<std::string> key_stack;
+ std::stack<vcomponent> comp_stack;
/* Number for unfolded lines */
- int line;
- int column;
+ int line = 0;
+ int column = 0;
/* Actuall lines and columns from file */
- int pline;
- int pcolumn;
+ int pline = 1;
+ int pcolumn = 1;
strbuf str;
-} parse_ctx;
-INIT_F(parse_ctx, char* filename);
-FREE_F(parse_ctx);
+ parse_ctx (const std::string& filename)
+ : filename(filename) { }
+};
int handle_kv(
content_line* cline,
diff --git a/strbuf.c b/strbuf.c
deleted file mode 100644
index f17de211..00000000
--- a/strbuf.c
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "strbuf.h"
-
-#include <string.h>
-#include <stdio.h>
-
-#include "err.h"
-
-INIT_F(strbuf) {
- INIT(strbuf, self, 1);
- return 0;
-}
-
-/*
- * Giving len < 1 is an error.
- */
-INIT_F(strbuf, size_t len) {
- self->mem = (char*) calloc(sizeof(*self->mem), len);
- self->alloc = len;
- self->ptr = 0;
- self->len = 0;
- return 0;
-}
-
-int strbuf_realloc(strbuf* str, size_t len) {
- str->mem = (char*) realloc(str->mem, len);
- str->alloc = len;
- return 0;
-}
-
-FREE_F(strbuf) {
- /* has already been freed */
- if (self->mem == NULL) return 1;
-
- free (self->mem);
- self->mem = NULL;
- self->alloc = 0;
- self->len = 0;
- return 0;
-}
-
-/*
- * Reallocates memmory for you. Returns 1 if memory was reallocated.
- */
-int strbuf_append(strbuf* s, char c) {
- int retval = 0;
-
- if (s->len + 1 > s->alloc) {
- s->alloc <<= 1;
- s->mem = (char*) realloc(s->mem, s->alloc);
- retval = 1;
- }
-
- s->mem[s->len] = c;
- s->ptr = ++s->len;
- return retval;
-}
-
-int strbuf_cap(strbuf* s) {
- /*
- * TODO check memmory usage
- */
- return strbuf_append(s, 0);
-}
-
-int DEEP_COPY(strbuf)(strbuf* dest, strbuf* src) {
- int retval = 0;
-
- if (dest->alloc < src->len) {
- /* +1 in length is to have room for '\0'. */
- strbuf_realloc(dest, src->len + 1);
- retval = 1;
- }
-
- dest->len = src->len;
- memcpy(dest->mem, src->mem, src->len);
- return retval;
-}
-
-int strbuf_cmp(strbuf* a, strbuf* b) {
- if (a == NULL || a->alloc == 0 ||
- b == NULL || b->alloc == 0)
- {
- ERR("a or b not alloced");
- // return -1;
- }
-
- return strncmp(a->mem, b->mem, a->len);
-}
-
-int strbuf_c(strbuf* a, char* b) {
- if (a == NULL || a->alloc == 0) {
- ERR("a not allocated");
- return -1;
- }
-
- return strcmp(a->mem, b) == 0;
-}
-
-char* charat(strbuf* s, unsigned int idx) {
- if (idx > s->len) {
- ERR("Index out of bounds");
- return (char*) -1;
- }
-
- return &s->mem[idx];
-}
-
-char* strbuf_cur(strbuf* s) {
- return &s->mem[s->ptr];
-}
-
-char* strbuf_end(strbuf* s) {
- return &s->mem[s->len];
-}
-
-int strbuf_reset(strbuf* s) {
- s->ptr = 0;
- return 0;
-}
-
-
-int strbuf_soft_reset(strbuf* s) {
- s->ptr = s->len = 0;
- return 0;
-}
-
-strbuf* RESOLVE(strbuf)(strbuf* dest, strbuf* new_) {
- if (dest == NULL) return new_;
- else return dest;
-}
-
-FMT_F(strbuf) {
- return sprintf(buf, "%s", self->mem);
-}
-
-int SIZE(strbuf)(strbuf* self) {
- return self->len;
-}
diff --git a/strbuf.cpp b/strbuf.cpp
new file mode 100644
index 00000000..3864b271
--- /dev/null
+++ b/strbuf.cpp
@@ -0,0 +1,26 @@
+#include "strbuf.h"
+
+#include <cstdlib>
+
+void strbuf::realloc (size_t len) {
+ this->mem = static_cast<char*>(std::realloc(this->mem, len));
+ this->alloc = len;
+}
+
+strbuf::~strbuf() {
+ free (this->mem);
+ this->mem = NULL;
+ this->alloc = 0;
+ this->len = 0;
+}
+
+strbuf& strbuf::operator+=(char c) {
+ if (this->len + 1 > this->alloc) {
+ this->alloc <<= 1;
+ this->mem = static_cast<char*> (std::realloc(this->mem, this->alloc));
+ }
+
+ this->mem[this->len] = c;
+ this->ptr = ++this->len;
+ return *this;
+}
diff --git a/strbuf.h b/strbuf.h
index c531734e..07580f63 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -1,8 +1,9 @@
#ifndef STRBUF_H
#define STRBUF_H
-#include <stdlib.h>
-#include "macro.h"
+#include <unistd.h>
+#include <cstdlib>
+#include <cstring>
/*
* A high level string type which holds it's own length, how much
@@ -12,88 +13,74 @@
* Also comes with a number of functions which allow for safe(er)
* access to the memmory.
*/
-typedef struct {
+struct strbuf {
char* mem;
/* TODO add support for negative ptr */
- int ptr;
- unsigned int alloc;
- unsigned int len;
-} strbuf;
+ int ptr = 0;
+ size_t alloc;
+ size_t len = 0;
-/*
- * Init strbuf to size of 0
- * Doesnt't call malloc.
- */
-INIT_F(strbuf);
+ strbuf () : strbuf (1) { };
+ strbuf (size_t alloc)
+ : alloc(alloc)
+ , mem(static_cast<char*>(malloc(alloc))) { };
-/* Constructor */
-INIT_F(strbuf, size_t len);
+ ~strbuf();
-/*
- * Like realloc, but for strbuf
- */
-int strbuf_realloc(strbuf* str, size_t len);
+ /*
+ * Like realloc, but for strbuf
+ */
+ void realloc (size_t len);
-/*
- * Free's contents of str, but keeps str.
- */
-FREE_F(strbuf);
+ bool operator==(strbuf& other) {
+ return strncmp(this->mem, other.mem, this->len) == 0;
+ }
+ bool operator==(char* other)
+ { strncmp(this->mem, other, this->len) == 0 ; }
-int strbuf_cmp(strbuf* a, strbuf* b);
-int strbuf_c(strbuf* a, char* b);
+ strbuf& operator=(strbuf* other);
-/*
- * Copy contents from src to dest.
- * Assumes that dest is already initialized.
- */
-int DEEP_COPY(strbuf)(strbuf*, strbuf*);
+ strbuf& operator+=(char c);
-/*
- * Append char to end of strbuf, determined by s->len.
- */
-int strbuf_append(strbuf* s, char c);
+ void cap() { this->mem += '\0'; }
-/*
- * Calls strbuf_append with NULL.
- */
-int strbuf_cap(strbuf* s);
+ /*
+ * Returns a pointer to character at index. Allows mutation of the
+ * value pointed to by the return address.
+ */
+ char& operator[](int idx)
+ { return this->mem[idx]; }
-/*
- * 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()
+ { return this->mem[this->ptr]; }
-/*
- * Same as `charat`, But returns the current character.
- */
-char* strbuf_cur(strbuf* s);
+ /* Returns the character after the last, so where null hopefully is. */
+ char& back()
+ { return this->mem[this->len]; }
-/*
- * Resets the seek for strbuf to 0.
- */
-int strbuf_reset(strbuf* s);
+ /* Resets the seek for strbuf to 0. */
+ void reset();
-/*
- * Sets the length and seek ptr to 0, but doesn't touch the memmory.
- */
-int strbuf_soft_reset(strbuf* s);
+ /* Sets the length and seek ptr to 0, but doesn't touch the memmory. */
+ void soft_reset();
-/*
- * Returns the character after the last, so where null hopefully is.
- */
-char* strbuf_end(strbuf* s);
+ std::string to_string() {
+ return std::string (this->mem);
+ }
+};
/*
* Reallocs dest to be the same size as src, and copies the contents
* of src into dest.
*/
-int strbuf_realloc_copy(strbuf* dest, strbuf* src);
+// int strbuf_realloc_copy(strbuf* dest, strbuf* src);
/*
* Copies contents from src to dest, also allocating dest in the
* process. dest should not be initialized before self call.
*/
+#if 0
int strbuf_init_copy(strbuf* dest, strbuf* src);
strbuf* RESOLVE(strbuf)(strbuf*, strbuf*);
@@ -101,5 +88,6 @@ strbuf* RESOLVE(strbuf)(strbuf*, strbuf*);
FMT_F(strbuf);
int SIZE(strbuf)(strbuf*);
+#endif
#endif /* STRBUF_H */
diff --git a/trie.cpp b/trie.cpp
new file mode 100644
index 00000000..729277bd
--- /dev/null
+++ b/trie.cpp
@@ -0,0 +1,134 @@
+#include "trie.h"
+
+template <class T>
+trie<T>::trie () {
+ this->root = new trie_node<T> ('\0');
+}
+
+template <class T>
+trie_node<T>::trie_node (char c) {
+ this->c = c;
+}
+
+template <class T>
+trie_node<T>::trie_node (char c, trie_node<T>* next, trie_node<T>* child) {
+ this->c = c;
+ this->next = next;
+ this->child = child;
+}
+
+template <class T>
+int trie<T>::push_back (const char* key, const T& item) {
+ trie_node<T> *cur, *last;
+
+ last = this->root;
+ cur = last->child;
+
+ char* subkey = key;
+
+ while (true) {
+ if (cur == NULL) {
+ /* Build direct LL for remaining subkey */
+ for (char* c = subkey; c[0] != '\0'; c++) {
+ // NEW(TRIE_NODE(TYPE), t, *c);
+ auto t = new trie_node<T>(*c);
+ last->child = t;
+ last = t;
+ }
+ // TODO fix resolve
+ // last->value = RESOLVE(TYPE)(last->value, val);
+ last->value = item;
+ return 0;
+ } else if (cur->c == subkey[0]) {
+ /* This node belongs to the key,
+ * Decend further */
+ last = cur;
+ cur = cur->child;
+ subkey++;
+ } else if (subkey[0] == '\0') {
+ /* Key finished */
+ // TODO fix resolve
+ // last->value = RESOLVE(TYPE)(last->value, val);
+ last->value = item;
+ return 0;
+ } else if (cur->next != NULL) {
+ /* This node was not part of the set, but it's sibling might */
+ cur = cur->next;
+ /* `last` not set since we aren't moving down */
+ } else {
+ /* No node on self level was part of the set, create a new__
+ * sibling and follow down that parse */
+ // NEW(TRIE_NODE(TYPE), t, *subkey);
+ auto t = new trie_node<T>(*subkey);
+ cur->next = t;
+ last = cur;
+ cur = t;
+ }
+ }
+}
+
+template <class T>
+T& trie<T>::operator[] (char* key) {
+ trie_node<T>* n = this->root->child;
+ char* subkey = key;
+
+ while (n != NULL) {
+ if (subkey[1] == '\0') {
+ return n->value;
+ } else if (subkey[0] == n->c) {
+ n = n->child;
+ subkey++;
+ } else {
+ n = n->next;
+ }
+ }
+
+ // ERR("Position not found");
+ // return 0;
+ return nullptr;
+}
+
+template <class T>
+std::ostream& operator<<(std::ostream& o, trie_node<T>* node) {
+#if 0
+ va_list ap;
+ va_start(ap, buf);
+ int argc = va_arg(ap, int);
+ int depth = argc >= 1
+ ? va_arg(ap, int)
+ : 0;
+ va_end(ap);
+
+ int seek = 0;
+#endif
+ // TODO figure out depth
+ int depth = 1;
+
+ trie_node<T>* n = node;
+
+
+ if (n == NULL) { o << std::endl; }
+ while (n != NULL) {
+ o << '|';
+ for (int i = 0; i < depth; i++) o << ' ';
+ o << (n->c == '\0' ? '0' : n->c);
+ if (n->value != NULL) {
+ o << n->value << std::endl;
+ }
+
+ if (n->child != NULL) {
+ o << std::endl;
+ o << n->child; // depth + 1
+ }
+ n = n->next;
+ }
+ return o;
+}
+
+template <class T>
+std::ostream& operator<<(std::ostream& o, trie<T>* trie) {
+ o << "Trie: " << trie << " {\n";
+ o << trie->root->child;
+ o << "}";
+ return o;
+}
diff --git a/trie.h b/trie.h
index 404864d3..d672125b 100644
--- a/trie.h
+++ b/trie.h
@@ -1,46 +1,60 @@
#ifndef TRIE_H
#define TRIE_H
-#include <stdio.h>
+#include <iostream>
-#include "macro.h"
+template <typename T>
+struct trie_node {
+ char c;
+ T* value = NULL;
+ trie_node<T>* next = NULL;
+ trie_node<T>* child = NULL;
-#define TRIE(T) TEMPL(trie, T)
-#define TRIE_NODE(T) TEMPL(trie_node, T)
+ trie_node (char c);
+ trie_node (char c, trie_node<T>* next, trie_node<T>* child);
-#endif /* TRIE_H */
-#ifdef TYPE
+ // ~trie_node ();
+};
-typedef struct TRIE_NODE(TYPE) {
- char c;
- TYPE* value;
- struct TRIE_NODE(TYPE)* next;
- struct TRIE_NODE(TYPE)* child;
-} TRIE_NODE(TYPE);
+template <class T>
+std::ostream& operator<<(std::ostream&, trie_node<T>* node);
+
+template <typename T>
+struct trie {
+ trie_node<T>* root;
+
+ trie ();
+ // ~trie ();
-typedef struct {
- TRIE_NODE(TYPE)* root;
-} TRIE(TYPE);
+ int push_back (const char* key, const T&);
+ T& operator[] ( char* key );
-INIT_F ( TRIE(TYPE) );
+ bool empty () { return this->root->child == NULL; }
+};
-INIT_F (TRIE_NODE(TYPE), char c);
+template <class T>
+std::ostream& operator<<(std::ostream&, trie<T>* trie);
-INIT_F (TRIE_NODE(TYPE),
- char c, TRIE_NODE(TYPE)* next, TRIE_NODE(TYPE)* child );
-int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val );
+// INIT_F ( TRIE(TYPE) );
-TYPE* GET(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key );
+// INIT_F (TRIE_NODE(TYPE), char c);
-FREE_F(TRIE_NODE(TYPE));
+// INIT_F (TRIE_NODE(TYPE),
+// char c, TRIE_NODE(TYPE)* next, TRIE_NODE(TYPE)* child );
-FREE_F(TRIE(TYPE));
+// int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val );
-int EMPTY(TRIE(TYPE))(TRIE(TYPE)*);
+// TYPE* GET(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key );
-FMT_F(TRIE_NODE(TYPE));
-FMT_F(TRIE(TYPE));
+// FREE_F(TRIE_NODE(TYPE));
-#endif /* TYPE */
+// FREE_F(TRIE(TYPE));
+
+// int EMPTY(TRIE(TYPE))(TRIE(TYPE)*);
+
+// FMT_F(TRIE_NODE(TYPE));
+// FMT_F(TRIE(TYPE));
+
+#endif /* TRIE_H */
diff --git a/trie.inc.h b/trie.inc.h
deleted file mode 100644
index 5517939e..00000000
--- a/trie.inc.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef TYPE
-#error "Set TYPE before including self file"
-#else
-
-#include <stdarg.h>
-
-#include "err.h"
-#include "macro.h"
-
-INIT_F ( TRIE(TYPE) ) {
- NEW(TRIE_NODE(TYPE), t, '\0');
- self->root = t;
- return 0;
-}
-
-INIT_F (TRIE_NODE(TYPE), char c) {
- self->c = c;
- self->value = NULL;
- self->next = NULL;
- self->child = NULL;
- return 0;
-}
-
-INIT_F (TRIE_NODE(TYPE),
- char c,
- TRIE_NODE(TYPE)* next,
- TRIE_NODE(TYPE)* child )
-{
- self->c = c;
- self->next = next;
- self->child = child;
- return 0;
-}
-
-int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val ) {
- TRIE_NODE(TYPE) *cur, *last;
-
- last = trie->root;
- cur = last->child;
-
- char* subkey = key;
-
- while (1) {
- if (cur == NULL) {
- /* Build direct LL for remaining subkey */
- for (char* c = subkey; c[0] != '\0'; c++) {
- NEW(TRIE_NODE(TYPE), t, *c);
- last->child = t;
- last = t;
- }
- last->value = RESOLVE(TYPE)(last->value, val);
- return 0;
- } else if (cur->c == subkey[0]) {
- /* This node belongs to the key,
- * Decend further */
- last = cur;
- cur = cur->child;
- subkey++;
- } else if (subkey[0] == '\0') {
- /* Key finished */
- last->value = 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 */
- cur = cur->next;
- /* `last` not set since we aren't moving down */
- } else {
- /* No node on self level was part of the set, create a new__
- * sibling and follow down that parse */
- NEW(TRIE_NODE(TYPE), t, *subkey);
- cur->next = t;
- last = cur;
- cur = t;
- }
- }
-
- return 0;
-}
-
-/*
- * TODO what happens when I give an invalid key?
- */
-TYPE* GET(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key ) {
- TRIE_NODE(TYPE)* n = trie->root->child;
- char* subkey = key;
-
- while (n != NULL) {
- if (subkey[1] == '\0') {
- return n->value;
- } else if (subkey[0] == n->c) {
- n = n->child;
- subkey++;
- } else {
- n = n->next;
- }
- }
-
- ERR("Position not found");
- return 0;
-}
-
-FREE_F(TRIE_NODE(TYPE)) {
- if (self == NULL) return 0;
- if (self->value != NULL) FFREE(TYPE, self->value);
- if (self->next != NULL) FREE(TRIE_NODE(TYPE))(self->next);
- if (self->child != NULL) FREE(TRIE_NODE(TYPE))(self->child);
- free (self);
- return 0;
-}
-
-FREE_F(TRIE(TYPE)) {
- if (self->root->c != '\0') {
- // ERR("Invalid trie");
- return 1;
- }
- return FREE(TRIE_NODE(TYPE))(self->root);
-}
-
-int EMPTY(TRIE(TYPE))(TRIE(TYPE)* self) {
- return self->root->child == NULL;
-}
-
-FMT_F(TRIE_NODE(TYPE)) {
-
- va_list ap;
- va_start(ap, buf);
- int argc = va_arg(ap, int);
- int depth = argc >= 1
- ? va_arg(ap, int)
- : 0;
- va_end(ap);
-
- int seek = 0;
-
- TRIE_NODE(TYPE)* n = self;
-
- if (n == NULL) { fmtf("\n"); }
- while (n != NULL) {
- fmtf("|");
- // FOR(int, i, depth) fmtf(" ");
- for (int i = 0; i < depth; i++) fmtf(" ");
- fmtf("%c ", n->c == '\0' ? '0' : n->c);
- if (n->value != NULL) {
- seek += FMT(TYPE)(n->value, buf + seek);
- fmtf("\n");
- }
-
- if (n->child != NULL) {
- fmtf("\n");
- seek += FMT(TRIE_NODE(TYPE))(n->child, buf + seek, depth + 1);
- }
- n = n->next;
- }
- return seek;
-
-}
-
-FMT_F(TRIE(TYPE)) {
- int seek = 0;
- fmtf("Trie: %p: {\n", self);
- seek += FMT(TRIE_NODE(TYPE))(self->root->child, buf + seek);
- fmtf("}");
- return seek;
-}
-
-#endif /* TYPE */
diff --git a/vcal.c b/vcal.c
deleted file mode 100644
index 7f674dac..00000000
--- a/vcal.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include "vcal.h"
-
-#include <string.h>
-
-#define TYPE strbuf
-#include "linked_list.inc.h"
-#undef TYPE
-
-#define TYPE param_set
-#include "linked_list.inc.h"
-#undef TYPE
-
-#define TYPE content_set
-#include "linked_list.inc.h"
-#undef TYPE
-
-#define T strbuf
- #define V LLIST(strbuf)
- #include "pair.inc.h"
- #undef V
- #define V LLIST(param_set)
- #include "pair.inc.h"
- #undef V
- #define V LLIST(content_set)
- #include "pair.inc.h"
- #undef V
-#undef T
-
-#define TYPE content_line
-// #include "hash.inc"
-#include "trie.inc.h"
-#undef TYPE
-
-#define TYPE vcomponent
-#include "vector.inc.h"
-#undef TYPE
-
-INIT_F(vcomponent) {
- (void) self;
- ERR("Do not use");
- return 0;
-}
-
-INIT_F(vcomponent, char* type) {
- return INIT(vcomponent, self, type, NULL);
-}
-
-INIT_F(vcomponent, char* type, char* filename) {
-
- INIT(TRIE(content_line), &self->clines);
- INIT(VECT(vcomponent), &self->components);
-
- self->filename = NULL;
- if (filename != NULL) {
- self->filename = (char*) calloc(sizeof(*filename), strlen(filename) + 1);
- strcpy(self->filename, filename);
- }
-
- self->type = (char*) calloc(sizeof(*type), strlen(type) + 1);
- strcpy(self->type, type);
-
- self->parent = NULL;
-
- return 0;
-}
-
-content_line* RESOLVE(content_line)
- (content_line* dest, content_line* new_)
-{
- if (dest == NULL) return new_;
-
- if (strbuf_cmp(&dest->key, &new_->key) != 0) {
- ERR("Can't resolve between these two types");
- return NULL;
- }
-
- /* This destroys new_->val. */
- APPEND(LLIST(content_set)) (&dest->val, &new_->val);
-
- FREE(strbuf)(&new_->key);
- free(new_);
-
- return dest;
-}
-
-content_line* get_property (vcomponent* ev, char* key) {
- return GET(TRIE(content_line))(&ev->clines, key);
-}
-
-FREE_F(vcomponent) {
- if (self->filename != NULL) free(self->filename);
- free(self->type);
-
- if (FREE(TRIE(content_line))(&self->clines) != 0) {
- fprintf(stderr, "Error freeing vcomponent belonging to file \n %s \n",
- self->filename);
- }
-
- FREE(VECT(vcomponent))(&self->components);
-
- return 0;
-}
-
-int PUSH(vcomponent)(vcomponent* parent, vcomponent* child) {
- return PUSH(VECT(vcomponent))(&parent->components, child);
-}
-
-int DEEP_COPY(vcomponent)(vcomponent* a, vcomponent* b) {
- (void) a;
- (void) b;
- ERR("Deep copy not implemented for vcomponent");
- return -1;
-}
-
-FMT_F(vcomponent) {
- int seek = 0;
-
- for (int i = 0; i < 40; i++) fmtf("_");
-
- seek += sprintf(buf + seek, _YELLOW);
- seek += sprintf(buf + seek, "\nVComponet (Type := %s)\n", self->type);
- seek += sprintf(buf + seek, _RESET);
- seek += FMT(TRIE(content_line))(&self->clines, buf + seek);
- seek += sprintf(buf + seek, "\nComponents:\n");
- FOR(VECT, vcomponent, comp, &self->components) {
- seek += FMT(vcomponent)(comp, buf + seek);
- }
-
- return seek;
-}
diff --git a/vcal.cpp b/vcal.cpp
new file mode 100644
index 00000000..a104664d
--- /dev/null
+++ b/vcal.cpp
@@ -0,0 +1,14 @@
+#include "vcal.h"
+#include "err.h"
+
+std::ostream& operator<<(std::ostream& o, vcomponent* self) {
+ for (int i = 0; i < 40; i++) o << '_';
+
+ o << _YELLOW << std::endl
+ << "VComponet (Type := " << self->type << _RESET
+ << self->clines
+ << std::endl << "Components:" << std::endl
+ << self->components;
+
+ return o;
+}
diff --git a/vcal.h b/vcal.h
index 1c96c4c6..bb30e482 100644
--- a/vcal.h
+++ b/vcal.h
@@ -1,47 +1,20 @@
#ifndef VCAL_H
#define VCAL_H
-#include <stdlib.h>
-
-#include "strbuf.h"
-
-#define TYPE strbuf
-#include "linked_list.h"
-// #include "trie.h"
-#undef TYPE
-
-#define T strbuf
- #define V LLIST(strbuf)
- #include "pair.h"
- /* left := param_name | right := param_values */
- #define param_set PAIR(strbuf, LLIST(strbuf))
- #undef V
-#undef T
-
-#define TYPE param_set
-#include "linked_list.h"
-#undef TYPE
-
-#define T strbuf
- #define V LLIST(param_set)
- #include "pair.h"
- /* left := content | right := params */
- #define content_set PAIR(strbuf, LLIST(param_set))
- #undef V
-#undef T
-
-#define TYPE content_set
-#include "linked_list.h"
-#undef TYPE
-
-#define T strbuf
- #define V LLIST(content_set)
- #include "pair.h"
- /* left := content | right := params */
- #define content_line PAIR(strbuf, LLIST(content_set))
- #undef V
-#undef T
+#include <string>
+#include <utility>
+#include <vector>
+#include <list>
+#include <iostream>
+#include "trie.h"
+
+
+typedef std::pair<strbuf, std::list<strbuf> > param_set;
+typedef std::pair<strbuf, std::list<param_set> > content_set;
+typedef std::pair<strbuf, std::list<content_set> > content_line;
+
+#if 0
/*
* Helper macros for accessing fields in
* content_line, content_set, and param_set
@@ -50,21 +23,36 @@
*/
/* ptr -> ptr */
-#define CLINE_KEY(c) (&(c)->key)
-#define CLINE_CUR_CSET(c) (&((c)->val.cur->value))
+#define CLINE_KEY(c) (&(c)->first)
+#define CLINE_CUR_CSET(c) (&((c)->second.cur->value))
/* content_set */
-#define CLINE_CUR(c) ((c)->val.cur->value)
+#define CLINE_CUR(c) ((c)->second.cur->value)
/* strbuf */
-#define CLINE_CUR_VAL(c) (& CLINE_CUR(c)->key)
+#define CLINE_CUR_VAL(c) (& CLINE_CUR(c)->first)
-/* LLIST(param_set) */
-#define CLINE_CUR_PARAMS(c) (& CLINE_CUR(c)->val)
+ /* LLIST(param_set) */
+#define CLINE_CUR_PARAMS(c) (& CLINE_CUR(c)->second)
+
+ /* strbuf */
+#define CLINE_CUR_PARAM_KEY(c) (CLINE_CUR_PARAMS(c)->cur->value->first)
+ /* strbuf */
+#define CLINE_CUR_PARAM_VAL(c) (CLINE_CUR_PARAMS(c)->cur->value->second.cur->value)
+#endif
+
+ struct vcomponent {
+ std::string filename;
+ std::string type;
+ vcomponent* parent = nullptr;
+ trie<content_line> clines;
+ std::vector<vcomponent> components;
+
+ vcomponent(const std::string& type) : vcomponent(type, nullptr) { };
+ vcomponent(const std::string& type, const std::string& filename)
+ : type(type) , filename(filename) { };
+
+ ~vcomponent();
-/* strbuf */
-#define CLINE_CUR_PARAM_KEY(c) (CLINE_CUR_PARAMS(c)->cur->value->key)
-/* strbuf */
-#define CLINE_CUR_PARAM_VAL(c) (CLINE_CUR_PARAMS(c)->cur->value->val.cur->value)
/*
* Resolves a collision in some form of structure (probably a hash-map
@@ -72,46 +60,16 @@
* to have the correct form, and returns it. Destroying new_ in the
* process.
*/
-content_line* RESOLVE(content_line)
- (content_line* dest, content_line* new_);
+ vcomponent* operator= (vcomponent* other);
-#define TYPE content_line
-#include "trie.h"
-#undef TYPE
+ content_line& operator[] (char* key) {
+ return this->clines[key];
+ }
-typedef struct s_vcomponent vcomponent;
-
-#define TYPE vcomponent
-#include "vector.h"
-#undef TYPE
-
-struct s_vcomponent {
- char* filename;
- char* type;
- vcomponent* parent;
- TRIE(content_line) clines;
- VECT(vcomponent) components;
+ void push_back(const vcomponent& child)
+ { this->components.push_back(child); }
};
-#define FCHILD(v) GET(VECT(vcomponent))(&(v)->components, 0)
-
-INIT_F(vcomponent);
-INIT_F(vcomponent, char* type);
-INIT_F(vcomponent, char* type, char* filename);
-FREE_F(vcomponent);
-
-content_line* get_property (vcomponent* ev, char* key);
-
-int add_content_line (vcomponent* ev, content_line* c);
-
-/*
- * Appends ev to cal. Doesn't copy ev. So make sure that it wont go
- * out of scope.
- */
-int PUSH(vcomponent)(vcomponent*, vcomponent*);
-
-int DEEP_COPY(vcomponent)(vcomponent*, vcomponent*);
-
-FMT_F(vcomponent);
+std::ostream& operator<<(std::ostream&, vcomponent*);
#endif /* VCAL_H */