summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalrecur.c
authorzautrix <zautrix>2004-06-29 11:59:46 (UTC)
committer zautrix <zautrix>2004-06-29 11:59:46 (UTC)
commitda43dbdc6c82453228f34766fc74585615cba938 (patch) (side-by-side diff)
tree16576932cea08bf117b2d0320b0d5f66ee8ad093 /libical/src/libical/icalrecur.c
parent627489ea2669d3997676bc3cee0f5d0d0c16c4d4 (diff)
downloadkdepimpi-da43dbdc6c82453228f34766fc74585615cba938.zip
kdepimpi-da43dbdc6c82453228f34766fc74585615cba938.tar.gz
kdepimpi-da43dbdc6c82453228f34766fc74585615cba938.tar.bz2
New lib ical.Some minor changes as well.
Diffstat (limited to 'libical/src/libical/icalrecur.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libical/icalrecur.c789
1 files changed, 433 insertions, 356 deletions
diff --git a/libical/src/libical/icalrecur.c b/libical/src/libical/icalrecur.c
index 203ce70..d5a59c6 100644
--- a/libical/src/libical/icalrecur.c
+++ b/libical/src/libical/icalrecur.c
@@ -16,13 +16,17 @@
2.1, available at: http://www.fsf.org/copyleft/lesser.html
Or:
The Mozilla Public License Version 1.0. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
+*/
+/**
+ @file icalrecur.c
+ @brief 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
@@ -127,30 +131,33 @@
======================================================================*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#include "icalrecur.h"
-#ifdef ICAL_NO_LIBICAL
-#define icalerror_set_errno(x)
-#define icalerror_check_arg_rv(x,y)
-#else
#include "icalerror.h"
#include "icalmemory.h"
-#endif
#include <stdlib.h> /* for malloc */
#include <errno.h> /* for errno */
#include <string.h> /* for strdup and strchr*/
#include <assert.h>
#include <stddef.h> /* For offsetof() macro */
#include "pvl.h"
+/** 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 MAX_TIME_T_YEAR 2037
+
#define TEMP_MAX 1024
#define BYDAYIDX impl->by_indices[BY_DAY]
#define BYDAYPTR impl->by_ptrs[BY_DAY]
@@ -167,13 +174,12 @@ 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);
-
/*********************** Rule parsing routines ************************/
struct icalrecur_parser {
const char* rule;
char* copy;
char* this_clause;
@@ -250,13 +256,13 @@ void icalrecur_clause_name_and_value(struct icalrecur_parser *parser,
void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
int size, char* vals)
{
char *t, *n;
int i=0;
int sign = 1;
- short v;
+ int v;
n = vals;
while(n != 0){
if(i == size){
@@ -277,18 +283,20 @@ void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
if( *t == '-'){
sign = -1;
t++;
} else if (*t == '+'){
sign = 1;
t++;
+ } else {
+ sign = 1;
}
v = atoi(t) * sign ;
- array[i++] = v;
+ array[i++] = (short)v;
array[i] = ICAL_RECURRENCE_ARRAY_MAX;
}
}
@@ -329,27 +337,24 @@ void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals)
sign = 1;
t++;
} else {
sign = 1;
}
- weekno = 0;
/* Get Optional weekno */
- if( sscanf(t,"%d",&weekno) != 0){
- if (n != 0){
- int weeknolen = (n-t)-3; /* 3 -> one for \0, 2 for day name */
- /* could use abs(log10(weekno))+1, but that needs libm */
- t += weeknolen;
- } else {
- t = end -2;
- }
- }
+ 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++] = sign* ((int)wd + 8*weekno);
+ array[i++] = (short)(sign* (wd + 8*weekno));
array[i] = ICAL_RECURRENCE_ARRAY_MAX;
}
free(vals_copy);
@@ -384,23 +389,24 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
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){
parser.rt.count = atoi(value);
} else if (strcmp(name,"UNTIL") == 0){
parser.rt.until = icaltime_from_string(value);
} else if (strcmp(name,"INTERVAL") == 0){
- parser.rt.interval = atoi(value);
+ parser.rt.interval = (short)atoi(value);
} else if (strcmp(name,"WKST") == 0){
parser.rt.week_start = icalrecur_string_to_weekday(value);
} 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){
@@ -426,26 +432,25 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
} 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;
}
-#ifndef ICAL_NO_LIBICAL
-
-struct { char* str;size_t offset; short limit; } recurmap[] =
+static struct { char* str;size_t offset; int limit; } recurmap[] =
{
{";BYSECOND=",offsetof(struct icalrecurrencetype,by_second),60},
{";BYMINUTE=",offsetof(struct icalrecurrencetype,by_minute),60},
{";BYHOUR=",offsetof(struct icalrecurrencetype,by_hour),24},
{";BYDAY=",offsetof(struct icalrecurrencetype,by_day),7},
{";BYMONTHDAY=",offsetof(struct icalrecurrencetype,by_month_day),31},
@@ -454,12 +459,13 @@ struct { char* str;size_t offset; short limit; } recurmap[] =
{";BYMONTH=",offsetof(struct icalrecurrencetype,by_month),12},
{";BYSETPOS=",offsetof(struct icalrecurrencetype,by_set_pos),366},
{0,0,0},
};
/* A private routine in icalvalue.c */
+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)
{
char* str;
char *str_p;
@@ -478,13 +484,16 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
icalmemory_append_string(&str,&str_p,&buf_sz,
icalrecur_freq_to_string(recur->freq));
if(recur->until.year != 0){
temp[0] = 0;
- print_datetime_to_string(temp,&(recur->until));
+ 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){
@@ -498,26 +507,26 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
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);
- short limit = recurmap[j].limit;
+ 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 */
- short dow = icalrecurrencetype_day_day_of_week(array[i]);
- const char *daystr = icalrecur_weekday_to_string(dow);
- short pos;
+ 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 {
@@ -537,14 +546,12 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
}
}
}
return str;
}
-#endif
-
/************************* occurrence iteration routiens ******************/
enum byrule {
NO_CONTRACTION = -1,
@@ -570,19 +577,21 @@ struct icalrecur_iterator_impl {
short days[366];
short days_index;
enum byrule byrule;
short by_indices[9];
- short orig_data[9]; /* 1 if there was data in the byrule */
+ short orig_data[9]; /**< 1 if there was data in the byrule */
- short *by_ptrs[9]; /* Pointers into the by_* array elements of the rule */
+ short *by_ptrs[9]; /**< Pointers into the by_* array elements of the rule */
};
+static void increment_year(icalrecur_iterator* impl, int inc);
+
int icalrecur_iterator_sizeof_byarray(short* byarray)
{
int array_itr;
for(array_itr = 0;
byarray[array_itr] != ICAL_RECURRENCE_ARRAY_MAX;
@@ -596,27 +605,30 @@ enum expand_table {
UNKNOWN = 0,
CONTRACT = 1,
EXPAND =2,
ILLEGAL=3
};
-/* 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. */
+/**
+ * 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.
+ */
+
struct expand_split_map_struct
{
icalrecurrencetype_frequency frequency;
/* Elements of the 'map' array correspond to the BYxxx rules:
Second,Minute,Hour,Day,Month Day,Year Day,Week No,Month*/
short map[8];
};
-struct expand_split_map_struct expand_map[] =
+static struct expand_split_map_struct expand_map[] =
{
{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}},
@@ -625,21 +637,22 @@ struct expand_split_map_struct expand_map[] =
{ICAL_NO_RECURRENCE, {0,0,0,0,0,0,0,0}}
};
-/* Check that the rule has only the two given interday byrule parts. */
-int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl,
+/** Check that the rule has only the two given interday byrule parts. */
+static
+int icalrecur_two_byrule(icalrecur_iterator* impl,
enum byrule one,enum byrule two)
{
short test_array[9];
enum byrule itr;
int passes = 0;
- memset(test_array,0,9);
+ memset(test_array,0,sizeof(test_array));
test_array[one] = 1;
test_array[two] = 1;
for(itr = BY_DAY; itr != BY_SET_POS; itr++){
@@ -656,14 +669,14 @@ int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl,
}
return passes;
}
-/* Check that the rule has only the one given interdat byrule parts. */
-int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one)
+/** Check that the rule has only the one given interdat byrule parts. */
+static int icalrecur_one_byrule(icalrecur_iterator* impl,enum byrule one)
{
int passes = 1;
enum byrule itr;
for(itr = BY_DAY; itr != BY_SET_POS; itr++){
@@ -673,13 +686,13 @@ int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one)
}
}
return passes;
}
-int count_byrules(struct icalrecur_iterator_impl* impl)
+static int count_byrules(icalrecur_iterator* impl)
{
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){
@@ -688,60 +701,58 @@ int count_byrules(struct icalrecur_iterator_impl* impl)
}
return count;
}
-void setup_defaults(struct icalrecur_iterator_impl* impl,
+static void setup_defaults(icalrecur_iterator* impl,
enum byrule byrule, icalrecurrencetype_frequency req,
- short deftime, int *timepart)
+ int deftime, int *timepart)
{
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] = deftime;
+ impl->by_ptrs[byrule][0] = (short)deftime;
}
/* Initialize the first occurence */
if( freq != req && expand_map[freq].map[byrule] != CONTRACT){
*timepart = impl->by_ptrs[byrule][0];
}
}
-int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){
+static int has_by_data(icalrecur_iterator* impl, enum byrule byrule){
return (impl->orig_data[byrule] == 1);
}
-int expand_year_days(struct icalrecur_iterator_impl* impl,short year);
+static int expand_year_days(icalrecur_iterator* impl, int year);
icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
struct icaltimetype dtstart)
{
- struct icalrecur_iterator_impl* impl;
+ icalrecur_iterator* impl;
icalrecurrencetype_frequency freq;
- short days_in_month;
-
- if ( ( impl = (struct icalrecur_iterator_impl *)
- malloc(sizeof(struct icalrecur_iterator_impl))) == 0) {
+ if ( ( impl = (icalrecur_iterator*)
+ malloc(sizeof(icalrecur_iterator))) == 0) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
return 0;
}
- memset(impl,0,sizeof(struct icalrecur_iterator_impl));
+ memset(impl,0,sizeof(icalrecur_iterator));
impl->rule = rule;
impl->last = dtstart;
impl->dtstart = dtstart;
impl->days_index =0;
impl->occurrence_no = 0;
@@ -757,37 +768,37 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
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);
+ 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]
- = (impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (short)(impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_WEEK_NO]
- =(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ =(short)(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_YEAR_DAY]
- =(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ =(short)(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_MONTH_DAY]
- =(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ =(short)(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_DAY]
- = (impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (short)(impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_HOUR]
- = (impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (short)(impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_MINUTE]
- = (impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (short)(impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_SECOND]
- = (impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (short)(impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX);
impl->orig_data[BY_SET_POS]
- = (impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ = (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. */
@@ -849,35 +860,40 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
/* 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 coresponding BY_* array when the
BY_* array is empty */
- setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,impl->dtstart.second,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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] = icaltime_day_of_week(impl->dtstart);
+ 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
@@ -885,45 +901,59 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
days ahead ) will skip over some occurrences in the
second week. */
/* This is probably a HACK. There should be some more
general way to solve this problem */
- short dow = impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last);
+ short dow = (short)(impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last));
if(dow < 0) {
/* initial time is after first day of BY_DAY data */
impl->last.day += dow;
impl->last = icaltime_normalize(impl->last);
}
}
}
- /* For YEARLY rule, begin by setting up the year days array */
+ /* 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){
- expand_year_days(impl,impl->last.year);
+ 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 &&
has_by_data(impl,BY_DAY)) {
- short dow = icalrecurrencetype_day_day_of_week(
+ int dow = icalrecurrencetype_day_day_of_week(
impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
- short pos = icalrecurrencetype_day_position(
+ int pos = icalrecurrencetype_day_position(
impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
- short poscount = 0;
- days_in_month =
+ 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. ) */
@@ -966,32 +996,27 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
return impl;
}
void icalrecur_iterator_free(icalrecur_iterator* i)
{
+ icalerror_check_arg_rv((i!=0),"impl");
- struct icalrecur_iterator_impl* impl =
- (struct icalrecur_iterator_impl*)i;
-
- icalerror_check_arg_rv((impl!=0),"impl");
-
- free(impl);
+ free(i);
}
-
-void increment_year(struct icalrecur_iterator_impl* impl, int inc)
+static void increment_year(icalrecur_iterator* impl, int inc)
{
impl->last.year+=inc;
}
-/* Increment month is different that the other incement_* routines --
+/** Increment month is different that the other incement_* routines --
it figures out the interval for itself, and uses BYMONTH data if
available. */
-void increment_month(struct icalrecur_iterator_impl* impl)
+static void increment_month(icalrecur_iterator* impl)
{
int years;
if(has_by_data(impl,BY_MONTH) ){
/* Ignore the frequency and use the byrule data */
@@ -1032,63 +1057,63 @@ void increment_month(struct icalrecur_iterator_impl* impl)
if (years != 0){
increment_year(impl,years);
}
}
}
-void increment_monthday(struct icalrecur_iterator_impl* impl, int inc)
+static void increment_monthday(icalrecur_iterator* impl, int inc)
{
int i;
for(i=0; i<inc; i++){
- short days_in_month =
- icaltime_days_in_month(impl->last.month,impl->last.year);
+ 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);
}
}
}
-void increment_hour(struct icalrecur_iterator_impl* impl, int inc)
+static void increment_hour(icalrecur_iterator* impl, int inc)
{
- short days;
+ 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);
}
}
-void increment_minute(struct icalrecur_iterator_impl* impl, int inc)
+static void increment_minute(icalrecur_iterator* impl, int inc)
{
- short hours;
+ 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);
}
}
-void increment_second(struct icalrecur_iterator_impl* impl, int inc)
+static void increment_second(icalrecur_iterator* impl, int inc)
{
- short minutes;
+ int minutes;
impl->last.second+=inc;
minutes = impl->last.second / 60;
impl->last.second = impl->last.second % 60;
@@ -1099,13 +1124,13 @@ void increment_second(struct icalrecur_iterator_impl* impl, int inc)
}
#if 0
#include "ical.h"
void test_increment()
{
- struct icalrecur_iterator_impl impl;
+ icalrecur_iterator impl;
impl.last = icaltime_from_string("20000101T000000Z");
printf("Orig: %s\n",icaltime_as_ctime(impl.last));
increment_second(&impl,5);
@@ -1129,23 +1154,23 @@ void test_increment()
printf("+ 600 days : %s\n",icaltime_as_ctime(impl.last));
}
#endif
-short next_second(struct icalrecur_iterator_impl* impl)
+static int next_second(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE);
+ int has_by_second = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ int this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE);
- short end_of_data = 0;
+ int end_of_data = 0;
- assert(has_by_data || this_frequency);
+ assert(has_by_second || this_frequency);
- if( has_by_data ){
+ 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){
@@ -1156,45 +1181,45 @@ short next_second(struct icalrecur_iterator_impl* impl)
impl->last.second =
impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]];
- } else if( !has_by_data && this_frequency ){
+ } 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_data && end_of_data && this_frequency ){
+ if(has_by_second && end_of_data && this_frequency ){
increment_minute(impl,1);
}
return end_of_data;
}
-int next_minute(struct icalrecur_iterator_impl* impl)
+static int next_minute(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE);
+ int has_by_minute = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ int this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE);
- short end_of_data = 0;
+ int end_of_data = 0;
- assert(has_by_data || this_frequency);
+ assert(has_by_minute || this_frequency);
if (next_second(impl) == 0){
return 0;
}
- if( has_by_data ){
+ 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){
@@ -1204,42 +1229,42 @@ int next_minute(struct icalrecur_iterator_impl* impl)
end_of_data = 1;
}
impl->last.minute =
impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]];
- } else if( !has_by_data && this_frequency ){
+ } 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_data && end_of_data && this_frequency ){
+ if(has_by_minute && end_of_data && this_frequency ){
increment_hour(impl,1);
}
return end_of_data;
}
-int next_hour(struct icalrecur_iterator_impl* impl)
+static int next_hour(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE);
+ int has_by_hour = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ int this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE);
- short end_of_data = 0;
+ int end_of_data = 0;
- assert(has_by_data || this_frequency);
+ assert(has_by_hour || this_frequency);
if (next_minute(impl) == 0){
return 0;
}
- if( has_by_data ){
+ 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){
@@ -1248,36 +1273,36 @@ int next_hour(struct icalrecur_iterator_impl* impl)
end_of_data = 1;
}
impl->last.hour =
impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]];
- } else if( !has_by_data && this_frequency ){
+ } 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_data && end_of_data && this_frequency ){
+ if(has_by_hour && end_of_data && this_frequency ){
increment_monthday(impl,1);
}
return end_of_data;
}
-int next_day(struct icalrecur_iterator_impl* impl)
+static int next_day(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE);
+ 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_data || this_frequency);
+ assert(has_by_day || this_frequency);
if (next_hour(impl) == 0){
return 0;
}
/* Always increment through the interval, since this routine is not
@@ -1293,20 +1318,20 @@ int next_day(struct icalrecur_iterator_impl* impl)
return 0;
}
-int next_yearday(struct icalrecur_iterator_impl* impl)
+static int next_yearday(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ int has_by_yearday = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short end_of_data = 0;
+ int end_of_data = 0;
- assert(has_by_data );
+ assert(has_by_yearday );
if (next_hour(impl) == 0){
return 0;
}
impl->by_indices[BY_YEAR_DAY]++;
@@ -1318,76 +1343,29 @@ int next_yearday(struct icalrecur_iterator_impl* impl)
end_of_data = 1;
}
impl->last.day =
impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]];
- if(has_by_data && end_of_data){
+ if(has_by_yearday && end_of_data){
increment_year(impl,1);
}
return end_of_data;
}
-/* This routine is only called by next_week. It is certain that BY_DAY
-has data */
-
-int next_weekday_by_week(struct icalrecur_iterator_impl* impl)
-{
-
- short end_of_data = 0;
- short start_of_week, dow;
- struct icaltimetype next;
-
- if (next_hour(impl) == 0){
- return 0;
- }
-
- assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
-
- while(1) {
-
- impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */
-
- /* Are we at the end of the BYDAY array? */
- if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]
- ==ICAL_RECURRENCE_ARRAY_MAX){
-
- impl->by_indices[BY_DAY] = 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 */
- dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]];
- start_of_week = icaltime_start_doy_of_week(impl->last);
-
- dow--; /*Sun is 1, not 0 */
-
- if(dow+start_of_week <1 && !end_of_data){
- /* The selected date is in the previous year. */
- 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;
- }
-}
+/* Returns the day of the month for the current month of t that is the
+ pos'th instance of the day-of-week dow */
-int nth_weekday(short dow, short pos, struct icaltimetype t){
+static int nth_weekday(int dow, int pos, struct icaltimetype t){
- short days_in_month = icaltime_days_in_month(t.month,t.year);
- short end_dow, start_dow;
- short wd;
+ 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) {
@@ -1425,52 +1403,72 @@ int nth_weekday(short dow, short pos, struct icaltimetype t){
wd = wd + pos * 7;
}
return wd;
}
+static int is_day_in_byday(icalrecur_iterator* impl,struct icaltimetype tt){
+
+ int idx;
-int next_month(struct icalrecur_iterator_impl* impl)
+ 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;
+}
+
+static int next_month(icalrecur_iterator* impl)
{
int data_valid = 1;
- short this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE);
+ 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)){
- /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13 */
- short day, idx,j;
- short days_in_month = icaltime_days_in_month(impl->last.month,
+ 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++){
- short dow =
+ int dow =
icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
- short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
- short mday = BYMDPTR[j];
- short this_dow;
+ 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)){
@@ -1485,57 +1483,63 @@ int next_month(struct icalrecur_iterator_impl* impl)
if ( day > days_in_month){
impl->last.day = 1;
increment_month(impl);
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)){
- /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR */
/* For this case, the weekdays are relative to the
month. BYDAY=FR -> First Friday in month, etc. */
- short day, idx;
- short days_in_month = icaltime_days_in_month(impl->last.month,
- impl->last.year);
+ /* 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);
- /* Iterate through the remaining days in the month and check 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 ) */
-
for(day = impl->last.day+1; day <= days_in_month; day++){
- for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
- short dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
- short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
- short this_dow;
-
- impl->last.day = day;
- this_dow = icaltime_day_of_week(impl->last);
-
- if( (pos == 0 && dow == this_dow ) ||
- (nth_weekday(dow,pos,impl->last) == day)){
- goto DEND;
- }
+ impl->last.day = day;
+ if(is_day_in_byday(impl,impl->last)){
+ data_valid = 1;
+ break;
}
}
- DEND:
-
if ( day > days_in_month){
impl->last.day = 1;
increment_month(impl);
- data_valid = 0; /* signal that impl->last is invalid */
+
+ /* 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)) {
- /* Cases like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3 */
- short day;
+ int day;
assert( BYMDPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);
BYMDIDX++;
/* Are we at the end of the BYDAY array? */
@@ -1545,43 +1549,96 @@ int next_month(struct icalrecur_iterator_impl* impl)
increment_month(impl);
}
day = BYMDPTR[BYMDIDX];
if (day < 0) {
- day = icaltime_days_in_month(impl->last.month,impl->last.year)+
- day + 1;
+ day = icaltime_days_in_month(impl->last.month, impl->last.year) + day + 1;
}
impl->last.day = day;
} else {
increment_month(impl);
}
- return data_valid; /* Signal that the data is valid */
+ return data_valid;
}
+static int next_weekday_by_week(icalrecur_iterator* impl)
+{
+
+ 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;
+ }
+
+ /* If we get here, we need to step to tne next day */
+
+ for (;;) {
+ struct icaltimetype tt = icaltime_null_time();
+ 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]);
+ tt.year = impl->last.year;
+ tt.day = impl->last.day;
+ tt.month = impl->last.month;
+
+ start_of_week = icaltime_start_doy_of_week(tt);
+
+ dow--; /* Set Sunday to be 0 */
+
+ 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;
+ }
+
+}
-int next_week(struct icalrecur_iterator_impl* impl)
+static int next_week(icalrecur_iterator* impl)
{
- short has_by_data = (impl->by_ptrs[BY_WEEK_NO][0]!=ICAL_RECURRENCE_ARRAY_MAX);
- short this_frequency = (impl->rule.freq == ICAL_WEEKLY_RECURRENCE);
- short end_of_data = 0;
+ int end_of_data = 0;
- /* Increment to the next week day */
+ /* 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){
+ 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]++;
@@ -1599,82 +1656,79 @@ int next_week(struct icalrecur_iterator_impl* impl)
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 if( !has_by_data && this_frequency ){
- /* If there is no BY_WEEK_NO data, just jump forward 7 days. */
+ } else {
+ /* Jump to the next week */
increment_monthday(impl,7*impl->rule.interval);
}
-
- if(has_by_data && end_of_data && this_frequency ){
+ if( has_by_data(impl,BY_WEEK_NO) && end_of_data){
increment_year(impl,1);
}
return end_of_data;
}
-/* Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */
-pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
+/** Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */
+static pvl_list expand_by_day(icalrecur_iterator* impl, int year)
{
/* Try to calculate each of the occurrences. */
int i;
pvl_list days_list = pvl_newlist();
- short start_dow, end_dow, end_year_day, start_doy;
+ 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);
- start_doy = icaltime_start_doy_of_week(tmp);
/* Get the last day of the year*/
- tmp.year++;
- tmp = icaltime_normalize(tmp);
- tmp.day--;
- tmp = icaltime_normalize(tmp);
+ 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++){
- short dow =
+ /* This is 1 (Sun) to 7 (Sat). */
+ int dow =
icalrecurrencetype_day_day_of_week(BYDAYPTR[i]);
- short pos = icalrecurrencetype_day_position(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 week;
- for(week = 0; week < 52 ; week ++){
- short doy = start_doy + (week * 7) + dow-1;
+ int doy, tmp_start_doy;
- if(doy > end_year_day){
- break;
- } else {
+ 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 */
+ /* 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;
@@ -1693,113 +1747,116 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
/* For INTERVAL=YEARLY, set up the days[] array in the iterator to
list all of the days of the current year that are specified in this
rule. */
-int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
+static int expand_year_days(icalrecur_iterator* impl, int year)
{
int j,k;
int days_index=0;
struct icaltimetype t;
int flags;
- t = icaltime_null_time();
+ t = icaltime_null_date();
#define HBD(x) has_by_data(impl,x)
- t.is_date = 1; /* Needed to make day_of_year routines work property */
-
- memset(&t,0,sizeof(t));
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++){
- struct icaltimetype t;
- short month = impl->by_ptrs[BY_MONTH][j];
- short doy;
+ 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++] = doy;
+ 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++)
{
- short month_day = impl->by_ptrs[BY_MONTH_DAY][k];
- short doy;
+ 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++] = doy;
+ 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++)
{
- short month = impl->by_ptrs[BY_MONTH][j];
- short month_day = impl->by_ptrs[BY_MONTH_DAY][k];
- short doy;
+ 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++] = doy;
+ impl->days[days_index++] = (short)doy;
}
}
break;
}
case 1<<BY_WEEK_NO: {
/* FREQ=YEARLY; BYWEEKNO=20,50 */
- struct icaltimetype t;
- short dow;
+ int dow;
t.day = impl->dtstart.day;
t.month = impl->dtstart.month;
t.year = year;
t.is_date = 1;
@@ -1816,74 +1873,99 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
break;
}
case 1<<BY_DAY: {
/*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/
- int days_index = 0;
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)(int)pvl_data(i);
+ short day = (short)(*((int*)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*/
- int days_index = 0;
- pvl_elem itr;
- pvl_list days = expand_by_day(impl,year);
- for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
- short doy = (short)(int)pvl_data(itr);
- struct icaltimetype tt;
- short j;
+ 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;
- tt = icaltime_from_day_of_year(doy,year);
+ t.year = year;
+ t.month = month;
+ t.day = 1;
+ t.is_date = 1;
- for(j=0;
- impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;
- j++){
- short month = impl->by_ptrs[BY_MONTH][j];
+ first_dow = icaltime_day_of_week(t);
- if(tt.month == month){
- impl->days[days_index++] = doy;
- }
- }
+ /* 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);
- pvl_free(days);
+ 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*/
- int days_index = 0;
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)(int)pvl_data(itr);
+ short day = (short)(*((int*)pvl_data(itr)));
struct icaltimetype tt;
- short j;
tt = icaltime_from_day_of_year(day,year);
for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
- short mday = BYMDPTR[j];
+ int mday = BYMDPTR[j];
if(tt.day == mday){
impl->days[days_index++] = day;
}
}
@@ -1894,27 +1976,26 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
break;
}
case (1<<BY_DAY) + (1<<BY_MONTH_DAY) + (1<<BY_MONTH): {
/*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=10; MYMONTH=6,11*/
- int days_index = 0;
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)(int)pvl_data(itr);
+ short day = (short)(*((int*)pvl_data(itr)));
struct icaltimetype tt;
- short i,j;
+ 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++){
- short mday = BYMDPTR[j];
- short month = BYMONPTR[i];
+ int mday = BYMDPTR[j];
+ int month = BYMONPTR[i];
if(tt.month == month && tt.day == mday){
impl->days[days_index++] = day;
}
}
}
@@ -1927,27 +2008,26 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
}
case (1<<BY_DAY) + (1<<BY_WEEK_NO) : {
/*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50*/
- int days_index = 0;
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)(int)pvl_data(itr);
+ short day = (short)(*((int*)pvl_data(itr)));
struct icaltimetype tt;
- short i;
+ int i;
tt = icaltime_from_day_of_year(day,year);
for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
- short weekno = BYWEEKPTR[i];
-
- if(weekno== icaltime_week_number(tt)){
+ int weekno = BYWEEKPTR[i];
+ int this_weekno = icaltime_week_number(tt);
+ if(weekno== this_weekno){
impl->days[days_index++] = day;
}
}
}
@@ -1960,14 +2040,13 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
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++){
- short doy = impl->by_ptrs[BY_YEAR_DAY][j];
- impl->days[days_index++] = doy;
+ impl->days[days_index++] = impl->by_ptrs[BY_YEAR_DAY][j];
}
break;
}
default: {
icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
@@ -1977,41 +2056,41 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
}
return 0;
}
-int next_year(struct icalrecur_iterator_impl* impl)
+static int next_year(icalrecur_iterator* impl)
{
struct icaltimetype next;
- /* Next_year does it's own interatio in days, so the next level down is hours */
if (next_hour(impl) == 0){
- return 1;
+ 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;
}
-
- if(impl->days[0] == ICAL_RECURRENCE_ARRAY_MAX) {
- return 0;
}
- next = icaltime_from_day_of_year(impl->days[impl->days_index],impl->last.year);
+ 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;
}
-int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl,
- short v, enum byrule byrule)
+int icalrecur_check_rulepart(icalrecur_iterator* impl,
+ int v, enum byrule byrule)
{
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){
@@ -2020,14 +2099,14 @@ int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl,
}
}
return 0;
}
-int check_contract_restriction(struct icalrecur_iterator_impl* impl,
- enum byrule byrule, short v)
+static int check_contract_restriction(icalrecur_iterator* impl,
+ enum byrule byrule, int v)
{
int pass = 0;
int itr;
icalrecurrencetype_frequency freq = impl->rule.freq;
if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX &&
@@ -2045,41 +2124,39 @@ int check_contract_restriction(struct icalrecur_iterator_impl* impl,
test passes*/
return 1;
}
}
-int check_contracting_rules(struct icalrecur_iterator_impl* impl)
+static int check_contracting_rules(icalrecur_iterator* impl)
{
- int day_of_week=0;
- int week_no=0;
- int year_day=0;
+ 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) )
+ 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;
}
}
-struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
+struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *impl)
{
int valid = 1;
- struct icalrecur_iterator_impl* impl =
- (struct icalrecur_iterator_impl*)itr;
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();
}
@@ -2117,13 +2194,13 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
}
case ICAL_MONTHLY_RECURRENCE: {
valid = next_month(impl);
break;
}
case ICAL_YEARLY_RECURRENCE:{
- valid = next_year(impl);
+ next_year(impl);
break;
}
default:{
icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
return icaltime_null_time();
}
@@ -2132,13 +2209,13 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
if(impl->last.year >= 2038 ){
/* HACK */
return icaltime_null_time();
}
} while(!check_contracting_rules(impl)
- || icaltime_compare(impl->last,impl->dtstart) <= 0
+ || 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 ) {
@@ -2163,45 +2240,44 @@ void icalrecurrencetype_clear(struct icalrecurrencetype *recur)
recur->freq = ICAL_NO_RECURRENCE;
recur->interval = 1;
memset(&(recur->until),0,sizeof(struct icaltimetype));
recur->count = 0;
}
-/* The 'day' element of icalrecurrencetype_weekday is encoded to allow
-reporesentation 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.
-
-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'
-
+/** 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.
+ *
+ * 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'
*/
enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day)
{
return abs(day)%8;
}
-short icalrecurrencetype_day_position(short day)
+int icalrecurrencetype_day_position(short day)
{
- short wd, pos;
+ int wd, pos;
wd = icalrecurrencetype_day_day_of_week(day);
pos = (abs(day)-wd)/8 * ((day<0)?-1:1);
return pos;
}
/****************** Enumeration Routines ******************/
-struct {icalrecurrencetype_weekday wd; const char * str; }
+static struct {icalrecurrencetype_weekday wd; const char * str; }
wd_map[] = {
{ICAL_SUNDAY_WEEKDAY,"SU"},
{ICAL_MONDAY_WEEKDAY,"MO"},
{ICAL_TUESDAY_WEEKDAY,"TU"},
{ICAL_WEDNESDAY_WEEKDAY,"WE"},
{ICAL_THURSDAY_WEEKDAY,"TH"},
@@ -2235,13 +2311,13 @@ icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str)
return ICAL_NO_WEEKDAY;
}
-struct {
+static struct {
icalrecurrencetype_frequency kind;
const char* str;
} freq_map[] = {
{ICAL_SECONDLY_RECURRENCE,"SECONDLY"},
{ICAL_MINUTELY_RECURRENCE,"MINUTELY"},
{ICAL_HOURLY_RECURRENCE,"HOURLY"},
@@ -2273,29 +2349,30 @@ icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str)
return freq_map[i].kind;
}
}
return ICAL_NO_RECURRENCE;
}
-/* Fill an array with the 'count' number of occurrences generated by
- the rrule. 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. */
+/** Fill an array with the 'count' number of occurrences generated by
+ * the rrule. 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.
+ */
int icalrecur_expand_recurrence(char* rule, time_t start,
int count, time_t* array)
{
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(start,0);
+ 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;