Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions
icalrecur.h File Reference

Routines for dealing with recurring time. More...

#include <time.h>
#include "icaltime.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  icalrecurrencetype
 Main struct for holding digested recurrence rules. More...

Defines

#define ICAL_BY_SECOND_SIZE   61
 Recurrence type routines.
#define ICAL_BY_MINUTE_SIZE   61
#define ICAL_BY_HOUR_SIZE   25
#define ICAL_BY_DAY_SIZE   364 /* 7 days * 52 weeks */
#define ICAL_BY_MONTHDAY_SIZE   32
#define ICAL_BY_YEARDAY_SIZE   367
#define ICAL_BY_WEEKNO_SIZE   54
#define ICAL_BY_MONTH_SIZE   13
#define ICAL_BY_SETPOS_SIZE   367

Typedefs

typedef enum
icalrecurrencetype_frequency 
icalrecurrencetype_frequency
typedef enum
icalrecurrencetype_weekday 
icalrecurrencetype_weekday
typedef struct icalrecur_iterator_impl
 Recurrence iteration routines.

Enumerations

enum  icalrecurrencetype_frequency {
  ICAL_SECONDLY_RECURRENCE = 0, ICAL_MINUTELY_RECURRENCE = 1, ICAL_HOURLY_RECURRENCE = 2, ICAL_DAILY_RECURRENCE = 3,
  ICAL_WEEKLY_RECURRENCE = 4, ICAL_MONTHLY_RECURRENCE = 5, ICAL_YEARLY_RECURRENCE = 6, ICAL_NO_RECURRENCE = 7,
  ICAL_SECONDLY_RECURRENCE = 0, ICAL_MINUTELY_RECURRENCE = 1, ICAL_HOURLY_RECURRENCE = 2, ICAL_DAILY_RECURRENCE = 3,
  ICAL_WEEKLY_RECURRENCE = 4, ICAL_MONTHLY_RECURRENCE = 5, ICAL_YEARLY_RECURRENCE = 6, ICAL_NO_RECURRENCE = 7
}
enum  icalrecurrencetype_weekday {
  ICAL_NO_WEEKDAY, ICAL_SUNDAY_WEEKDAY, ICAL_MONDAY_WEEKDAY, ICAL_TUESDAY_WEEKDAY,
  ICAL_WEDNESDAY_WEEKDAY, ICAL_THURSDAY_WEEKDAY, ICAL_FRIDAY_WEEKDAY, ICAL_SATURDAY_WEEKDAY,
  ICAL_NO_WEEKDAY, ICAL_SUNDAY_WEEKDAY, ICAL_MONDAY_WEEKDAY, ICAL_TUESDAY_WEEKDAY,
  ICAL_WEDNESDAY_WEEKDAY, ICAL_THURSDAY_WEEKDAY, ICAL_FRIDAY_WEEKDAY, ICAL_SATURDAY_WEEKDAY
}
enum  { ICAL_RECURRENCE_ARRAY_MAX = 0x7f7f, ICAL_RECURRENCE_ARRAY_MAX_BYTE = 0x7f }

Functions

void icalrecurrencetype_clear (struct icalrecurrencetype *r)
enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week (short day)
 Array Encoding.
int icalrecurrencetype_day_position (short day)
 0 == any of day of week.
icalrecurrencetype_weekday icalrecur_string_to_weekday (const char *str)
struct icalrecurrencetype icalrecurrencetype_from_string (const char *str)
 Recurrance rule parser.
char * icalrecurrencetype_as_string (struct icalrecurrencetype *recur)
icalrecur_iterator * icalrecur_iterator_new (struct icalrecurrencetype rule, struct icaltimetype dtstart)
 Create a new recurrence rule iterator.
struct icaltimetype icalrecur_iterator_next (icalrecur_iterator *)
 Get the next occurrence from an iterator.
void icalrecur_iterator_decrement_count (icalrecur_iterator *)
void icalrecur_iterator_free (icalrecur_iterator *)
 Free the iterator.
int icalrecur_expand_recurrence (char *rule, time_t start, int count, time_t *array)
 Fills array up with at most 'count' time_t values, each representing an occurrence time in seconds past the POSIX epoch.

Detailed Description

Routines for dealing with recurring time.

How to use:

1) Get a rule and a start time from a component

        icalproperty rrule;
        struct icalrecurrencetype recur;
        struct icaltimetype dtstart;

       rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY);
       recur = icalproperty_get_rrule(rrule);
       start = icalproperty_get_dtstart(dtstart);

Or, just make them up:

        recur = icalrecurrencetype_from_string("FREQ=YEARLY;BYDAY=SU,WE");
        dtstart = icaltime_from_string("19970101T123000")

2) Create an iterator

        icalrecur_iterator* ritr;
        ritr = icalrecur_iterator_new(recur,start);

3) Iterator over the occurrences

        struct icaltimetype next;
        while (next = icalrecur_iterator_next(ritr) 
               && !icaltime_is_null_time(next){
                Do something with next
        }

Note that that the time returned by icalrecur_iterator_next is in whatever timezone that dtstart is in.


How to use:

1) Get a rule and a start time from a component

        icalproperty rrule;
        struct icalrecurrencetype recur;
        struct icaltimetype dtstart;

       rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY);
       recur = icalproperty_get_rrule(rrule);
       start = icalproperty_get_dtstart(dtstart);

Or, just make them up:

        recur = icalrecurrencetype_from_string("FREQ=YEARLY;BYDAY=SU,WE");
        dtstart = icaltime_from_string("19970101T123000")

2) Create an iterator

        icalrecur_iterator* ritr;
        ritr = icalrecur_iterator_new(recur,start);

3) Iterator over the occurrences

        struct icaltimetype next;
        while (next = icalrecur_iterator_next(ritr) 
               && !icaltime_is_null_time(next){
                Do something with next
        }

Note that that the time returned by icalrecur_iterator_next is in whatever timezone that dtstart is in.

Definition in file icalrecur.h.


Class Documentation

struct icalrecurrencetype

Main struct for holding digested recurrence rules.

Definition at line 868 of file ical.h.

Collaboration diagram for icalrecurrencetype:
Class Members
short by_day
short by_hour
short by_minute
short by_month
short by_month_day
short by_second
short by_set_pos
short by_week_no
short by_year_day
int count
icalrecurrencetype_frequency freq
short interval
icalrecurrencetype_weekday week_start

Define Documentation

#define ICAL_BY_DAY_SIZE   364 /* 7 days * 52 weeks */

Definition at line 123 of file icalrecur.h.

Definition at line 122 of file icalrecur.h.

Definition at line 121 of file icalrecur.h.

Definition at line 127 of file icalrecur.h.

Definition at line 124 of file icalrecur.h.

Recurrence type routines.

Definition at line 120 of file icalrecur.h.

Definition at line 128 of file icalrecur.h.

Definition at line 126 of file icalrecur.h.

Definition at line 125 of file icalrecur.h.


Typedef Documentation

typedef struct icalrecur_iterator_impl

Recurrence iteration routines.

Definition at line 193 of file icalrecur.h.


Enumeration Type Documentation

anonymous enum
Enumerator:
ICAL_RECURRENCE_ARRAY_MAX 
ICAL_RECURRENCE_ARRAY_MAX_BYTE 

Definition at line 106 of file icalrecur.h.

Enumerator:
ICAL_SECONDLY_RECURRENCE 
ICAL_MINUTELY_RECURRENCE 
ICAL_HOURLY_RECURRENCE 
ICAL_DAILY_RECURRENCE 
ICAL_WEEKLY_RECURRENCE 
ICAL_MONTHLY_RECURRENCE 
ICAL_YEARLY_RECURRENCE 
ICAL_NO_RECURRENCE 
ICAL_SECONDLY_RECURRENCE 
ICAL_MINUTELY_RECURRENCE 
ICAL_HOURLY_RECURRENCE 
ICAL_DAILY_RECURRENCE 
ICAL_WEEKLY_RECURRENCE 
ICAL_MONTHLY_RECURRENCE 
ICAL_YEARLY_RECURRENCE 
ICAL_NO_RECURRENCE 

Definition at line 78 of file icalrecur.h.

Enumerator:
ICAL_NO_WEEKDAY 
ICAL_SUNDAY_WEEKDAY 
ICAL_MONDAY_WEEKDAY 
ICAL_TUESDAY_WEEKDAY 
ICAL_WEDNESDAY_WEEKDAY 
ICAL_THURSDAY_WEEKDAY 
ICAL_FRIDAY_WEEKDAY 
ICAL_SATURDAY_WEEKDAY 
ICAL_NO_WEEKDAY 
ICAL_SUNDAY_WEEKDAY 
ICAL_MONDAY_WEEKDAY 
ICAL_TUESDAY_WEEKDAY 
ICAL_WEDNESDAY_WEEKDAY 
ICAL_THURSDAY_WEEKDAY 
ICAL_FRIDAY_WEEKDAY 
ICAL_SATURDAY_WEEKDAY 

Definition at line 94 of file icalrecur.h.


Function Documentation

int icalrecur_expand_recurrence ( char *  rule,
time_t  start,
int  count,
time_t *  array 
)

Fills array up with at most 'count' time_t values, each representing an occurrence time in seconds past the POSIX epoch.

Fills array up with at most 'count' time_t values, each representing an occurrence time in seconds past the POSIX epoch.

Note that the times are returned in UTC, but the times are calculated in local time. YOu will have to convert the results back into local time before using them.

Definition at line 2435 of file icalrecur.c.

{
    struct icalrecurrencetype recur;
    icalrecur_iterator* ritr;
    time_t tt;
    struct icaltimetype icstart, next;
    int i = 0;

    memset(array, 0, count*sizeof(time_t));

    icstart = icaltime_from_timet_with_zone(start,0,0);

    recur = icalrecurrencetype_from_string(rule);

    for(ritr = icalrecur_iterator_new(recur,icstart),
       next = icalrecur_iterator_next(ritr);
       !icaltime_is_null_time(next) && i < count;
       next = icalrecur_iterator_next(ritr)){

       tt = icaltime_as_timet(next);
       
       if (tt >= start ){
           array[i++] = tt;
       }

    }

    icalrecur_iterator_free(ritr);

    return 1;
}

Here is the call graph for this function:

void icalrecur_iterator_decrement_count ( icalrecur_iterator *  )

Here is the caller graph for this function:

void icalrecur_iterator_free ( icalrecur_iterator *  )

Free the iterator.

Definition at line 1053 of file icalrecur.c.

{
    icalerror_check_arg_rv((i!=0),"impl");
    
    free(i);

}
icalrecur_iterator* icalrecur_iterator_new ( struct icalrecurrencetype  rule,
struct icaltimetype  dtstart 
)

Create a new recurrence rule iterator.

Definition at line 795 of file icalrecur.c.

{
    icalrecur_iterator* impl;
    icalrecurrencetype_frequency freq;

    if ( ( impl = (icalrecur_iterator*)
          malloc(sizeof(icalrecur_iterator))) == 0) {
       icalerror_set_errno(ICAL_NEWFAILED_ERROR);
       return 0;
    }

    memset(impl,0,sizeof(icalrecur_iterator));

    impl->rule = rule;
    impl->last = dtstart;
    impl->dtstart = dtstart;
    impl->days_index =0;
    impl->occurrence_no = 0;
    freq = impl->rule.freq;

    /* Set up convienience pointers to make the code simpler. Allows
       us to iterate through all of the BY* arrays in the rule. */

    impl->by_ptrs[BY_MONTH]=impl->rule.by_month;
    impl->by_ptrs[BY_WEEK_NO]=impl->rule.by_week_no;
    impl->by_ptrs[BY_YEAR_DAY]=impl->rule.by_year_day;
    impl->by_ptrs[BY_MONTH_DAY]=impl->rule.by_month_day;
    impl->by_ptrs[BY_DAY]=impl->rule.by_day;
    impl->by_ptrs[BY_HOUR]=impl->rule.by_hour;
    impl->by_ptrs[BY_MINUTE]=impl->rule.by_minute;
    impl->by_ptrs[BY_SECOND]=impl->rule.by_second;
    impl->by_ptrs[BY_SET_POS]=impl->rule.by_set_pos;

    memset(impl->orig_data,0,9*sizeof(short));

    /* Note which by rules had data in them when the iterator was
       created. We can't use the actuall by_x arrays, because the
       empty ones will be given default values later in this
       routine. The orig_data array will be used later in has_by_data */

    impl->orig_data[BY_MONTH]
       = (short)(impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_WEEK_NO]
      =(short)(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_YEAR_DAY]
    =(short)(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_MONTH_DAY]
    =(short)(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_DAY]
       = (short)(impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_HOUR]
       = (short)(impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_MINUTE]
     = (short)(impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_SECOND]
     = (short)(impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX);
    impl->orig_data[BY_SET_POS]
     = (short)(impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX);


    /* Check if the recurrence rule is legal */

    /* If the BYYEARDAY appears, no other date rule part may appear.   */

    if(icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH) ||
       icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_WEEK_NO) ||
       icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH_DAY) ||
       icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_DAY) ){

       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);

       return 0;
    }

    /* BYWEEKNO and BYMONTH rule parts may not both appear.*/

    if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH)){
       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);

       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
       return 0;
    }

    /* BYWEEKNO and BYMONTHDAY rule parts may not both appear.*/

    if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH_DAY)){
       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);

       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
       return 0;
    }


    /*For MONTHLY recurrences (FREQ=MONTHLY) neither BYYEARDAY nor
      BYWEEKNO may appear. */

    if(freq == ICAL_MONTHLY_RECURRENCE && 
       icalrecur_one_byrule(impl,BY_WEEK_NO)){
       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
       return 0;
    }


    /*For WEEKLY recurrences (FREQ=WEEKLY) neither BYMONTHDAY nor
      BYYEARDAY may appear. */

    if(freq == ICAL_WEEKLY_RECURRENCE && 
       icalrecur_one_byrule(impl,BY_MONTH_DAY )) {
       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
       return 0;
    }

    /* BYYEARDAY may only appear in YEARLY rules */
    if(freq != ICAL_YEARLY_RECURRENCE && 
       icalrecur_one_byrule(impl,BY_YEAR_DAY )) {
       icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
       return 0;
    }

    /* Rewrite some of the rules and set up defaults to make later
       processing easier. Primarily, t involves copying an element
       from the start time into the corresponding BY_* array when the
       BY_* array is empty */


    setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,
                 impl->dtstart.second,
                 &(impl->last.second));

    setup_defaults(impl,BY_MINUTE,ICAL_MINUTELY_RECURRENCE,
                 impl->dtstart.minute,
                 &(impl->last.minute));

    setup_defaults(impl,BY_HOUR,ICAL_HOURLY_RECURRENCE,
                 impl->dtstart.hour,
                 &(impl->last.hour));

    setup_defaults(impl,BY_MONTH_DAY,ICAL_DAILY_RECURRENCE,
                 impl->dtstart.day,
                 &(impl->last.day));

    setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,
                 impl->dtstart.month,
                 &(impl->last.month));


    if(impl->rule.freq == ICAL_WEEKLY_RECURRENCE ){

       if(impl->by_ptrs[BY_DAY][0] == ICAL_RECURRENCE_ARRAY_MAX){

          /* Weekly recurrences with no BY_DAY data should occur on the
             same day of the week as the start time . */
          impl->by_ptrs[BY_DAY][0] = (short)icaltime_day_of_week(impl->dtstart);

       } else {
         /* If there is BY_DAY data, then we need to move the initial
            time to the start of the BY_DAY data. That is if the
            start time is on a Wednesday, and the rule has
            BYDAY=MO,WE,FR, move the initial time back to
            monday. Otherwise, jumping to the next week ( jumping 7
            days ahead ) will skip over some occurrences in the
            second week. */

         /* This depends on impl->by_ptrs[BY_DAY] being correctly sorted by
          * day. This should probably be abstracted to make such assumption
          * more explicit. */
         short dow = (short)(impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last));
         if (dow > impl->rule.week_start-1) dow -= 7;
         impl->last.day += dow;
         impl->last = icaltime_normalize(impl->last);
      }
      

    }

    /* For YEARLY rule, begin by setting up the year days array . The
       YEARLY rules work by expanding one year at a time. */

    if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){
        struct icaltimetype next;

       for (;;) {
            expand_year_days(impl, impl->last.year);
           if (impl->days[0] != ICAL_RECURRENCE_ARRAY_MAX)
               break; /* break when no days are expanded */
           increment_year(impl,impl->rule.interval);
       }

        /* Copy the first day into last. */
       next = icaltime_from_day_of_year(impl->days[0], impl->last.year);
    
       impl->last.day =  next.day;
       impl->last.month =  next.month;
    } 


    /* If this is a monthly interval with by day data, then we need to
       set the last value to the appropriate day of the month */

    if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE)
       if (has_by_data(impl,BY_DAY)) {

       int dow = icalrecurrencetype_day_day_of_week(
           impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);  
       int pos =  icalrecurrencetype_day_position(
           impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);  
       
       int poscount = 0;
       int days_in_month = 
            icaltime_days_in_month(impl->last.month, impl->last.year); 
       
        if(pos >= 0){
            /* Count up from the first day pf the month to find the
               pos'th weekday of dow ( like the second monday. ) */

            for(impl->last.day = 1;
                impl->last.day <= days_in_month;
                impl->last.day++){
                
                if(icaltime_day_of_week(impl->last) == dow){
                    if(++poscount == pos || pos == 0){
                        break;
                    }
                }
            }
        } else {
            /* Count down from the last day pf the month to find the
               pos'th weekday of dow ( like the second to last monday. ) */
            pos = -pos;
            for(impl->last.day = days_in_month;
                impl->last.day != 0;
                impl->last.day--){
                
                if(icaltime_day_of_week(impl->last) == dow){
                    if(++poscount == pos ){
                        break;
                    }
                }
            }
        }


       if(impl->last.day > days_in_month || impl->last.day == 0){
           icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
           return 0;
       }
       
    } else if (has_by_data(impl,BY_MONTH_DAY)) {
       impl->last = icaltime_normalize(impl->last);
    }



    return impl;
}

Here is the call graph for this function:

struct icaltimetype icalrecur_iterator_next ( icalrecur_iterator *  ) [read]

Get the next occurrence from an iterator.

Definition at line 2233 of file icalrecur.c.

{
    int valid = 1;
    
    if( (impl->rule.count!=0 &&impl->occurrence_no >= impl->rule.count) ||
       (!icaltime_is_null_time(impl->rule.until) && 
       icaltime_compare(impl->last,impl->rule.until) > 0)) {
       return icaltime_null_time();
    }

    if(impl->occurrence_no == 0 
       &&  icaltime_compare(impl->last,impl->dtstart) >= 0){

       impl->occurrence_no++;
       return impl->last;
    }

    do {
        valid = 1;
       switch(impl->rule.freq){
           
           case ICAL_SECONDLY_RECURRENCE: {
              next_second(impl);
              break;
           }
           case ICAL_MINUTELY_RECURRENCE: {
              next_minute(impl);
              break;
           }
           case ICAL_HOURLY_RECURRENCE: {
              next_hour(impl);
              break;
           }
           case ICAL_DAILY_RECURRENCE: {
              next_day(impl);
              break;
           }
           case ICAL_WEEKLY_RECURRENCE: {
              next_week(impl);
              break;
           }
           case ICAL_MONTHLY_RECURRENCE: {
              valid = next_month(impl);
              break;
           }
           case ICAL_YEARLY_RECURRENCE:{
              next_year(impl);
              break;
           }
           default:{
              icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
                return icaltime_null_time();
           }
       }    
       
    } while(!check_contracting_rules(impl) 
           || icaltime_compare(impl->last,impl->dtstart) < 0
            || valid == 0);
    
    
/* Ignore null times and times that are after the until time */
    if( !icaltime_is_null_time(impl->rule.until) && 
       icaltime_compare(impl->last,impl->rule.until) > 0 ) {
       return icaltime_null_time();
    }

    impl->occurrence_no++;

    return impl->last;
}

Here is the call graph for this function:

Definition at line 2376 of file icalrecur.c.

{
    int i;

    for (i=0; wd_map[i].wd  != ICAL_NO_WEEKDAY; i++) {
       if ( strcmp(str,wd_map[i].str) == 0){
           return wd_map[i].wd;
       }
    }

    return ICAL_NO_WEEKDAY;
}

Here is the caller graph for this function:

Definition at line 516 of file icalrecur.c.

{
    char* str;
    char *str_p;
    size_t buf_sz = 200;
    char temp[20];
    int i,j;

    if(recur->freq == ICAL_NO_RECURRENCE){
       return 0;
    }

    str = (char*)icalmemory_tmp_buffer(buf_sz);
    str_p = str;

    icalmemory_append_string(&str,&str_p,&buf_sz,"FREQ=");
    icalmemory_append_string(&str,&str_p,&buf_sz,
                          icalrecur_freq_to_string(recur->freq));

    if(recur->until.year != 0){
       
       temp[0] = 0;
       if (recur->until.is_date)
           print_date_to_string(temp,&(recur->until));
       else
           print_datetime_to_string(temp,&(recur->until));
       
       icalmemory_append_string(&str,&str_p,&buf_sz,";UNTIL=");
       icalmemory_append_string(&str,&str_p,&buf_sz, temp);
    }

    if(recur->count != 0){
       snprintf(temp,sizeof(temp),"%d",recur->count);
       icalmemory_append_string(&str,&str_p,&buf_sz,";COUNT=");
       icalmemory_append_string(&str,&str_p,&buf_sz, temp);
    }

    if(recur->interval != 0){
       snprintf(temp,sizeof(temp),"%d",recur->interval);
       icalmemory_append_string(&str,&str_p,&buf_sz,";INTERVAL=");
       icalmemory_append_string(&str,&str_p,&buf_sz, temp);
    }
    
    for(j =0; recurmap[j].str != 0; j++){
       short* array = (short*)(recurmap[j].offset+ (size_t)recur);
       int limit = recurmap[j].limit;

       /* Skip unused arrays */
       if( array[0] != ICAL_RECURRENCE_ARRAY_MAX ) {

           icalmemory_append_string(&str,&str_p,&buf_sz,recurmap[j].str);
           
           for(i=0; 
              i< limit  && array[i] != ICAL_RECURRENCE_ARRAY_MAX;
              i++){
              if (j == 3) { /* BYDAY */
                  const char *daystr = icalrecur_weekday_to_string(
                     icalrecurrencetype_day_day_of_week(array[i]));
                  int pos;

                  pos = icalrecurrencetype_day_position(array[i]);  
                  
                  if (pos == 0)
                     icalmemory_append_string(&str,&str_p,&buf_sz,daystr);
                  else {
                     snprintf(temp,sizeof(temp),"%d%s",pos,daystr);
                     icalmemory_append_string(&str,&str_p,&buf_sz,temp);
                  }                  
                  
              } else {
                  snprintf(temp,sizeof(temp),"%d",array[i]);
                  icalmemory_append_string(&str,&str_p,&buf_sz, temp);
              }
              
              if( (i+1)<limit &&array[i+1] 
                  != ICAL_RECURRENCE_ARRAY_MAX){
                  icalmemory_append_char(&str,&str_p,&buf_sz,',');
              }
           }   
       }   
    }

    /* If week start is not monday (the default per RFC2445) append WKST */
    if (recur->week_start != ICAL_MONDAY_WEEKDAY && recur->week_start != ICAL_NO_WEEKDAY) {
       icalmemory_append_string(&str,&str_p,&buf_sz,";WKST=");
       icalmemory_append_string(&str,&str_p,&buf_sz,
                     icalrecur_weekday_to_string(recur->week_start));
    }

    return  str;
}

Here is the call graph for this function:

Definition at line 2308 of file icalrecur.c.

{
    memset(recur,ICAL_RECURRENCE_ARRAY_MAX_BYTE,
          sizeof(struct icalrecurrencetype));

    recur->week_start = ICAL_MONDAY_WEEKDAY;
    recur->freq = ICAL_NO_RECURRENCE;
    recur->interval = 1;
    memset(&(recur->until),0,sizeof(struct icaltimetype));
    recur->count = 0;
}

Here is the call graph for this function:

Array Encoding.

The 'day' element of the by_day array is encoded to allow representation of both the day of the week ( Monday, Tueday), but also the Nth day of the week ( First tuesday of the month, last thursday of the year) These routines decode the day values 1 == Monday, etc.

Array Encoding.

The day's position in the period ( Nth-ness) and the numerical value of the day are encoded together as: pos*7 + dow

A position of 0 means 'any' or 'every'

Definition at line 2331 of file icalrecur.c.

{
    return abs(day)%8;
}

0 == any of day of week.

1 == first, 2 = second, -2 == second to last, etc

Definition at line 2336 of file icalrecur.c.

{
    int wd, pos;

    wd = icalrecurrencetype_day_day_of_week(day);

    pos = (abs(day)-wd)/8 * ((day<0)?-1:1);


    return pos;
}

Here is the call graph for this function:

Recurrance rule parser.

Convert between strings and recurrencetype structures.

Definition at line 405 of file icalrecur.c.

{
    struct icalrecur_parser parser;

    memset(&parser,0,sizeof(parser));
    icalrecurrencetype_clear(&parser.rt);

    icalerror_check_arg_re(str!=0,"str",parser.rt);


    /* Set up the parser struct */
    parser.rule = str;
    parser.copy = icalmemory_strdup(parser.rule);
    parser.this_clause = parser.copy;

    if(parser.copy == 0){
       icalerror_set_errno(ICAL_NEWFAILED_ERROR);
       return parser.rt;
    }

    /* Loop through all of the clauses */
    for(icalrecur_first_clause(&parser); 
       parser.this_clause != 0;
       icalrecur_next_clause(&parser))
    {
       char *name, *value;
       icalrecur_clause_name_and_value(&parser,&name,&value);

       if(name == 0){
           icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
           icalrecurrencetype_clear(&parser.rt);
              free(parser.copy);
           return parser.rt;
       }

       if (strcmp(name,"FREQ") == 0){
           parser.rt.freq = icalrecur_string_to_freq(value);
       } else if (strcmp(name,"COUNT") == 0){
           int v = atoi(value);
           if (v >= 0) {
           parser.rt.count = v;
           }
       } else if (strcmp(name,"UNTIL") == 0){
           parser.rt.until = icaltime_from_string(value);
       } else if (strcmp(name,"INTERVAL") == 0){
           int v = atoi(value);
           if (v > 0 && v <= SHRT_MAX) {
           parser.rt.interval = (short) v;
           }
       } else if (strcmp(name,"WKST") == 0){
           parser.rt.week_start = icalrecur_string_to_weekday(value);
      sort_bydayrules(parser.rt.by_day,parser.rt.week_start);
       } else if (strcmp(name,"BYSECOND") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_second,
                              ICAL_BY_SECOND_SIZE,value);
       } else if (strcmp(name,"BYMINUTE") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_minute,
                              ICAL_BY_MINUTE_SIZE,value);
       } else if (strcmp(name,"BYHOUR") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_hour,
                              ICAL_BY_HOUR_SIZE,value);
       } else if (strcmp(name,"BYDAY") == 0){
           icalrecur_add_bydayrules(&parser,value);
       } else if (strcmp(name,"BYMONTHDAY") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_month_day,
                              ICAL_BY_MONTHDAY_SIZE,value);
       } else if (strcmp(name,"BYYEARDAY") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_year_day,
                              ICAL_BY_YEARDAY_SIZE,value);
       } else if (strcmp(name,"BYWEEKNO") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_week_no,
                              ICAL_BY_WEEKNO_SIZE,value);
       } else if (strcmp(name,"BYMONTH") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_month,
                              ICAL_BY_MONTH_SIZE,value);
       } else if (strcmp(name,"BYSETPOS") == 0){
           icalrecur_add_byrules(&parser,parser.rt.by_set_pos,
                              ICAL_BY_SETPOS_SIZE,value);
       } else {
           icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
           icalrecurrencetype_clear(&parser.rt);
              free(parser.copy);
           return parser.rt;
       }
       
    }

    free(parser.copy);

    return parser.rt;

}

Here is the call graph for this function: