Home
add initial parsing functions - ics2txt - convert icalendar .ics file to plain text HTML git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit 8248ba97aa609be30e0ecf481d93e59a9876afcd DIR parent a7b4ceeaf4a57476c0952e0da2def5f92bdfdb9f HTML Author: Josuah Demangeon <me@josuah.net> Date: Sun, 28 Jun 2020 14:33:48 +0200 add initial parsing functions Diffstat: M ics2tsv.c | 7 ++++--- M src/ical.c | 93 +++++++++++++++++++++++++++---- M src/ical.h | 40 ++++++++++++++++++++++++++++---- M src/map.c | 3 --- 4 files changed, 122 insertions(+), 21 deletions(-) --- DIR diff --git a/ics2tsv.c b/ics2tsv.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "ical.h" #include "log.h" @@ -8,16 +9,16 @@ int print_ical_to_tsv(FILE *fp) { - struct ical_contentline contentline; + struct ical_contentline cl; char *line = NULL, *ln = NULL; size_t sz = 0; ssize_t r; - ical_init_contentline(&contentline); + memset(&cl, 0, sizeof cl); while ((r = ical_read_line(&line, &ln, &sz, fp)) > 0) { debug("readling line \"%s\"", line); - if (ical_parse_contentline(&contentline, line) < 0) + if (ical_parse_contentline(&cl, line) < 0) die("parsing line \"%s\"", line); } free(line); DIR diff --git a/src/ical.c b/src/ical.c @@ -1,9 +1,11 @@ #include "ical.h" +#include <assert.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> /* strcase* */ #include "util.h" @@ -29,19 +31,21 @@ ical_read_line(char **line, char **ln, size_t *sz, FILE *fp) } while (c == ' '); ungetc(c, fp); + assert(!ferror(fp)); return 1; } int -ical_parse_contentline(struct ical_contentline *contentline, char *line) +ical_parse_contentline(struct ical_contentline *cl, char *line) { char *column, *equal, *param, *cp; size_t sz; + int e = errno; if ((column = strchr(line, ':')) == NULL) return -1; *column = '\0'; - if ((contentline->value = strdup(column + 1)) == NULL) + if ((cl->value = strdup(column + 1)) == NULL) return -1; if ((cp = strchr(line, ';')) != NULL) @@ -50,27 +54,94 @@ ical_parse_contentline(struct ical_contentline *contentline, char *line) if ((equal = strchr(param, '=')) == NULL) return -1; *equal = '\0'; - if (map_set(&contentline->param, param, equal + 1) < 0) + if (map_set(&cl->param, param, equal + 1) < 0) return -1; } - sz = sizeof(contentline->name); - if (strlcpy(contentline->name, line, sz) >= sz) + sz = sizeof cl->name; + if (strlcpy(cl->name, line, sz) >= sz) return errno=EMSGSIZE, -1; + assert(errno == e); return 0; } -void -ical_init_contentline(struct ical_contentline *contentline) +int +ical_parse_tzid(struct ical_value *value, struct ical_contentline *cl) +{ + return 0; +} + +int +ical_parse_date(struct ical_value *value, struct ical_contentline *cl) +{ + return 0; +} + +int +ical_parse_attribute(struct ical_value *value, struct ical_contentline *cl) +{ + return 0; +} + +int +ical_begin_vnode(struct ical_vcalendar *vcal, char const *name) { - memset(contentline, 0, sizeof(*contentline)); + if (strcasecmp(name, "VCALENDAR")) + return 0; + return -1; } +int +ical_end_vnode(struct ical_vcalendar *vcal, char const *name) +{ + if (strcasecmp(name, "VCALENDAR")) + return 0; + return -1; +} + +int +ical_add_contentline(struct ical_vcalendar *vcal, struct ical_contentline *cl) +{ + struct ical_value value_buf, *value = &value_buf; + int i; + struct { + char *name; + enum ical_value_type type; + int (*fn)(struct ical_value *, struct ical_contentline *); + } map[] = { + { "DTSTART", ICAL_VALUE_TIME, ical_parse_date }, + { "DTEND", ICAL_VALUE_TIME, ical_parse_date }, + { "TZID", ICAL_VALUE_TIME, ical_parse_tzid }, + { NULL, ICAL_VALUE_ATTRIBUTE, ical_parse_attribute }, + }; + + if (strcasecmp(cl->name, "BEGIN") == 0) + return ical_begin_vnode(vcal, cl->value); + + if (strcasecmp(cl->name, "END") == 0) + return ical_end_vnode(vcal, cl->value); + + memset(value, 0, sizeof *value); + + for (i = 0; map[i].name == NULL; i++) + if (strcasecmp(cl->name, map[i].name) == 0) + break; + value->type = map[i].type; + if (map[i].fn(value, cl) < 0) + return -1; + return 0; +} + +void +ical_free_value(struct ical_value *value) +{ + ; +} void -ical_free_contentline(struct ical_contentline *contentline) +ical_free_contentline(struct ical_contentline *cl) { - map_free(&contentline->param); - free(contentline->value); + map_free(&cl->param); + free(cl->value); } DIR diff --git a/src/ical.h b/src/ical.h @@ -6,16 +6,48 @@ #include "map.h" -struct ical_vevent { - time_t beg, end; - struct map map; -}; +#define ICAL_NEST_MAX 4 + +/* */ struct ical_contentline { char name[32], *value; struct map param; }; +/* single value for an iCalendar element attribute */ + +enum ical_value_type { + ICAL_VALUE_TIME, ICAL_VALUE_ATTRIBUTE, +} type; + +union ical_value_union { + time_t *time; + char *str; +}; + +struct ical_value { + enum ical_value_type type; + union ical_value_union value; +}; + +/* global propoerties for an iCalendar document as well as parsing state */ + +struct ical_vcalendar { + time_t tzid; + char *stack[ICAL_NEST_MAX + 1]; + struct ical_vnode *current; +}; + +/* element part of an iCalendar document with eventual nested childs */ + +struct ical_vnode { + char name[32]; + time_t beg, end; + struct map properties; /* struct ical_value */ + struct ical_vnode *child, *next; +}; + /** src/ical.c **/ int ical_read_line(char **line, char **ln, size_t *sz, FILE *fp); int ical_parse_contentline(struct ical_contentline *contentline, char *line); DIR diff --git a/src/map.c b/src/map.c @@ -32,11 +32,8 @@ map_set(struct map *map, char *key, void *value) size_t i, sz; void *v; - debug("%s: key=%s len=%zd", __func__, key, map->len); - for (i = 0; i < map->len; i++) { int cmp = strcmp(key, map->entry[i].key); - debug("cmp(%s,%s)=%d", key, map->entry[i].key, cmp); if (cmp == 0) { map->entry[i].value = value;