summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalspanlist.c
Side-by-side diff
Diffstat (limited to 'libical/src/libicalss/icalspanlist.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libicalss/icalspanlist.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/libical/src/libicalss/icalspanlist.c b/libical/src/libicalss/icalspanlist.c
new file mode 100644
index 0000000..cab6a81
--- a/dev/null
+++ b/libical/src/libicalss/icalspanlist.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalspanlist.c
+ CREATOR: ebusboom 23 aug 2000
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ical.h"
+#include "icalspanlist.h"
+#include "pvl.h"
+#include <stdlib.h> /* for free and malloc */
+
+struct icalspanlist_impl {
+ pvl_list spans;
+};
+
+int compare_span(void* a, void* b)
+{
+ struct icaltime_span *span_a = (struct icaltime_span *)a ;
+ struct icaltime_span *span_b = (struct icaltime_span *)b ;
+
+ if(span_a->start == span_b->start){
+ return 0;
+ } else if(span_a->start < span_b->start){
+ return -1;
+ } else { /*if(span_a->start > span->b.start)*/
+ return 1;
+ }
+}
+
+icalcomponent* icalspanlist_get_inner(icalcomponent* comp)
+{
+ if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
+ return icalcomponent_get_first_real_component(comp);
+ } else {
+ return comp;
+ }
+}
+
+
+void print_span(int c, struct icaltime_span span );
+
+
+/* Make a free list from a set of component */
+icalspanlist* icalspanlist_new(icalset *set,
+ struct icaltimetype start,
+ struct icaltimetype end)
+{
+ struct icaltime_span range;
+ pvl_elem itr;
+ icalcomponent *c,*inner;
+ icalcomponent_kind kind, inner_kind;
+ struct icalspanlist_impl *sl;
+ struct icaltime_span *freetime;
+
+ if ( ( sl = (struct icalspanlist_impl*)
+ malloc(sizeof(struct icalspanlist_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ sl->spans = pvl_newlist();
+
+ range.start = icaltime_as_timet(start);
+ range.end = icaltime_as_timet(end);
+
+ printf("Range start: %s",ctime(&range.start));
+ printf("Range end : %s",ctime(&range.end));
+
+
+ /* Get a list of spans of busy time from the events in the set
+ and order the spans based on the start time */
+
+ for(c = icalset_get_first_component(set);
+ c != 0;
+ c = icalset_get_next_component(set)){
+
+ struct icaltime_span span;
+
+ kind = icalcomponent_isa(c);
+ inner = icalcomponent_get_inner(c);
+
+ if(!inner){
+ continue;
+ }
+
+ inner_kind = icalcomponent_isa(inner);
+
+ if( kind != ICAL_VEVENT_COMPONENT &&
+ inner_kind != ICAL_VEVENT_COMPONENT){
+ continue;
+ }
+
+ icalerror_clear_errno();
+
+ span = icalcomponent_get_span(c);
+ span.is_busy = 1;
+
+ if(icalerrno != ICAL_NO_ERROR){
+ continue;
+ }
+
+ if ((range.start < span.end && icaltime_is_null_time(end)) ||
+ (range.start < span.end && range.end > span.start )){
+
+ struct icaltime_span *s;
+
+ if ((s=(struct icaltime_span *)
+ malloc(sizeof(struct icaltime_span))) == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memcpy(s,&span,sizeof(span));
+
+ pvl_insert_ordered(sl->spans,compare_span,(void*)s);
+
+ }
+ }
+
+ /* Now Fill in the free time spans. loop through the spans. if the
+ start of the range is not within the span, create a free entry
+ that runs from the start of the range to the start of the
+ span. */
+
+ for( itr = pvl_head(sl->spans);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ struct icaltime_span *s = (icalproperty*)pvl_data(itr);
+
+ if ((freetime=(struct icaltime_span *)
+ malloc(sizeof(struct icaltime_span))) == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ if(range.start < s->start){
+ freetime->start = range.start;
+ freetime->end = s->start;
+
+ freetime->is_busy = 0;
+
+
+ pvl_insert_ordered(sl->spans,compare_span,(void*)freetime);
+ } else {
+ free(freetime);
+ }
+
+ range.start = s->end;
+ }
+
+ /* If the end of the range is null, then assume that everything
+ after the last item in the calendar is open and add a span
+ that indicates this */
+
+ if( icaltime_is_null_time(end)){
+ struct icaltime_span* last_span;
+
+ last_span = pvl_data(pvl_tail(sl->spans));
+
+ if (last_span != 0){
+
+ if ((freetime=(struct icaltime_span *)
+ malloc(sizeof(struct icaltime_span))) == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ freetime->is_busy = 0;
+ freetime->start = last_span->end;
+ freetime->end = freetime->start;
+ pvl_insert_ordered(sl->spans,compare_span,(void*)freetime);
+ }
+ }
+
+
+ return sl;
+
+}
+
+void icalspanlist_free(icalspanlist* s)
+{
+ struct icaltime_span *span;
+ struct icalspanlist_impl* impl = (struct icalspanlist_impl*)s;
+
+ while( (span=pvl_pop(impl->spans)) != 0){
+ free(span);
+ }
+
+ pvl_free(impl->spans);
+
+ impl->spans = 0;
+}
+
+
+void icalspanlist_dump(icalspanlist* s){
+
+ int i = 0;
+ struct icalspanlist_impl* sl = (struct icalspanlist_impl*)s;
+ pvl_elem itr;
+
+ for( itr = pvl_head(sl->spans);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ struct icaltime_span *s = (icalproperty*)pvl_data(itr);
+
+ printf("#%02d %d start: %s",++i,s->is_busy,ctime(&s->start));
+ printf(" end : %s",ctime(&s->end));
+
+ }
+}
+
+icalcomponent* icalspanlist_make_free_list(icalspanlist* sl);
+icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl);
+
+struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
+ struct icaltimetype t)
+{
+ struct icalspanlist_impl* impl = (struct icalspanlist_impl*)sl;
+ pvl_elem itr;
+ struct icalperiodtype period;
+ struct icaltime_span *s;
+
+ time_t rangett= icaltime_as_timet(t);
+
+ period.start = icaltime_null_time();
+ period.end = icaltime_null_time();
+
+ /* Is the reference time before the first span? If so, assume
+ that the reference time is free */
+ itr = pvl_head(impl->spans);
+ s = (icalproperty*)pvl_data(itr);
+
+ if (s == 0){
+ /* No elements in span */
+ return period;
+ }
+
+ if(rangett <s->start ){
+ /* End of period is start of first span if span is busy, end
+ of the span if it is free */
+ period.start = t;
+
+ if (s->is_busy == 0){
+ period.end = icaltime_from_timet(s->start,0);
+ } else {
+ period.end = icaltime_from_timet(s->end,0);
+ }
+
+ return period;
+ }
+
+ /* Otherwise, find the first free span that contains the
+ reference time. */
+
+ for( itr = pvl_head(impl->spans);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ s = (icalproperty*)pvl_data(itr);
+
+ if(s->is_busy == 0 && s->start >= rangett &&
+ ( rangett < s->end || s->end == s->start)){
+
+ if (rangett < s->start){
+ period.start = icaltime_from_timet(s->start,0);
+ } else {
+ period.start = icaltime_from_timet(rangett,0);
+ }
+
+ period.end = icaltime_from_timet(s->end,0);
+
+ return period;
+ }
+
+ }
+
+ period.start = icaltime_null_time();
+ period.end = icaltime_null_time();
+
+ return period;
+}
+
+struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl,
+ struct icaltimetype t);
+