diff options
Diffstat (limited to 'libical/src/libicalss/icalspanlist.c')
-rw-r--r-- | libical/src/libicalss/icalspanlist.c | 567 |
1 files changed, 0 insertions, 567 deletions
diff --git a/libical/src/libicalss/icalspanlist.c b/libical/src/libicalss/icalspanlist.c deleted file mode 100644 index 6c366fa5ba..0000000000 --- a/libical/src/libicalss/icalspanlist.c +++ /dev/null @@ -1,567 +0,0 @@ -/* -*- 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 <libical/ical.h> -#include "icalspanlist.h" - -#include <stdlib.h> /* for free and malloc */ -#include <string.h> - -struct icalspanlist_impl { - pvl_list spans; /**< list of icaltime_span data **/ - struct icaltimetype start; /**< start time of span **/ - struct icaltimetype end; /**< end time of span **/ -}; - -/** @brief Internal comparison function for two spans - * - * @param a a spanlist. - * @param b another spanlist. - * - * @return -1, 0, 1 depending on the comparison of the start times. - * - * Used to insert spans into the tree in sorted order. - */ - -static 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; - } -} - - -/** @brief callback function for collecting spanlists of a - * series of events. - * - * @param comp A valid icalcomponent. - * @param span The span to insert into data. - * @param data The actual spanlist to insert into - * - * This callback is used by icalcomponent_foreach_recurrence() - * to build up a spanlist. - */ - -static void icalspanlist_new_callback(icalcomponent *comp, - struct icaltime_span *span, - void *data) -{ - icaltime_span *s; - icalspanlist *sl = (icalspanlist*) data; - - if (span->is_busy == 0) - return; - - if ((s=(icaltime_span *) malloc(sizeof(icaltime_span))) == 0) { - icalerror_set_errno(ICAL_NEWFAILED_ERROR); - return; - } - - /** copy span data into allocated memory.. **/ - *s = *span; - pvl_insert_ordered(sl->spans, compare_span, (void*)s); -} - - - -/** @brief Make a free list from a set of VEVENT components. - * - * @param set A valid icalset containing VEVENTS - * @param start The free list starts at this date/time - * @param end The free list ends at this date/time - * - * @return A spanlist corresponding to the VEVENTS - * - * Given a set of components, a start time and an end time - * return a spanlist that contains the free/busy times. - */ - -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; - icalspanlist *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(); - sl->start = start; - sl->end = end; - - range.start = icaltime_as_timet(start); - range.end = icaltime_as_timet(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)){ - - 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(); - - icalcomponent_foreach_recurrence(c, start, end, - icalspanlist_new_callback, - (void*)sl); - - } - - /* 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 = (struct icaltime_span*)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 = (struct icaltime_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; -} - -/** @brief Destructor. - * @param s A valid icalspanlist - * - * Free memory associated with the spanlist - */ - -void icalspanlist_free(icalspanlist* s) -{ - struct icaltime_span *span; - - if (s == NULL) - return; - - while( (span=pvl_pop(s->spans)) != 0){ - free(span); - } - - pvl_free(s->spans); - - s->spans = 0; - - free(s); -} - - -/** @brief (Debug) print out spanlist to stdout. - * @param sl A valid icalspanlist. - */ - -void icalspanlist_dump(icalspanlist* sl){ - int i = 0; - pvl_elem itr; - - for( itr = pvl_head(sl->spans); - itr != 0; - itr = pvl_next(itr)) - { - struct icaltime_span *s = (struct icaltime_span*)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); - - -/** @brief Find next free time span in a spanlist. - * - * @param sl The spanlist to search. - * @param t The time to start looking. - * - * Given a spanlist and a time, find the next period of time - * that is free - */ - -struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl, - struct icaltimetype t) -{ - 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(); - - itr = pvl_head(sl->spans); - s = (struct icaltime_span *)pvl_data(itr); - - if (s == 0){ - /* No elements in span */ - return period; - } - - /* Is the reference time before the first span? If so, assume - that the reference time is free */ - 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 == 1){ - 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(sl->spans); - itr != 0; - itr = pvl_next(itr)) - { - s = (struct icaltime_span *)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); - - -/** @brief Returns an hour-by-hour array of free/busy times over a - * given period. - * - * @param sl A valid icalspanlist - * @param delta_t The time slice to divide by, in seconds. Default 3600. - * - * @return A pointer to an array of integers containing the number of - * busy events in each delta_t time period. The final entry - * contains the value -1. - * - * This calculation is somewhat tricky. This is due to the fact that - * the time range contains the start time, but does not contain the - * end time. To perform a proper calculation we subtract one second - * off the end times to get a true containing time. - * - * Also note that if you supplying a spanlist that does not start or - * end on a time boundary divisible by delta_t you may get results - * that are not quite what you expect. - */ - -int* icalspanlist_as_freebusy_matrix(icalspanlist* sl, int delta_t) { - pvl_elem itr; - int spanduration_secs; - int *matrix; - int matrix_slots; - time_t sl_start, sl_end; - - icalerror_check_arg_rz( (sl!=0), "spanlist"); - - if (!delta_t) - delta_t = 3600; - - /** calculate the start and end time as time_t **/ - sl_start = icaltime_as_timet_with_zone(sl->start, icaltimezone_get_utc_timezone()); - sl_end = icaltime_as_timet_with_zone(sl->end, icaltimezone_get_utc_timezone()); - - - /** insure that the time period falls on a time boundary divisable - by delta_t */ - - sl_start /= delta_t; - sl_start *= delta_t; - - sl_end /= delta_t; - sl_end *= delta_t; - - - /** find the duration of this spanlist **/ - spanduration_secs = sl_end - sl_start; - - - /** malloc our matrix, add one extra slot for a final -1 **/ - matrix_slots = spanduration_secs/delta_t + 1; - - matrix = (int*) malloc(sizeof(int) * matrix_slots); - if (matrix == NULL) { - icalerror_set_errno(ICAL_NEWFAILED_ERROR); - return NULL; - } - memset(matrix, 0, sizeof(int) * matrix_slots); - matrix[matrix_slots-1] = -1; - - /* loop through each span and mark the slots in the array */ - - for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { - struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr); - - if (s->is_busy == 1) { - int offset_start = s->start/delta_t - sl_start/delta_t; - int offset_end = (s->end - 1) /delta_t - sl_start/delta_t + 1; - int i; - - if (offset_end >= matrix_slots) - offset_end = matrix_slots - 1; - - i = offset_start; - for (i=offset_start; i < offset_end; i++) { - matrix[i]++; - } - } - } - return matrix; -} - - -/** @brief Return a VFREEBUSY component for the corresponding spanlist - * - * @param sl A valid icalspanlist, from icalspanlist_new() - * @param organizer The organizer specified as MAILTO:user@domain - * @param attendee The attendee specified as MAILTO:user@domain - * - * @return A valid icalcomponent or NULL. - * - * This function returns a VFREEBUSY component for the given spanlist. - * The start time is mapped to DTSTART, the end time to DTEND. - * Each busy span is represented as a separate FREEBUSY entry. - * An attendee parameter is required, and organizer parameter is - * optional. - */ - -icalcomponent *icalspanlist_as_vfreebusy(icalspanlist* sl, - const char* organizer, - const char* attendee) { - icalcomponent *comp; - icalproperty *p; - struct icaltimetype atime = icaltime_from_timet( time(0),0); - pvl_elem itr; - icaltimezone *utc_zone; - icalparameter *param; - - if (!attendee) { - icalerror_set_errno(ICAL_USAGE_ERROR); - return 0; - } - - utc_zone = icaltimezone_get_utc_timezone (); - - comp = icalcomponent_new_vfreebusy(); - - icalcomponent_add_property(comp, icalproperty_new_dtstart(sl->start)); - icalcomponent_add_property(comp, icalproperty_new_dtend(sl->end)); - icalcomponent_add_property(comp, icalproperty_new_dtstamp(atime)); - - if (organizer) { - icalcomponent_add_property(comp, icalproperty_new_organizer(organizer)); - } - icalcomponent_add_property(comp, icalproperty_new_attendee(attendee)); - - /* now add the freebusy sections.. */ - - for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { - struct icalperiodtype period; - struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr); - - if (s->is_busy == 1) { - - period.start = icaltime_from_timet_with_zone (s->start, 0, utc_zone); - period.end = icaltime_from_timet_with_zone (s->end, 0, utc_zone); - period.duration = icaldurationtype_null_duration(); - - - p = icalproperty_new_freebusy(period); - param = icalparameter_new_fbtype(ICAL_FBTYPE_BUSY); - icalproperty_add_parameter(p, param); - - icalcomponent_add_property(comp, p); - } - - } - - return comp; -} - - -/** @brief Return a spanlist corresponding to the VFREEBUSY portion of - * an icalcomponent. - * - * @param c A valid icalcomponent. - * - * @return A valid icalspanlist or NULL if no VFREEBUSY section. - * - */ - - -icalspanlist *icalspanlist_from_vfreebusy(icalcomponent* comp) -{ - icalcomponent *inner; - icalproperty *prop; - icalspanlist *sl; - - icalerror_check_arg_rz((comp != NULL), "comp"); - - inner = icalcomponent_get_inner(comp); - if (!inner) return NULL; - - if ( ( sl = (icalspanlist*) malloc(sizeof(icalspanlist))) == 0) { - icalerror_set_errno(ICAL_NEWFAILED_ERROR); - return 0; - } - sl->spans = pvl_newlist(); - - /* cycle through each FREEBUSY property, adding to the spanlist */ - for (prop = icalcomponent_get_first_property(inner, ICAL_FREEBUSY_PROPERTY); - prop != NULL; - prop = icalcomponent_get_next_property(inner, ICAL_FREEBUSY_PROPERTY)) { - icaltime_span *s = (icaltime_span *) malloc(sizeof(icaltime_span)); - icalparameter *param; - struct icalperiodtype period; - icalparameter_fbtype fbtype; - - if (s == 0) { - icalerror_set_errno(ICAL_NEWFAILED_ERROR); - return 0; - } - - param = icalproperty_get_first_parameter(prop, ICAL_FBTYPE_PARAMETER); - fbtype = (param) ? icalparameter_get_fbtype(param) : ICAL_FBTYPE_BUSY; - - switch (fbtype) { - case ICAL_FBTYPE_FREE: - case ICAL_FBTYPE_NONE: - case ICAL_FBTYPE_X: - s->is_busy = 1; - default: - s->is_busy = 0; - } - - period = icalproperty_get_freebusy(prop); - s->start = icaltime_as_timet_with_zone(period.start, icaltimezone_get_utc_timezone()); - s->end = icaltime_as_timet_with_zone(period.end, icaltimezone_get_utc_timezone()); -; - pvl_insert_ordered(sl->spans, compare_span, (void*)s); - } - /** @todo calculate start/end limits.. fill in holes? **/ - return sl; -} |