add initial parsing functions - ics2txt - convert icalendar .ics file to plain … | |
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
commit 8248ba97aa609be30e0ecf481d93e59a9876afcd | |
parent a7b4ceeaf4a57476c0952e0da2def5f92bdfdb9f | |
Author: Josuah Demangeon <[email protected]> | |
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(-) | |
--- | |
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); | |
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… | |
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); | |
} | |
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); | |
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; |