Introduction
Introduction Statistics Contact Development Disclaimer Help
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;
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.