Back to index

lightning-sunbird  0.9+nobinonly
Classes | Functions
icalspanlist.c File Reference
#include "ical.h"
#include "icalspanlist.h"
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Classes

struct  icalspanlist_impl

Functions

static int compare_span (void *a, void *b)
 Internal comparison function for two spans.
static void icalspanlist_new_callback (icalcomponent *comp, struct icaltime_span *span, void *data)
 callback function for collecting spanlists of a series of events.
icalspanlist * icalspanlist_new (icalset *set, struct icaltimetype start, struct icaltimetype end)
 Make a free list from a set of VEVENT components.
void icalspanlist_free (icalspanlist *s)
 Destructor.
void icalspanlist_dump (icalspanlist *sl)
 (Debug) print out spanlist to stdout.
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)
 Find next free time span in a spanlist.
struct icalperiodtype icalspanlist_next_busy_time (icalspanlist *sl, struct icaltimetype t)
inticalspanlist_as_freebusy_matrix (icalspanlist *sl, int delta_t)
 Returns an hour-by-hour array of free/busy times over a given period.
icalcomponent * icalspanlist_as_vfreebusy (icalspanlist *sl, const char *organizer, const char *attendee)
 Return a VFREEBUSY component for the corresponding spanlist.
icalspanlist * icalspanlist_from_vfreebusy (icalcomponent *comp)
 Return a spanlist corresponding to the VFREEBUSY portion of an icalcomponent.

Class Documentation

struct icalspanlist_impl

Definition at line 35 of file icalspanlist.c.

Collaboration diagram for icalspanlist_impl:
Class Members
pvl_list spans list of icaltime_span data

Function Documentation

static int compare_span ( void a,
void b 
) [static]

Internal comparison function for two spans.

Parameters:
aa spanlist.
banother spanlist.
Returns:
-1, 0, 1 depending on the comparison of the start times.

Used to insert spans into the tree in sorted order.

Definition at line 51 of file icalspanlist.c.

{
    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;
    }
}

Here is the caller graph for this function:

int* icalspanlist_as_freebusy_matrix ( icalspanlist *  sl,
int  delta_t 
)

Returns an hour-by-hour array of free/busy times over a given period.

Return an integer matrix of total events per delta_t timespan.

Parameters:
slA valid icalspanlist
delta_tThe time slice to divide by, in seconds. Default 3600.
Returns:
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.

calculate the start and end time as time_t

insure that the time period falls on a time boundary divisable by delta_t

find the duration of this spanlist

malloc our matrix, add one extra slot for a final -1

Definition at line 372 of file icalspanlist.c.

                                                                    {
  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;

  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());


  sl_start /= delta_t;
  sl_start *= delta_t;

  sl_end /= delta_t;
  sl_end *= delta_t;


  spanduration_secs = sl_end - sl_start;


  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

icalcomponent* icalspanlist_as_vfreebusy ( icalspanlist *  sl,
const char *  organizer,
const char *  attendee 
)

Return a VFREEBUSY component for the corresponding spanlist.

Return a valid VFREEBUSY component for this span.

Parameters:
slA valid icalspanlist, from icalspanlist_new()
organizerThe organizer specified as MAILTO:user
attendeeThe attendee specified as MAILTO:user
Returns:
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.

Definition at line 452 of file icalspanlist.c.

                                                          {
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void icalspanlist_dump ( icalspanlist *  sl)

(Debug) print out spanlist to stdout.

Parameters:
slA valid icalspanlist.

Definition at line 253 of file icalspanlist.c.

                                        {
     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));

    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void icalspanlist_free ( icalspanlist *  s)

Destructor.

Parameters:
sA valid icalspanlist

Free memory associated with the spanlist

Definition at line 230 of file icalspanlist.c.

{
    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

icalspanlist* icalspanlist_from_vfreebusy ( icalcomponent *  comp)

Return a spanlist corresponding to the VFREEBUSY portion of an icalcomponent.

Construct an icalspanlist from a VFREEBUSY component.

Parameters:
cA valid icalcomponent.
Returns:
A valid icalspanlist or NULL if no VFREEBUSY section.
Todo:
calculate start/end limits.. fill in holes?

Definition at line 516 of file icalspanlist.c.

{
  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);
  }
  return sl;
}

Here is the call graph for this function:

Here is the caller graph for this function:

icalcomponent* icalspanlist_make_busy_list ( icalspanlist *  sl)
icalcomponent* icalspanlist_make_free_list ( icalspanlist *  sl)
icalspanlist* icalspanlist_new ( icalset *  set,
struct icaltimetype  start,
struct icaltimetype  end 
)

Make a free list from a set of VEVENT components.

Constructor Make a free list from a set of component.

Parameters:
setA valid icalset containing VEVENTS
startThe free list starts at this date/time
endThe free list ends at this date/time
Returns:
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.

Definition at line 111 of file icalspanlist.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void icalspanlist_new_callback ( icalcomponent *  comp,
struct icaltime_span span,
void data 
) [static]

callback function for collecting spanlists of a series of events.

Parameters:
compA valid icalcomponent.
spanThe span to insert into data.
dataThe actual spanlist to insert into

This callback is used by icalcomponent_foreach_recurrence() to build up a spanlist.

copy span data into allocated memory..

Definition at line 77 of file icalspanlist.c.

{
  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;
  }

  *s = *span;
  pvl_insert_ordered(sl->spans, compare_span, (void*)s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct icalperiodtype icalspanlist_next_busy_time ( icalspanlist *  sl,
struct icaltimetype  t 
) [read]
struct icalperiodtype icalspanlist_next_free_time ( icalspanlist *  sl,
struct icaltimetype  t 
) [read]

Find next free time span in a spanlist.

Get first next free time after time t.

Parameters:
slThe spanlist to search.
tThe time to start looking.

Given a spanlist and a time, find the next period of time that is free

Definition at line 282 of file icalspanlist.c.

{
     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;
}

Here is the call graph for this function:

Here is the caller graph for this function: