From c4a0c84c3e569bac79c82cb588d8fd600b234c0b Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Fri, 12 Oct 2012 22:22:44 +0000 Subject: [PATCH] Working iCalendar parsing --- cal/dummy.c | 4 +- cal/ical.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/date.c | 5 ++ src/event.c | 3 +- src/event.h | 6 +-- view/week.c | 2 +- 6 files changed, 148 insertions(+), 11 deletions(-) diff --git a/cal/dummy.c b/cal/dummy.c index 1e40fec..fb87063 100644 --- a/cal/dummy.c +++ b/cal/dummy.c @@ -43,8 +43,8 @@ static event_t events[8]; event_t *dummy_get(cal_t *cal, year_t year, month_t month, day_t day, int days) { for (int i = 0; i < N_ELEMENTS(events); i++) { - datetime_t *s = &events[i].start; - datetime_t *e = &events[i].end; + date_t *s = &events[i].start; + date_t *e = &events[i].end; events[i] = event; add_days(&s->year, &s->month, &s->day, 7*i); add_days(&e->year, &e->month, &e->day, 7*i); diff --git a/cal/ical.c b/cal/ical.c index f4709a9..23844a3 100644 --- a/cal/ical.c +++ b/cal/ical.c @@ -23,18 +23,135 @@ #include "date.h" #include "event.h" +/* Local types */ +typedef struct { + icalcomponent *comp; + struct icaltimetype start; + struct icaltimetype end; +} ical_inst; + /* Helper functions */ -static event_t *to_event(icalcomponent *comp) +static int ical_compare(const void *_a, const void *_b) +{ + const ical_inst *a = _a; + const ical_inst *b = _b; + int scomp = icaltime_compare(a->start, b->start); + int ecomp = icaltime_compare(a->end, b->end); + return scomp != 0 ? scomp : + ecomp != 0 ? ecomp : 0 ; +} + +static date_t to_date(struct icaltimetype time) +{ + return (date_t){ + .year = time.year, + .month = time.month-1, + .day = time.day-1, + .hour = time.hour, + .min = time.minute, + }; +} + +static event_t *to_event(ical_inst *inst) { - event_t *event = calloc(1, sizeof(event)); + event_t *event = calloc(1, sizeof(event_t)); + event->name = icalcomponent_get_summary(inst->comp); + event->desc = icalcomponent_get_description(inst->comp); + event->start = to_date(inst->start); + event->end = to_date(inst->end); return event; } +static event_t *to_list(icalarray *array) +{ + event_t list = {}; + event_t *tail = &list; + for (int i = 0; i < array->num_elements; i++) { + ical_inst *inst = icalarray_element_at(array, i); + tail->next = to_event(inst); + tail = tail->next; + } + return list.next; +} + +static void print_list(event_t *start) +{ + for (event_t *cur = start; cur; cur = cur->next) + printf("%04d-%02d-%02d %02d:%02d - %s\n", + cur->start.year, cur->start.month, cur->start.day, + cur->start.hour, cur->start.min, + cur->name ?: cur->desc ?: "[no summary]"); +} + +static void add_events(icalarray *array, icalcomponent *comp, + icaltimetype start, icaltimetype end) +{ + icalcomponent_kind kind = icalcomponent_isa(comp); + + if (kind == ICAL_VEVENT_COMPONENT || + kind == ICAL_VTODO_COMPONENT) { + /* Get recurrence data */ + struct icaltimetype cstart, cend; // Component times + struct icaltimetype istart, iend; // Instance times + struct icaldurationtype length; // Duration + + icalproperty *rrule; + struct icalrecurrencetype recur; + icalrecur_iterator *iter; + + cstart = icalcomponent_get_dtstart(comp); + cend = icalcomponent_get_dtend(comp); + length = icaltime_subtract(cend, cstart); + + rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); + recur = icalproperty_get_rrule(rrule); + iter = icalrecur_iterator_new(recur, cstart); + + /* Add recurrences */ + while (1) { + istart = icalrecur_iterator_next(iter); + if (icaltime_is_null_time(istart)) + break; // no more instances + iend = icaltime_add(istart, length); + if (icaltime_compare(iend, start) <= 0) + continue; // instance ends before start time + if (icaltime_compare(istart, end) >= 0) + break; // instance begins after stop time + icalarray_append(array, &(ical_inst){ + .comp = comp, + .start = istart, + .end = iend, + }); + } + } + + /* Add children */ + icalcomponent_kind find = ICAL_ANY_COMPONENT; + icalcomponent *child = icalcomponent_get_first_component(comp, find); + while (child) { + add_events(array, child, start, end); + child = icalcomponent_get_next_component(comp, find); + } +} + /* Event functions */ event_t *ical_get(cal_t *cal, year_t year, month_t month, day_t day, int days) { - (void)to_event; - return NULL; + /* Load ical */ + FILE *file = fopen("data/all.ics", "r"); + icalparser *parser = icalparser_new(); + icalparser_set_gen_data(parser, file); + icalcomponent *ical = icalparser_parse(parser, (void*)fgets); + + /* Add events */ + icalarray *array = icalarray_new(sizeof(ical_inst), 1); + icaltimetype start = {.year = 2000}; + icaltimetype end = {.year = 2020}; + add_events(array, ical, start, end); + icalarray_sort(array, ical_compare); + return to_list(array); + + /* Todo, memory management */ } /* Test functions */ @@ -60,10 +177,24 @@ void ical_printr(icalcomponent *comp, int depth) void ical_test(void) { + /* Load ical */ FILE *file = fopen("data/all.ics", "r"); icalparser *parser = icalparser_new(); icalparser_set_gen_data(parser, file); icalcomponent *ical = icalparser_parse(parser, (void*)fgets); + + /* Test print */ ical_printr(ical, 0); + + /* Test Add */ + icalarray *array = icalarray_new(sizeof(ical_inst), 1); + icaltimetype start = {.year = 2000}; + icaltimetype end = {.year = 2020}; + add_events(array, ical, start, end); + icalarray_sort(array, ical_compare); + event_t *events = to_list(array); + print_list(events); + + /* Cleanup */ icalparser_free(parser); } diff --git a/src/date.c b/src/date.c index ec71579..965f15a 100644 --- a/src/date.c +++ b/src/date.c @@ -36,6 +36,11 @@ void date_init(void) YEAR = tm->tm_year+1900; MONTH = tm->tm_mon; DAY = tm->tm_mday-1; + + // Testing */ + YEAR = 2009; + MONTH = MAY; + DAY = 1; } /* Time functions */ diff --git a/src/event.c b/src/event.c index 76d33ce..e4dfe79 100644 --- a/src/event.c +++ b/src/event.c @@ -37,5 +37,6 @@ void event_init(void) /* Event get */ event_t *event_get(year_t year, month_t month, day_t day, int days) { - return dummy_get(0, year, month, day, days); + //return dummy_get(0, year, month, day, days); + return ical_get(0, year, month, day, days); } diff --git a/src/event.h b/src/event.h index b75f890..43e50b2 100644 --- a/src/event.h +++ b/src/event.h @@ -29,14 +29,14 @@ typedef struct { day_t day; hour_t hour; min_t min; -} datetime_t; +} date_t; typedef struct event_t { const cal_t *cal; - datetime_t start; - datetime_t end; const char *name; const char *desc; + date_t start; + date_t end; struct event_t *next; } event_t; diff --git a/view/week.c b/view/week.c index 230a7c5..9f8419d 100644 --- a/view/week.c +++ b/view/week.c @@ -37,7 +37,7 @@ static void print_event(event_t *event, wday_t day, hour_t hour, min_t min, floa (void)l; } -static int before(datetime_t *start, int year, int month, int day, int hour, int min) +static int before(date_t *start, int year, int month, int day, int hour, int min) { int rval = start->year < year ? 1 : start->year > year ? 0 : start->month < month ? 1 : start->month > month? 0 : -- 2.43.2