Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Enumerations | Functions | Variables
icalrecur.c File Reference

Implementation of routines for dealing with recurring time. More...

#include <limits.h>
#include "icalrecur.h"
#include "icalerror.h"
#include "icalmemory.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include "pvl.h"

Go to the source code of this file.

Classes

struct  icalrecur_parser
struct  icalrecur_iterator_impl
struct  expand_split_map_struct
 The split map indicates, for a particular interval, wether a BY_* rule part expands the number of instances in the occcurrence set or contracts it. More...

Defines

#define MAX_TIME_T_YEAR   2037
 This is the last year we will go up to, since 32-bit time_t values only go up to the start of 2038.
#define TEMP_MAX   1024
#define BYDAYIDX   impl->by_indices[BY_DAY]
#define BYDAYPTR   impl->by_ptrs[BY_DAY]
#define BYMONIDX   impl->by_indices[BY_MONTH]
#define BYMONPTR   impl->by_ptrs[BY_MONTH]
#define BYMDIDX   impl->by_indices[BY_MONTH_DAY]
#define BYMDPTR   impl->by_ptrs[BY_MONTH_DAY]
#define BYWEEKIDX   impl->by_indices[BY_WEEK_NO]
#define BYWEEKPTR   impl->by_ptrs[BY_WEEK_NO]
#define HBD(x)   has_by_data(impl,x)

Enumerations

enum  byrule {
  NO_CONTRACTION = -1, BY_SECOND = 0, BY_MINUTE = 1, BY_HOUR = 2,
  BY_DAY = 3, BY_MONTH_DAY = 4, BY_YEAR_DAY = 5, BY_WEEK_NO = 6,
  BY_MONTH = 7, BY_SET_POS, NO_CONTRACTION = -1, BY_SECOND = 0,
  BY_MINUTE = 1, BY_HOUR = 2, BY_DAY = 3, BY_MONTH_DAY = 4,
  BY_YEAR_DAY = 5, BY_WEEK_NO = 6, BY_MONTH = 7, BY_SET_POS
}
enum  expand_table { UNKNOWN = 0, CONTRACT = 1, EXPAND = 2, ILLEGAL = 3 }

Functions

const char * icalrecur_freq_to_string (icalrecurrencetype_frequency kind)
icalrecurrencetype_frequency icalrecur_string_to_freq (const char *str)
const char * icalrecur_weekday_to_string (icalrecurrencetype_weekday kind)
icalrecurrencetype_weekday icalrecur_string_to_weekday (const char *str)
const char * icalrecur_first_clause (struct icalrecur_parser *parser)
const char * icalrecur_next_clause (struct icalrecur_parser *parser)
void icalrecur_clause_name_and_value (struct icalrecur_parser *parser, char **name, char **value)
void icalrecur_add_byrules (struct icalrecur_parser *parser, short *array, int size, char *vals)
static void sort_bydayrules (short *array, int week_start)
void icalrecur_add_bydayrules (struct icalrecur_parser *parser, const char *vals)
struct icalrecurrencetype icalrecurrencetype_from_string (const char *str)
 Convert between strings and recurrencetype structures.
void print_date_to_string (char *str, struct icaltimetype *data)
void print_datetime_to_string (char *str, struct icaltimetype *data)
char * icalrecurrencetype_as_string (struct icalrecurrencetype *recur)
static void increment_year (icalrecur_iterator *impl, int inc)
int icalrecur_iterator_sizeof_byarray (short *byarray)
static int icalrecur_two_byrule (icalrecur_iterator *impl, enum byrule one, enum byrule two)
 Check that the rule has only the two given interday byrule parts.
static int icalrecur_one_byrule (icalrecur_iterator *impl, enum byrule one)
 Check that the rule has only the one given interdat byrule parts.
static int count_byrules (icalrecur_iterator *impl)
static void setup_defaults (icalrecur_iterator *impl, enum byrule byrule, icalrecurrencetype_frequency req, int deftime, int *timepart)
static int has_by_data (icalrecur_iterator *impl, enum byrule byrule)
static int expand_year_days (icalrecur_iterator *impl, int year)
icalrecur_iterator * icalrecur_iterator_new (struct icalrecurrencetype rule, struct icaltimetype dtstart)
 Create a new recurrence rule iterator.
void icalrecur_iterator_free (icalrecur_iterator *i)
 Free the iterator.
static void increment_month (icalrecur_iterator *impl)
 Increment month is different that the other incement_* routines -- it figures out the interval for itself, and uses BYMONTH data if available.
static void increment_monthday (icalrecur_iterator *impl, int inc)
static void increment_hour (icalrecur_iterator *impl, int inc)
static void increment_minute (icalrecur_iterator *impl, int inc)
static void increment_second (icalrecur_iterator *impl, int inc)
static int next_second (icalrecur_iterator *impl)
static int next_minute (icalrecur_iterator *impl)
static int next_hour (icalrecur_iterator *impl)
static int next_day (icalrecur_iterator *impl)
static int next_yearday (icalrecur_iterator *impl)
static int nth_weekday (int dow, int pos, struct icaltimetype t)
static int is_day_in_byday (icalrecur_iterator *impl, struct icaltimetype tt)
static int next_month (icalrecur_iterator *impl)
static int next_weekday_by_week (icalrecur_iterator *impl)
static int next_week (icalrecur_iterator *impl)
static pvl_list expand_by_day (icalrecur_iterator *impl, int year)
 Expand the BYDAY rule part and return a pointer to a newly allocated list of days.
static int next_year (icalrecur_iterator *impl)
int icalrecur_check_rulepart (icalrecur_iterator *impl, int v, enum byrule byrule)
static int check_contract_restriction (icalrecur_iterator *impl, enum byrule byrule, int v)
static int check_contracting_rules (icalrecur_iterator *impl)
struct icaltimetype icalrecur_iterator_next (icalrecur_iterator *impl)
 Get the next occurrence from an iterator.
void icalrecurrencetype_clear (struct icalrecurrencetype *recur)
enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week (short day)
 The 'day' element of icalrecurrencetype_weekday 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.
int icalrecurrencetype_day_position (short day)
 0 == any of day of week.
int icalrecur_expand_recurrence (char *rule, time_t start, int count, time_t *array)
 Fill an array with the 'count' number of occurrences generated by the rrule.

Variables

struct {
char * str
size_t offset
int limit
recurmap []
static struct expand_split_map_struct []
struct {
icalrecurrencetype_weekday wd
const char * str
wd_map []
struct {
icalrecurrencetype_frequency kind
const char * str
freq_map []

Detailed Description

Implementation of routines for dealing with recurring time.

How this code works:

Processing starts when the caller generates a new recurrence iterator via icalrecur_iterator_new(). This routine copies the recurrence rule into the iterator and extracts things like start and end dates. Then, it checks if the rule is legal, using some logic from RFC2445 and some logic that probably should be in RFC2445.

Then, icalrecur_iterator_new() re-writes some of the BY* arrays. This involves ( via a call to setup_defaults() ) :

1) For BY rule parts with no data ( ie BYSECOND was not specified ) copy the corresponding time part from DTSTART into the BY array. ( So impl->by_ptrs[BY_SECOND] will then have one element if is originally had none ) This only happens if the BY* rule part data would expand the number of occurrences in the occurrence set. This lets the code ignore DTSTART later on and still use it to get the time parts that were not specified in any other way.

2) For the by rule part that are not the same interval as the frequency -- for HOURLY anything but BYHOUR, for instance -- copy the first data element from the rule part into the first occurrence. For example, for "INTERVAL=MONTHLY and BYHOUR=10,30", initialize the first time to be returned to have an hour of 10.

Finally, for INTERVAL=YEARLY, the routine expands the rule to get all of the days specified in the rule. The code will do this for each new year, and this is the first expansion. This is a special case for the yearly interval; no other frequency gets expanded this way. The yearly interval is the most complex, so some special processing is required.

After creating a new iterator, the caller will make successive calls to icalrecur_iterator_next() to get the next time specified by the rule. The main part of this routine is a switch on the frequency of the rule. Each different frequency is handled by a different routine.

For example, next_hour handles the case of INTERVAL=HOURLY, and it is called by other routines to get the next hour. First, the routine tries to get the next minute part of a time with a call to next_minute(). If next_minute() returns 1, it has reached the end of its data, usually the last element of the BYMINUTE array. Then, if there is data in the BYHOUR array, the routine changes the hour to the next one in the array. If INTERVAL=HOURLY, the routine advances the hour by the interval.

If the routine used the last hour in the BYHOUR array, and the INTERVAL=HOURLY, then the routine calls increment_monthday() to set the next month day. The increment_* routines may call higher routine to increment the month or year also.

The code for INTERVAL=DAILY is handled by next_day(). First, the routine tries to get the next hour part of a time with a call to next_hour. If next_hour() returns 1, it has reached the end of its data, usually the last element of the BYHOUR array. This means that next_day() should increment the time to the next day. If FREQUENCY==DAILY, the routine increments the day by the interval; otherwise, it increments the day by 1.

Next_day() differs from next_hour because it does not use the BYDAY array to select an appropriate day. Instead, it returns every day ( incrementing by 1 if the frequency is not DAILY with INTERVAL!=1) Any days that are not specified in an non-empty BYDAY array are filtered out later.

Generally, the flow of these routine is for a next_* call a next_* routine of a lower interval ( next_day calls next_hour) and then to possibly call an increment_* routine of an equal or higher interval. ( next_day calls increment_monthday() )

When the call to the original next_* routine returns, icalrecur_iterator_next() will check the returned data against other BYrule parts to determine if is should be excluded by calling check_contracting_rules. Generally, a contracting rule is any with a larger time span than the interval. For instance, if INTERVAL=DAILY, BYMONTH is a contracting rule part.

Check_contracting_rules() uses icalrecur_check_rulepart() to do its work. icalrecur_check_rulepart() uses expand_map[] to determine if a rule is contracting, and if it is, and if the BY rule part has some data, then the routine checks if the value of a component of the time is part of the byrule part. For instance, for "INTERVAL=DAILY; BYMONTH=6,10", icalrecur_check_rulepart() would check that the time value given to it has a month of either 6 or 10.

Finally, icalrecur_iterator_next() does a few other checks on the time value, and if it passes, it returns the time.

A note about the end_of_data flag. The flag indicates that the routine is at the end of its data -- the last BY rule if the routine is using by rules, or the last day of the week/month/year/etc if not.

This flag is usually set early in a next_* routine and returned in the end. The way it is used allows the next_* routine to set the last time back to the first element in a BYxx rule, and then signal to the higer level routine to increment the next higher level. For instance. WITH FREQ=MONTHLY;BYDAY=TU,FR, After next_weekday_by_month runs though both TU and FR, it sets the week day back to TU and sets end_of_data to 1x. This signals next_month to increment the month.


Definition in file icalrecur.c.


Class Documentation

struct icalrecur_parser

Definition at line 194 of file icalrecur.c.

Class Members
char * copy
char * next_clause
const char * rule
char * this_clause
struct icalrecur_iterator_impl

Definition at line 626 of file icalrecur.c.

Collaboration diagram for icalrecur_iterator_impl:
Class Members
short days
short days_index
int occurrence_no
struct expand_split_map_struct

The split map indicates, for a particular interval, wether a BY_* rule part expands the number of instances in the occcurrence set or contracts it.

1=> contract, 2=>expand, and 3 means the pairing is not allowed.

Definition at line 673 of file icalrecur.c.

Class Members
icalrecurrencetype_frequency frequency
short map

Define Documentation

#define BYDAYIDX   impl->by_indices[BY_DAY]

Definition at line 173 of file icalrecur.c.

#define BYDAYPTR   impl->by_ptrs[BY_DAY]

Definition at line 174 of file icalrecur.c.

#define BYMDIDX   impl->by_indices[BY_MONTH_DAY]

Definition at line 179 of file icalrecur.c.

#define BYMDPTR   impl->by_ptrs[BY_MONTH_DAY]

Definition at line 180 of file icalrecur.c.

#define BYMONIDX   impl->by_indices[BY_MONTH]

Definition at line 176 of file icalrecur.c.

#define BYMONPTR   impl->by_ptrs[BY_MONTH]

Definition at line 177 of file icalrecur.c.

#define BYWEEKIDX   impl->by_indices[BY_WEEK_NO]

Definition at line 182 of file icalrecur.c.

#define BYWEEKPTR   impl->by_ptrs[BY_WEEK_NO]

Definition at line 183 of file icalrecur.c.

#define HBD (   x)    has_by_data(impl,x)
#define MAX_TIME_T_YEAR   2037

This is the last year we will go up to, since 32-bit time_t values only go up to the start of 2038.

Definition at line 168 of file icalrecur.c.

#define TEMP_MAX   1024

Definition at line 170 of file icalrecur.c.


Enumeration Type Documentation

enum byrule
Enumerator:
NO_CONTRACTION 
BY_SECOND 
BY_MINUTE 
BY_HOUR 
BY_DAY 
BY_MONTH_DAY 
BY_YEAR_DAY 
BY_WEEK_NO 
BY_MONTH 
BY_SET_POS 
NO_CONTRACTION 
BY_SECOND 
BY_MINUTE 
BY_HOUR 
BY_DAY 
BY_MONTH_DAY 
BY_YEAR_DAY 
BY_WEEK_NO 
BY_MONTH 
BY_SET_POS 

Definition at line 611 of file icalrecur.c.

Enumerator:
UNKNOWN 
CONTRACT 
EXPAND 
ILLEGAL 

Definition at line 659 of file icalrecur.c.

                  {
    UNKNOWN  = 0,
    CONTRACT = 1,
    EXPAND =2,
    ILLEGAL=3
};

Function Documentation

static int check_contract_restriction ( icalrecur_iterator *  impl,
enum byrule  byrule,
int  v 
) [static]

Definition at line 2184 of file icalrecur.c.

{
    int pass = 0;
    int itr;
    icalrecurrencetype_frequency freq = impl->rule.freq;

    if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX &&
       expand_map[freq].map[byrule] == CONTRACT){
       for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){
           if(impl->by_ptrs[byrule][itr] == v){
              pass=1;
              break;
           }
       }

       return pass;
    } else {
       /* This is not a contracting byrule, or it has no data, so the
           test passes*/
       return 1;
    }
}

Here is the caller graph for this function:

static int check_contracting_rules ( icalrecur_iterator *  impl) [static]

Definition at line 2209 of file icalrecur.c.

{

    int day_of_week = icaltime_day_of_week(impl->last);
    int week_no = icaltime_week_number(impl->last);
    int year_day = icaltime_day_of_year(impl->last);

    if (
       check_contract_restriction(impl,BY_SECOND, impl->last.second) &&
       check_contract_restriction(impl,BY_MINUTE, impl->last.minute) &&
       check_contract_restriction(impl,BY_HOUR, impl->last.hour) &&
       check_contract_restriction(impl,BY_DAY, day_of_week) &&
       check_contract_restriction(impl,BY_WEEK_NO, week_no) &&
       check_contract_restriction(impl,BY_MONTH_DAY, impl->last.day) &&
       check_contract_restriction(impl,BY_MONTH, impl->last.month) &&
       check_contract_restriction(impl,BY_YEAR_DAY, year_day) )
    {

       return 1;
    } else {
       return 0;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int count_byrules ( icalrecur_iterator *  impl) [static]

Definition at line 747 of file icalrecur.c.

{
    int count = 0;
    enum byrule itr;

    for(itr = BY_DAY; itr <= BY_SET_POS; itr++){
       if(impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX){
           count++;
       }
    }

    return count;
}
static pvl_list expand_by_day ( icalrecur_iterator *  impl,
int  year 
) [static]

Expand the BYDAY rule part and return a pointer to a newly allocated list of days.

Definition at line 1755 of file icalrecur.c.

{
    /* Try to calculate each of the occurrences. */
    int i;
    pvl_list days_list = pvl_newlist();

    int start_dow, end_dow, end_year_day;
    struct icaltimetype tmp = impl->last;
    
    tmp.year= year;
    tmp.month = 1;
    tmp.day = 1;
    tmp.is_date = 1;
    
    /* Find the day that 1st Jan falls on, 1 (Sun) to 7 (Sat). */
    start_dow = icaltime_day_of_week(tmp);
    
    /* Get the last day of the year*/
    tmp.year= year;
    tmp.month = 12;
    tmp.day = 31;
    tmp.is_date = 1;
    
    end_dow =  icaltime_day_of_week(tmp);
    end_year_day = icaltime_day_of_year(tmp);
    
    for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
        /* This is 1 (Sun) to 7 (Sat). */
        int dow = 
            icalrecurrencetype_day_day_of_week(BYDAYPTR[i]);  
        int pos =  icalrecurrencetype_day_position(BYDAYPTR[i]);
        
        if(pos == 0){
            /* The day was specified without a position -- it is just
               a bare day of the week ( BYDAY=SU) so add all of the
               days of the year with this day-of-week*/
            int doy, tmp_start_doy;
                
           tmp_start_doy = ((dow + 7 - start_dow) % 7) + 1;

            for (doy = tmp_start_doy; doy <= end_year_day; doy += 7)
                    pvl_push(days_list,(void*)(int)doy);
            
        } else if ( pos > 0) {
            int first;
            /* First occurrence of dow in year */
            if( dow >= start_dow) {
                first = dow - start_dow + 1;
            } else {
                first = dow - start_dow + 8;
            }

            /* Then just multiple the position times 7 to get the pos'th day in the year */
            pvl_push(days_list,(void*)(first+  (pos-1) * 7));
            
        } else { /* pos < 0 */ 
            int last;
            pos = -pos;

            /* last occurrence of dow in year */
            if( dow <= end_dow) {
                last = end_year_day - end_dow + dow;
            } else {
                last = end_year_day - end_dow + dow - 7;
            }

            pvl_push(days_list,(void*)(last - (pos-1) * 7));
        }
    }
    return days_list;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int expand_year_days ( icalrecur_iterator *  impl,
int  year 
) [static]

Definition at line 1832 of file icalrecur.c.

{
    int j,k;
    int days_index=0;
    struct icaltimetype t;
    int flags;

    t = icaltime_null_date();

#define HBD(x) has_by_data(impl,x)

    memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days));
    
    /* The flags and the following switch statement select which code
       to use to expand the yers days, based on which BY-rules are
       present. */

    flags = (HBD(BY_DAY) ? 1<<BY_DAY : 0) + 
        (HBD(BY_WEEK_NO) ? 1<<BY_WEEK_NO : 0) + 
        (HBD(BY_MONTH_DAY) ? 1<<BY_MONTH_DAY : 0) + 
        (HBD(BY_MONTH) ? 1<<BY_MONTH : 0) + 
        (HBD(BY_YEAR_DAY) ? 1<<BY_YEAR_DAY : 0);

    
    switch(flags) {
        
    case 0: {
        /* FREQ=YEARLY; */
        t = impl->dtstart;
        t.year = impl->last.year;
        
        impl->days[days_index++] = (short)icaltime_day_of_year(t);
  
        break;
    }
    case 1<<BY_MONTH: {
        /* FREQ=YEARLY; BYMONTH=3,11*/
       
        for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
           int month = impl->by_ptrs[BY_MONTH][j];          
            int doy;

           t = impl->dtstart;
           t.year = year;
           t.month = month;
           t.is_date = 1;

           doy = icaltime_day_of_year(t);
           
            impl->days[days_index++] = (short)doy;

        }
        break;
    }

    case 1<<BY_MONTH_DAY:  {
        /* FREQ=YEARLY; BYMONTHDAY=1,15*/
        for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++)
            {
                int month_day = impl->by_ptrs[BY_MONTH_DAY][k];
                int doy;

                t = impl->dtstart;
              t.day = month_day;
              t.year = year;
              t.is_date = 1;

              doy = icaltime_day_of_year(t);

              impl->days[days_index++] = (short)doy;

            }
        break;
    }

    case (1<<BY_MONTH_DAY) + (1<<BY_MONTH): {
        /* FREQ=YEARLY; BYMONTHDAY=1,15; BYMONTH=10 */

        for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
            for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++)
           {
                int month = impl->by_ptrs[BY_MONTH][j];
                int month_day = impl->by_ptrs[BY_MONTH_DAY][k];
                int doy;

              t.day = month_day;
              t.month = month;
              t.year = year;
              t.is_date = 1;

              doy = icaltime_day_of_year(t);

              impl->days[days_index++] = (short)doy;

            }
        }

        break;
    }

    case 1<<BY_WEEK_NO: {
        /* FREQ=YEARLY; BYWEEKNO=20,50 */

       int dow;

       t.day = impl->dtstart.day;
       t.month = impl->dtstart.month;
       t.year = year;
       t.is_date = 1;

        dow = icaltime_day_of_week(t);
       /* HACK Not finished */ 

        icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
       
        break;
    }

    case (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
        /*FREQ=YEARLY; WEEKNO=20,50; BYMONTH= 6,11 */
        icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
        break;
    }

    case 1<<BY_DAY: {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/
        pvl_elem i;
        pvl_list days = expand_by_day(impl,year);


        for(i=pvl_head(days);i!=0;i=pvl_next(i)){
            short day = (short)(intptr_t)pvl_data(i);
            impl->days[days_index++] = day;
        }

        pvl_free(days);

        break;
    }

    case (1<<BY_DAY)+(1<<BY_MONTH): {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTH = 12*/


        for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
           int month = impl->by_ptrs[BY_MONTH][j];
           int days_in_month = icaltime_days_in_month(month,year);
           int first_dow, last_dow, doy_offset;
            
           t.year = year;
           t.month = month;
           t.day = 1;
           t.is_date = 1;
              
           first_dow = icaltime_day_of_week(t);

           /* This holds the day offset used to calculate the day of the year
              from the month day. Just add the month day to this. */
           doy_offset = icaltime_day_of_year(t) - 1;

           t.day = days_in_month;
           last_dow = icaltime_day_of_week(t);

           for(k=0;impl->by_ptrs[BY_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++){
               short day_coded = impl->by_ptrs[BY_DAY][k];
              enum icalrecurrencetype_weekday dow =
                icalrecurrencetype_day_day_of_week(day_coded);
              int pos = icalrecurrencetype_day_position(day_coded);  
              int first_matching_day, last_matching_day, day, month_day;

              /* Calculate the first day in the month with the given weekday,
                 and the last day. */
              first_matching_day = ((dow + 7 - first_dow) % 7) + 1;
              last_matching_day = days_in_month - ((last_dow + 7 - dow) % 7);

              if (pos == 0) {
                  /* Add all of instances of the weekday within the month. */
                for (day = first_matching_day; day <= days_in_month; day += 7)
                    impl->days[days_index++] = (short)(doy_offset + day);

              } else if (pos > 0) {
                  /* Add the nth instance of the weekday within the month. */
                  month_day = first_matching_day + (pos - 1) * 7;

                  if (month_day <= days_in_month)
                      impl->days[days_index++] = (short)(doy_offset + month_day);

              } else {
                  /* Add the -nth instance of the weekday within the month.*/
                  month_day = last_matching_day + (pos + 1) * 7;

                  if (month_day > 0)
                      impl->days[days_index++] = (short)(doy_offset + month_day);
              }
           }
        }
        break;
    }

    case (1<<BY_DAY) + (1<<BY_MONTH_DAY) : {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=1,15*/

        pvl_elem itr;
        pvl_list days = expand_by_day(impl,year);

        for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
            short day = (short)(intptr_t)pvl_data(itr);
            struct icaltimetype tt; 
            
            tt = icaltime_from_day_of_year(day,year);
            
            for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
                    int mday = BYMDPTR[j];
                    
                    if(tt.day == mday){
                        impl->days[days_index++] = day;
                    }
            }
            
        }

        pvl_free(days);
       
        break;
    }

    case (1<<BY_DAY) + (1<<BY_MONTH_DAY) + (1<<BY_MONTH): {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=10; MYMONTH=6,11*/

        pvl_elem itr;
        pvl_list days = expand_by_day(impl,year);

        for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
            short day = (short)(intptr_t)pvl_data(itr);
            struct icaltimetype tt; 
            int i;
            
            tt = icaltime_from_day_of_year(day,year);
            
            for(i = 0; BYMONPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
                for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
                    int mday = BYMDPTR[j];
                    int month = BYMONPTR[i];
                    
                    if(tt.month == month  && tt.day == mday){
                        impl->days[days_index++] = day;
                    }
                }
            }

        }

        pvl_free(days);

       break;

    }

    case (1<<BY_DAY) + (1<<BY_WEEK_NO) : {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR;  WEEKNO=20,50*/
       
        pvl_elem itr;
        pvl_list days = expand_by_day(impl,year);

        for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
            short day = (short)(intptr_t)pvl_data(itr);
            struct icaltimetype tt; 
            int i;
            
            tt = icaltime_from_day_of_year(day,year);
            
            for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
                    int weekno = BYWEEKPTR[i];
                    int this_weekno = icaltime_week_number(tt);
                    if(weekno== this_weekno){
                        impl->days[days_index++] = day;
                    }
            }
                    
        }

        pvl_free(days);
        break;
    }

    case (1<<BY_DAY) + (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
        /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR;  WEEKNO=20,50; BYMONTHDAY=1,15*/
        icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
        break;
    }

    case 1<<BY_YEAR_DAY: {
       for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
           impl->days[days_index++] = impl->by_ptrs[BY_YEAR_DAY][j];
        }
        break;
    }

    default: {
        icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
        break;
    }

    }

    return 0;
}                                  

Here is the call graph for this function:

Here is the caller graph for this function:

static int has_by_data ( icalrecur_iterator *  impl,
enum byrule  byrule 
) [static]

Definition at line 786 of file icalrecur.c.

                                                                    {

    return (impl->orig_data[byrule] == 1);
}

Here is the caller graph for this function:

void icalrecur_add_bydayrules ( struct icalrecur_parser parser,
const char *  vals 
)

Definition at line 343 of file icalrecur.c.

{

    char *t, *n;
    int i=0;
    int sign = 1;
    int weekno = 0;
    icalrecurrencetype_weekday wd;
    short *array = parser->rt.by_day;
    char* end;
    char* vals_copy;

    vals_copy = icalmemory_strdup(vals);

    end = (char*)vals_copy+strlen(vals_copy);
    n = vals_copy;

    while(n != 0){
       

       t = n;

       n = strchr(t,',');

       if(n != 0){
           *n = 0;
           n++;
       }
       
       /* Get optional sign. */
       if( *t == '-'){
           sign = -1;
           t++;
       } else if (*t == '+'){
           sign = 1;
           t++;
       } else {
           sign = 1;
       }

       /* Get Optional weekno */
       weekno = strtol(t,&t,10);

       /* Outlook/Exchange generate "BYDAY=MO, FR" and "BYDAY=2 TH".
        * Cope with that.
        */
       if (*t == ' ')
           t++;

       wd = icalrecur_string_to_weekday(t);

       array[i++] = (short)(sign* (wd + 8*weekno));
       array[i] =  ICAL_RECURRENCE_ARRAY_MAX;

    }

    free(vals_copy);

    sort_bydayrules(parser->rt.by_day,parser->rt.week_start);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void icalrecur_add_byrules ( struct icalrecur_parser parser,
short *  array,
int  size,
char *  vals 
)

Definition at line 268 of file icalrecur.c.

{
    char *t, *n;
    int i=0;
    int sign = 1;
    int v;

    n = vals;

    while(n != 0){

       if(i == size){
           return;
       }
       
       t = n;

       n = strchr(t,',');

       if(n != 0){
           *n = 0;
           n++;
       }
       
       /* Get optional sign. HACK. sign is not allowed for all BYxxx
           rule parts */
       if( *t == '-'){
           sign = -1;
           t++;
       } else if (*t == '+'){
           sign = 1;
           t++;
       } else {
           sign = 1;
       }

       v = atoi(t) * sign ;


       array[i++] = (short)v;
       array[i] =  ICAL_RECURRENCE_ARRAY_MAX;

    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

int icalrecur_check_rulepart ( icalrecur_iterator *  impl,
int  v,
enum byrule  byrule 
)

Definition at line 2168 of file icalrecur.c.

{
    int itr;

    if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX){
       for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){
           if(impl->by_ptrs[byrule][itr] == v){
              return 1;
           }
       }
    } 

    return 0;
}
void icalrecur_clause_name_and_value ( struct icalrecur_parser parser,
char **  name,
char **  value 
)

Definition at line 248 of file icalrecur.c.

{
    char *idx;

    *name = parser->this_clause;

    idx = strchr(parser->this_clause,'=');

    if (idx == 0){
       *name = 0;
       *value = 0;
       return;
    }
    
    *idx = 0;
    idx++;
    *value = idx;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Fill an array with the 'count' number of occurrences generated by the rrule.

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:

Here is the caller graph for this function:

const char* icalrecur_first_clause ( struct icalrecur_parser parser)

Definition at line 203 of file icalrecur.c.

{
    char *idx;
    parser->this_clause = parser->copy;
    
    idx = strchr(parser->this_clause,';');

    if (idx == 0){
       parser->next_clause = 0;
       return 0;
    }

    *idx = 0;
    idx++;
    parser->next_clause = idx;

    return parser->this_clause;

}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2405 of file icalrecur.c.

{
    int i;

    for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) {
       if ( freq_map[i].kind == kind ) {
           return freq_map[i].str;
       }
    }
    return 0;
}

Here is the caller graph for this function:

void icalrecur_iterator_free ( icalrecur_iterator *  i)

Free the iterator.

Definition at line 1053 of file icalrecur.c.

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

}

Here is the caller graph for this function:

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:

Here is the caller graph for this function:

struct icaltimetype icalrecur_iterator_next ( icalrecur_iterator *  impl) [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:

Here is the caller graph for this function:

int icalrecur_iterator_sizeof_byarray ( short *  byarray)

Definition at line 647 of file icalrecur.c.

{
    int array_itr;

    for(array_itr = 0; 
       byarray[array_itr] != ICAL_RECURRENCE_ARRAY_MAX;
       array_itr++){
    }

    return array_itr;
}
const char* icalrecur_next_clause ( struct icalrecur_parser parser)

Definition at line 223 of file icalrecur.c.

{
    char* idx;

    parser->this_clause = parser->next_clause;

    if(parser->this_clause == 0){
       return 0;
    }

    idx = strchr(parser->this_clause,';');

    if (idx == 0){
       parser->next_clause = 0;
    } else {

       *idx = 0;
       idx++;
       parser->next_clause = idx;
    }
       
    return parser->this_clause;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int icalrecur_one_byrule ( icalrecur_iterator *  impl,
enum byrule  one 
) [static]

Check that the rule has only the one given interdat byrule parts.

Definition at line 731 of file icalrecur.c.

{
    int passes = 1;
    enum byrule itr;

    for(itr = BY_DAY; itr != BY_SET_POS; itr++){
       
       if ((itr==one && impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX) ||
           (itr!=one && impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX)) {
           passes = 0;
       }
    }

    return passes;
} 

Here is the caller graph for this function:

Definition at line 2417 of file icalrecur.c.

{
    int i;

    for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) {
       if ( strcmp(str,freq_map[i].str) == 0){
           return freq_map[i].kind;
       }
    }
    return ICAL_NO_RECURRENCE;
}

Here is the caller 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:

static int icalrecur_two_byrule ( icalrecur_iterator *  impl,
enum byrule  one,
enum byrule  two 
) [static]

Check that the rule has only the two given interday byrule parts.

Definition at line 700 of file icalrecur.c.

{
    short test_array[9];
    enum byrule itr;
    int passes = 0;

    memset(test_array,0,sizeof(test_array));

    test_array[one] = 1;
    test_array[two] = 1;

    for(itr = BY_DAY; itr != BY_SET_POS; itr++){

       if( (test_array[itr] == 0  &&
            impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX
           ) ||
           (test_array[itr] == 1  &&
            impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX
              ) 
           ) {
           /* test failed */
           passes = 0;
       }
    }

    return passes;

} 

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2363 of file icalrecur.c.

{
    int i;

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

    return 0;
}

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:

Here is the caller 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:

Here is the caller graph for this function:

The 'day' element of icalrecurrencetype_weekday 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.

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

Here is the caller graph for this function:

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:

Here is the caller graph for this function:

Convert between strings and recurrencetype structures.

Recurrance rule parser.

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:

Here is the caller graph for this function:

static void increment_hour ( icalrecur_iterator *  impl,
int  inc 
) [static]

Definition at line 1135 of file icalrecur.c.

{
    int days;

    impl->last.hour+=inc;

    days = impl->last.hour / 24;
    impl->last.hour = impl->last.hour % 24;

    if (impl->days != 0){
       increment_monthday(impl,days);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void increment_minute ( icalrecur_iterator *  impl,
int  inc 
) [static]

Definition at line 1149 of file icalrecur.c.

{
    int hours;

    impl->last.minute+=inc;

    hours = impl->last.minute / 60;
     impl->last.minute =  impl->last.minute % 60;

     if (hours != 0){
       increment_hour(impl,hours);
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

static void increment_month ( icalrecur_iterator *  impl) [static]

Increment month is different that the other incement_* routines -- it figures out the interval for itself, and uses BYMONTH data if available.

Definition at line 1069 of file icalrecur.c.

{
    int years;

     if(has_by_data(impl,BY_MONTH) ){
         /* Ignore the frequency and use the byrule data */
         
         impl->by_indices[BY_MONTH]++;
         
         if (impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]]
             ==ICAL_RECURRENCE_ARRAY_MAX){
             impl->by_indices[BY_MONTH] = 0;

             increment_year(impl,1);
             
         }
         
         impl->last.month = 
             impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]];

     } else {
         
         int inc;

         if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE){
            inc =  impl->rule.interval;
         } else {
             inc = 1;
         }

         impl->last.month+=inc;
         
         /* Months are offset by one */
         impl->last.month--;
         
         years = impl->last.month / 12;
         
         impl->last.month = impl->last.month % 12;
         
         impl->last.month++;
         
         if (years != 0){
             increment_year(impl,years);
         }
     }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void increment_monthday ( icalrecur_iterator *  impl,
int  inc 
) [static]

Definition at line 1116 of file icalrecur.c.

{
    int i;

    for(i=0; i<inc; i++){
       
       int days_in_month = 
           icaltime_days_in_month(impl->last.month, impl->last.year);

       impl->last.day++;
       
       if (impl->last.day > days_in_month){
           impl->last.day = impl->last.day-days_in_month;
           increment_month(impl);
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void increment_second ( icalrecur_iterator *  impl,
int  inc 
) [static]

Definition at line 1164 of file icalrecur.c.

{
    int minutes;

    impl->last.second+=inc;
    
    minutes = impl->last.second / 60;
    impl->last.second = impl->last.second % 60;
    
    if (minutes != 0)
    {
       increment_minute(impl, minutes);
    }                 
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void increment_year ( icalrecur_iterator *  impl,
int  inc 
) [static]

Definition at line 1061 of file icalrecur.c.

{
    impl->last.year+=inc;
}

Here is the caller graph for this function:

static int is_day_in_byday ( icalrecur_iterator *  impl,
struct icaltimetype  tt 
) [static]

Definition at line 1462 of file icalrecur.c.

                                                                           {

    int idx; 

    for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
        int dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);  
        int pos =  icalrecurrencetype_day_position(BYDAYPTR[idx]);  
        int this_dow = icaltime_day_of_week(tt);
        
        if( (pos == 0 &&  dow == this_dow ) || /* Just a dow, like "TU" or "FR" */
            (nth_weekday(dow,pos,tt) == tt.day)){ /*pos+wod: "3FR" or -1TU" */
            return 1;
        }
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_day ( icalrecur_iterator *  impl) [static]

Definition at line 1349 of file icalrecur.c.

{

  int has_by_day = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
  int this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE);

  assert(has_by_day || this_frequency);

  if (next_hour(impl) == 0){
      return 0;
  }

  /* Always increment through the interval, since this routine is not
     called by any other next_* routine, and the days that are
     excluded will be taken care of by restriction filtering */

  if(this_frequency){
      increment_monthday(impl,impl->rule.interval);
  } else {
      increment_monthday(impl,1);
  }


  return 0;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_hour ( icalrecur_iterator *  impl) [static]

Definition at line 1303 of file icalrecur.c.

{

  int has_by_hour = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX);
  int this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE);

  int end_of_data = 0;

  assert(has_by_hour || this_frequency);

  if (next_minute(impl) == 0){
      return 0;
  }

  if(  has_by_hour ){
      /* Ignore the frequency and use the byrule data */

      impl->by_indices[BY_HOUR]++;
      
      if (impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]]
         ==ICAL_RECURRENCE_ARRAY_MAX){
         impl->by_indices[BY_HOUR] = 0;
         
         end_of_data = 1;
      }

      impl->last.hour = 
         impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]];

  } else if( !has_by_hour &&  this_frequency ){
      /* Compute the next value from the last time and the frequency interval*/
      increment_hour(impl,impl->rule.interval);

  }

  /* If we have gone through all of the hours on the BY list, then we
     need to move to the next day */

  if(has_by_hour && end_of_data && this_frequency ){
      increment_monthday(impl,1);
  }

  return end_of_data;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_minute ( icalrecur_iterator *  impl) [static]

Definition at line 1257 of file icalrecur.c.

{

  int has_by_minute = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX);
  int this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE);

  int end_of_data = 0;

  assert(has_by_minute || this_frequency);


  if (next_second(impl) == 0){
      return 0;
  }

  if(  has_by_minute ){
      /* Ignore the frequency and use the byrule data */

      impl->by_indices[BY_MINUTE]++;
      
      if (impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]]
         ==ICAL_RECURRENCE_ARRAY_MAX){

         impl->by_indices[BY_MINUTE] = 0;
         
         end_of_data = 1;
      }

      impl->last.minute = 
         impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]];

  } else if( !has_by_minute &&  this_frequency ){
      /* Compute the next value from the last time and the frequency interval*/
      increment_minute(impl,impl->rule.interval);
  } 

/* If we have gone through all of the minutes on the BY list, then we
     need to move to the next hour */

  if(has_by_minute && end_of_data && this_frequency ){
      increment_hour(impl,1);
  }

  return end_of_data;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_month ( icalrecur_iterator *  impl) [static]

Definition at line 1480 of file icalrecur.c.

{
    int data_valid = 1;
    
    int this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE);
    
    assert( has_by_data(impl,BY_MONTH) || this_frequency);
  
    /* Iterate through the occurrences within a day. If we don't get to
       the end of the intra-day data, don't bother going to the next
       month */
    
    if (next_hour(impl) == 0){
        return data_valid; /* Signal that the data is valid */
    }
    
    /* Now iterate through the occurrences within a month -- by days,
       weeks or weekdays.  */

   /* 
    * Case 1: 
    * Rules Like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13 
    */
    
    if(has_by_data(impl,BY_DAY) && has_by_data(impl,BY_MONTH_DAY)){
      int day, idx,j;
      int days_in_month = icaltime_days_in_month(impl->last.month,
                                                   impl->last.year);
      /* Iterate through the remaining days in the month and check if
         each day is listed in the BY_DAY array and in the BY_MONTHDAY
         array. This seems very inneficient, but I think it is the
         simplest way to account for both BYDAY=1FR (First friday in
         month) and BYDAY=FR ( every friday in month ) */

      for(day = impl->last.day+1; day <= days_in_month; day++){
          for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
              for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
                  int dow = 
                      icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);  
                  int pos =  icalrecurrencetype_day_position(BYDAYPTR[idx]);  
                  int mday = BYMDPTR[j];
                  int this_dow;
                  
                  impl->last.day = day;
                  this_dow = icaltime_day_of_week(impl->last);
                  
                  if( (pos == 0 &&  dow == this_dow && mday == day) || 
                      (nth_weekday(dow,pos,impl->last) == day && mday==day)){
                      goto MDEND;
                  }
              }
          }
      }

  MDEND:

      if ( day > days_in_month){
          impl->last.day = 1;
          increment_month(impl);
          impl->last.day--; /* Go back one day, so searches next month start at day 1 */
          data_valid = 0; /* signal that impl->last is invalid */
      }

    
   /* 
    * Case 2: 
    * Rules Like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR 
    */
  
  }  else if(has_by_data(impl,BY_DAY)){
      /* For this case, the weekdays are relative to the
         month. BYDAY=FR -> First Friday in month, etc. */

      /* This code iterates through the remaining days in the month
         and checks if each day is listed in the BY_DAY array. This
         seems very inneficient, but I think it is the simplest way to
         account for both BYDAY=1FR (First friday in month) and
         BYDAY=FR ( every friday in month ) */

      int day;
      int days_in_month = icaltime_days_in_month(impl->last.month,
                                                   impl->last.year);
      assert( BYDAYPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);

      for(day = impl->last.day+1; day <= days_in_month; day++){
          impl->last.day = day;
          if(is_day_in_byday(impl,impl->last)){
              data_valid = 1;
              break;
          }
      }

      if ( day > days_in_month){
          impl->last.day = 1;
          increment_month(impl);

          /* Did moving to the next month put us on a valid date? if
             so, note that the new data is valid, if, not, mark it
             invalid */

          if(is_day_in_byday(impl,impl->last)){
              data_valid = 1;
          } else {
              data_valid = 0; /* signal that impl->last is invalid */
          }
      }

     /* 
       * Case 3
       * Rules Like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3  
       */

  } else if (has_by_data(impl,BY_MONTH_DAY)) {
      int day, days_in_month;

      assert( BYMDPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);

      BYMDIDX++;
          
      /* Are we at the end of the BYDAY array? */
      if (BYMDPTR[BYMDIDX] ==ICAL_RECURRENCE_ARRAY_MAX){
          
          BYMDIDX = 0; /* Reset to 0 */      
          increment_month(impl);          
      }
      
      days_in_month = icaltime_days_in_month(impl->last.month,
                                                   impl->last.year);

      day = BYMDPTR[BYMDIDX];
      
      if (day < 0) {
          day = icaltime_days_in_month(impl->last.month, impl->last.year) + day + 1;
      }

      if ( day > days_in_month){
          impl->last.day = 1;

          /* Did moving to the next month put us on a valid date? if
             so, note that the new data is valid, if, not, mark it
             invalid */

          if(is_day_in_byday(impl,impl->last)){
              data_valid = 1;
          } else {
              data_valid = 0; /* signal that impl->last is invalid */
          }
      }

      impl->last.day = day;

  } else {
      int days_in_month;

      increment_month(impl);

      days_in_month = icaltime_days_in_month(impl->last.month,
                                                   impl->last.year);
      if (impl->last.day > days_in_month){
          data_valid = 0; /* signal that impl->last is invalid */
      }
  }

  return data_valid;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_second ( icalrecur_iterator *  impl) [static]

Definition at line 1213 of file icalrecur.c.

{

  int has_by_second = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX);
  int this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE);

  int end_of_data = 0;

  assert(has_by_second || this_frequency);

  if(  has_by_second ){
      /* Ignore the frequency and use the byrule data */

      impl->by_indices[BY_SECOND]++;

      if (impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]]
         ==ICAL_RECURRENCE_ARRAY_MAX){
         impl->by_indices[BY_SECOND] = 0;

         end_of_data = 1;
      }


      impl->last.second = 
         impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]];
      
      
  } else if( !has_by_second &&  this_frequency ){
      /* Compute the next value from the last time and the frequency interval*/
      increment_second(impl, impl->rule.interval);

  }

  /* If we have gone through all of the seconds on the BY list, then we
     need to move to the next minute */

  if(has_by_second && end_of_data && this_frequency ){
      increment_minute(impl,1);
  }

  return end_of_data;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_week ( icalrecur_iterator *  impl) [static]

Definition at line 1704 of file icalrecur.c.

{
  int end_of_data = 0;

  /* Increment to the next week day, if there is data at a level less than a week */
  if (next_weekday_by_week(impl) == 0){
      return 0; /* Have not reached end of week yet */
  }

  /* If we get here, we have incremented through the entire week, and
     can increment to the next week */

  if( has_by_data(impl,BY_WEEK_NO)){
      /*FREQ=WEEKLY;BYWEEK=20*/
    /* Use the Week Number byrule data */
      int week_no;
      struct icaltimetype t;
      
      impl->by_indices[BY_WEEK_NO]++;
      
      if (impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]]
         ==ICAL_RECURRENCE_ARRAY_MAX){
         impl->by_indices[BY_WEEK_NO] = 0;
         
         end_of_data = 1;
      }
      
      t = impl->last;
      t.month=1; /* HACK, should be setting to the date of the first week of year*/
      t.day=1;
      
      week_no = impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]];
      
      impl->last.day += week_no*7;

      impl->last = icaltime_normalize(impl->last);
      
  } else {
      /* Jump to the next week */
      increment_monthday(impl,7*impl->rule.interval);
  }

  if( has_by_data(impl,BY_WEEK_NO) && end_of_data){
      increment_year(impl,1);
  }

  return end_of_data;
  
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_weekday_by_week ( icalrecur_iterator *  impl) [static]

Definition at line 1647 of file icalrecur.c.

{

  int end_of_data = 0;
  int start_of_week, dow;
  struct icaltimetype next;

  if (next_hour(impl) == 0){
      return 0;
  }

  if(!has_by_data(impl,BY_DAY)){
      return 1;
  }

       /* this call to 'sort_bydayrules' assures that the occurrences for
               weekly recurrences will be generated in a strict linear order. */
     sort_bydayrules(BYDAYPTR,impl->rule.week_start);

  /* If we get here, we need to step to tne next day */

  for (;;) {
      BYDAYIDX++; /* Look at next elem in BYDAY array */
      
      /* Are we at the end of the BYDAY array? */
      if (BYDAYPTR[BYDAYIDX]==ICAL_RECURRENCE_ARRAY_MAX){
         BYDAYIDX = 0; /* Reset to 0 */      
         end_of_data = 1; /* Signal that we're at the end */
      }
      
      /* Add the day of week offset to to the start of this week, and use
        that to get the next day */
      /* ignore position of dow ("4FR"), only use dow ("FR")*/
      dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[BYDAYIDX]); 
      dow -= impl->rule.week_start; /* Set Sunday to be 0 */
      if (dow < 0) dow += 7;

      start_of_week = icaltime_start_doy_week(impl->last, impl->rule.week_start);
      
      if(dow+start_of_week <1){
          /* The selected date is in the previous year. */
          if(!end_of_data){    
              continue;
          }
      } 
 
      next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year);
      
      impl->last.day =  next.day;
      impl->last.month =  next.month;
      impl->last.year =  next.year;

      return end_of_data;
  }

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_year ( icalrecur_iterator *  impl) [static]

Definition at line 2141 of file icalrecur.c.

{
    struct icaltimetype next;

    if (next_hour(impl) == 0){
       return 0;
    }

    if (impl->days[++impl->days_index] == ICAL_RECURRENCE_ARRAY_MAX){
       impl->days_index = 0;

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

    next = icaltime_from_day_of_year(impl->days[impl->days_index], impl->last.year);
    
    impl->last.day =  next.day;
    impl->last.month =  next.month;
  
    return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int next_yearday ( icalrecur_iterator *  impl) [static]

Definition at line 1377 of file icalrecur.c.

{

  int has_by_yearday = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);

  int end_of_data = 0;

  assert(has_by_yearday );

  if (next_hour(impl) == 0){
      return 0;
  }

  impl->by_indices[BY_YEAR_DAY]++;
  
  if (impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]]
      ==ICAL_RECURRENCE_ARRAY_MAX){
      impl->by_indices[BY_YEAR_DAY] = 0;
      
      end_of_data = 1;
  }
  
  impl->last.day = 
      impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]];
  
  if(has_by_yearday && end_of_data){
      increment_year(impl,1);
  }

  return end_of_data;

}

Here is the call graph for this function:

static int nth_weekday ( int  dow,
int  pos,
struct icaltimetype  t 
) [static]

Definition at line 1414 of file icalrecur.c.

                                                               {

    int days_in_month = icaltime_days_in_month(t.month, t.year);
    int end_dow, start_dow;
    int wd;

    if(pos >= 0){
        t.day = 1;
        start_dow = icaltime_day_of_week(t);        
        
        if (pos != 0) {
            pos--;
        }
         
        /* find month day of first occurrence of dow -- such as the
           month day of the first monday */

        wd = dow-start_dow+1;

        if (wd <= 0){
            wd = wd + 7;
        }

        wd = wd + pos * 7;
        
    } else {
        t.day = days_in_month;
        end_dow = icaltime_day_of_week(t);

        pos++;

        /* find month day of last occurrence of dow -- such as the
           month day of the last monday */

        wd = (end_dow - dow);

        if (wd < 0){
            wd = wd+ 7;
        }

        wd = days_in_month - wd;

        wd = wd + pos * 7;
    }
        
    return wd;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void print_date_to_string ( char *  str,
struct icaltimetype data 
)

Here is the caller graph for this function:

void print_datetime_to_string ( char *  str,
struct icaltimetype data 
)

Here is the caller graph for this function:

static void setup_defaults ( icalrecur_iterator *  impl,
enum byrule  byrule,
icalrecurrencetype_frequency  req,
int  deftime,
int timepart 
) [static]

Definition at line 762 of file icalrecur.c.

{

    icalrecurrencetype_frequency freq;
    freq = impl->rule.freq;

    /* Re-write the BY rule arrays with data from the DTSTART time so
       we don't have to explicitly deal with DTSTART */

    if(impl->by_ptrs[byrule][0] == ICAL_RECURRENCE_ARRAY_MAX &&
       expand_map[freq].map[byrule] != CONTRACT){
       impl->by_ptrs[byrule][0] = (short)deftime;
    }

    /* Initialize the first occurrence */
    if( freq != req && expand_map[freq].map[byrule] != CONTRACT){
       *timepart = impl->by_ptrs[byrule][0];
    }


}

Here is the caller graph for this function:

static void sort_bydayrules ( short *  array,
int  week_start 
) [static]

Definition at line 321 of file icalrecur.c.

{
       int one, two, i, j;

       for (i=0;
                      i<ICAL_BY_DAY_SIZE && array[i] != ICAL_RECURRENCE_ARRAY_MAX;
                      i++) {
              for (j=0; j<i; j++) {
                     one = icalrecurrencetype_day_day_of_week(array[j]) - week_start;
                     if (one < 0) one += 7;
                     two = icalrecurrencetype_day_day_of_week(array[i]) - week_start;
                     if (two < 0) two += 7;

                     if (one > two) {
                            short tmp = array[j];
                            array[j] = array[i];
                            array[i] = tmp;
                     }
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct expand_split_map_struct[] [static]
Initial value:
{
    {ICAL_SECONDLY_RECURRENCE,{1,1,1,1,1,1,1,1}},
    {ICAL_MINUTELY_RECURRENCE,{2,1,1,1,1,1,1,1}},
    {ICAL_HOURLY_RECURRENCE,  {2,2,1,1,1,1,1,1}},
    {ICAL_DAILY_RECURRENCE,   {2,2,2,1,1,1,1,1}},
    {ICAL_WEEKLY_RECURRENCE,  {2,2,2,2,3,3,1,1}},
    {ICAL_MONTHLY_RECURRENCE, {2,2,2,2,2,3,3,1}},
    {ICAL_YEARLY_RECURRENCE,  {2,2,2,2,2,2,2,2}},
    {ICAL_NO_RECURRENCE,      {0,0,0,0,0,0,0,0}}

}

Definition at line 683 of file icalrecur.c.

struct { ... } freq_map[] [static]
struct { ... } recurmap[] [static]
struct { ... } wd_map[] [static]