summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalrecur.c
Unidiff
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
@@ -21,3 +21,7 @@
21 the License at http://www.mozilla.org/MPL/ 21 the License at http://www.mozilla.org/MPL/
22*/
22 23
24/**
25 @file icalrecur.c
26 @brief Implementation of routines for dealing with recurring time
23 27
@@ -132,11 +136,10 @@
132 136
137#ifdef HAVE_STDINT_H
138#include <stdint.h>
139#endif
140
133#include "icalrecur.h" 141#include "icalrecur.h"
134 142
135#ifdef ICAL_NO_LIBICAL
136#define icalerror_set_errno(x)
137#define icalerror_check_arg_rv(x,y)
138#else
139#include "icalerror.h" 143#include "icalerror.h"
140#include "icalmemory.h" 144#include "icalmemory.h"
141#endif
142 145
@@ -150,2 +153,6 @@
150 153
154/** This is the last year we will go up to, since 32-bit time_t values
155 only go up to the start of 2038. */
156 #define MAX_TIME_T_YEAR2037
157
151#define TEMP_MAX 1024 158#define TEMP_MAX 1024
@@ -172,3 +179,2 @@ icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str);
172 179
173
174/*********************** Rule parsing routines ************************/ 180/*********************** Rule parsing routines ************************/
@@ -255,3 +261,3 @@ void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
255 int sign = 1; 261 int sign = 1;
256 short v; 262 int v;
257 263
@@ -282,2 +288,4 @@ void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
282 t++; 288 t++;
289 } else {
290 sign = 1;
283 } 291 }
@@ -287,3 +295,3 @@ void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
287 295
288 array[i++] = v; 296 array[i++] = (short)v;
289 array[i] = ICAL_RECURRENCE_ARRAY_MAX; 297 array[i] = ICAL_RECURRENCE_ARRAY_MAX;
@@ -334,13 +342,10 @@ void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals)
334 342
335 weekno = 0;
336 /* Get Optional weekno */ 343 /* Get Optional weekno */
337 if( sscanf(t,"%d",&weekno) != 0){ 344 weekno = strtol(t,&t,10);
338 if (n != 0){ 345
339 int weeknolen = (n-t)-3; /* 3 -> one for \0, 2 for day name */ 346 /* Outlook/Exchange generate "BYDAY=MO, FR" and "BYDAY=2 TH".
340 /* could use abs(log10(weekno))+1, but that needs libm */ 347 * Cope with that.
341 t += weeknolen; 348 */
342 } else { 349 if (*t == ' ')
343 t = end -2; 350 t++;
344 }
345 }
346 351
@@ -348,3 +353,3 @@ void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals)
348 353
349 array[i++] = sign* ((int)wd + 8*weekno); 354 array[i++] = (short)(sign* (wd + 8*weekno));
350 array[i] = ICAL_RECURRENCE_ARRAY_MAX; 355 array[i] = ICAL_RECURRENCE_ARRAY_MAX;
@@ -389,2 +394,3 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
389 icalrecurrencetype_clear(&parser.rt); 394 icalrecurrencetype_clear(&parser.rt);
395 free(parser.copy);
390 return parser.rt; 396 return parser.rt;
@@ -399,3 +405,3 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
399 } else if (strcmp(name,"INTERVAL") == 0){ 405 } else if (strcmp(name,"INTERVAL") == 0){
400 parser.rt.interval = atoi(value); 406 parser.rt.interval = (short)atoi(value);
401 } else if (strcmp(name,"WKST") == 0){ 407 } else if (strcmp(name,"WKST") == 0){
@@ -431,2 +437,3 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
431 icalrecurrencetype_clear(&parser.rt); 437 icalrecurrencetype_clear(&parser.rt);
438 free(parser.copy);
432 return parser.rt; 439 return parser.rt;
@@ -442,5 +449,3 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
442 449
443#ifndef ICAL_NO_LIBICAL 450static struct { char* str;size_t offset; int limit; } recurmap[] =
444
445struct { char* str;size_t offset; short limit; } recurmap[] =
446{ 451{
@@ -459,2 +464,3 @@ struct { char* str;size_t offset; short limit; } recurmap[] =
459/* A private routine in icalvalue.c */ 464/* A private routine in icalvalue.c */
465void print_date_to_string(char* str, struct icaltimetype *data);
460void print_datetime_to_string(char* str, struct icaltimetype *data); 466void print_datetime_to_string(char* str, struct icaltimetype *data);
@@ -483,3 +489,6 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
483 temp[0] = 0; 489 temp[0] = 0;
484 print_datetime_to_string(temp,&(recur->until)); 490 if (recur->until.is_date)
491 print_date_to_string(temp,&(recur->until));
492 else
493 print_datetime_to_string(temp,&(recur->until));
485 494
@@ -503,3 +512,3 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
503 short* array = (short*)(recurmap[j].offset+ (size_t)recur); 512 short* array = (short*)(recurmap[j].offset+ (size_t)recur);
504 short limit = recurmap[j].limit; 513 int limit = recurmap[j].limit;
505 514
@@ -514,5 +523,5 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
514 if (j == 3) { /* BYDAY */ 523 if (j == 3) { /* BYDAY */
515 short dow = icalrecurrencetype_day_day_of_week(array[i]); 524 const char *daystr = icalrecur_weekday_to_string(
516 const char *daystr = icalrecur_weekday_to_string(dow); 525 icalrecurrencetype_day_day_of_week(array[i]));
517 short pos; 526 int pos;
518 527
@@ -542,4 +551,2 @@ char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
542} 551}
543#endif
544
545 552
@@ -575,6 +582,6 @@ struct icalrecur_iterator_impl {
575 short by_indices[9]; 582 short by_indices[9];
576 short orig_data[9]; /* 1 if there was data in the byrule */ 583 short orig_data[9]; /**< 1 if there was data in the byrule */
577 584
578 585
579 short *by_ptrs[9]; /* Pointers into the by_* array elements of the rule */ 586 short *by_ptrs[9]; /**< Pointers into the by_* array elements of the rule */
580 587
@@ -582,2 +589,4 @@ struct icalrecur_iterator_impl {
582 589
590static void increment_year(icalrecur_iterator* impl, int inc);
591
583int icalrecur_iterator_sizeof_byarray(short* byarray) 592int icalrecur_iterator_sizeof_byarray(short* byarray)
@@ -601,6 +610,9 @@ enum expand_table {
601 610
602/* The split map indicates, for a particular interval, wether a BY_* 611/**
603 rule part expands the number of instances in the occcurrence set or 612 * The split map indicates, for a particular interval, wether a BY_*
604 contracts it. 1=> contract, 2=>expand, and 3 means the pairing is 613 * rule part expands the number of instances in the occcurrence set or
605 not allowed. */ 614 * contracts it. 1=> contract, 2=>expand, and 3 means the pairing is
615 * not allowed.
616 */
617
606struct expand_split_map_struct 618struct expand_split_map_struct
@@ -615,3 +627,3 @@ struct expand_split_map_struct
615 627
616struct expand_split_map_struct expand_map[] = 628static struct expand_split_map_struct expand_map[] =
617{ 629{
@@ -630,4 +642,5 @@ struct expand_split_map_struct expand_map[] =
630 642
631/* Check that the rule has only the two given interday byrule parts. */ 643/** Check that the rule has only the two given interday byrule parts. */
632int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl, 644static
645int icalrecur_two_byrule(icalrecur_iterator* impl,
633 enum byrule one,enum byrule two) 646 enum byrule one,enum byrule two)
@@ -638,3 +651,3 @@ int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl,
638 651
639 memset(test_array,0,9); 652 memset(test_array,0,sizeof(test_array));
640 653
@@ -661,4 +674,4 @@ int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl,
661 674
662/* Check that the rule has only the one given interdat byrule parts. */ 675/** Check that the rule has only the one given interdat byrule parts. */
663int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one) 676static int icalrecur_one_byrule(icalrecur_iterator* impl,enum byrule one)
664{ 677{
@@ -678,3 +691,3 @@ int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one)
678 691
679int count_byrules(struct icalrecur_iterator_impl* impl) 692static int count_byrules(icalrecur_iterator* impl)
680{ 693{
@@ -693,5 +706,5 @@ int count_byrules(struct icalrecur_iterator_impl* impl)
693 706
694void setup_defaults(struct icalrecur_iterator_impl* impl, 707static void setup_defaults(icalrecur_iterator* impl,
695 enum byrule byrule, icalrecurrencetype_frequency req, 708 enum byrule byrule, icalrecurrencetype_frequency req,
696 short deftime, int *timepart) 709 int deftime, int *timepart)
697{ 710{
@@ -706,3 +719,3 @@ void setup_defaults(struct icalrecur_iterator_impl* impl,
706 expand_map[freq].map[byrule] != CONTRACT){ 719 expand_map[freq].map[byrule] != CONTRACT){
707 impl->by_ptrs[byrule][0] = deftime; 720 impl->by_ptrs[byrule][0] = (short)deftime;
708 } 721 }
@@ -717,3 +730,3 @@ void setup_defaults(struct icalrecur_iterator_impl* impl,
717 730
718int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){ 731static int has_by_data(icalrecur_iterator* impl, enum byrule byrule){
719 732
@@ -723,3 +736,3 @@ int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){
723 736
724int expand_year_days(struct icalrecur_iterator_impl* impl,short year); 737static int expand_year_days(icalrecur_iterator* impl, int year);
725 738
@@ -729,9 +742,7 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
729{ 742{
730 struct icalrecur_iterator_impl* impl; 743 icalrecur_iterator* impl;
731 icalrecurrencetype_frequency freq; 744 icalrecurrencetype_frequency freq;
732 745
733 short days_in_month; 746 if ( ( impl = (icalrecur_iterator*)
734 747 malloc(sizeof(icalrecur_iterator))) == 0) {
735 if ( ( impl = (struct icalrecur_iterator_impl *)
736 malloc(sizeof(struct icalrecur_iterator_impl))) == 0) {
737 icalerror_set_errno(ICAL_NEWFAILED_ERROR); 748 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
@@ -740,3 +751,3 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
740 751
741 memset(impl,0,sizeof(struct icalrecur_iterator_impl)); 752 memset(impl,0,sizeof(icalrecur_iterator));
742 753
@@ -762,3 +773,3 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
762 773
763 memset(impl->orig_data,0,9); 774 memset(impl->orig_data,0,9*sizeof(short));
764 775
@@ -770,19 +781,19 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
770 impl->orig_data[BY_MONTH] 781 impl->orig_data[BY_MONTH]
771 = (impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX); 782 = (short)(impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX);
772 impl->orig_data[BY_WEEK_NO] 783 impl->orig_data[BY_WEEK_NO]
773 =(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX); 784 =(short)(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX);
774 impl->orig_data[BY_YEAR_DAY] 785 impl->orig_data[BY_YEAR_DAY]
775 =(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); 786 =(short)(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
776 impl->orig_data[BY_MONTH_DAY] 787 impl->orig_data[BY_MONTH_DAY]
777 =(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); 788 =(short)(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
778 impl->orig_data[BY_DAY] 789 impl->orig_data[BY_DAY]
779 = (impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); 790 = (short)(impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
780 impl->orig_data[BY_HOUR] 791 impl->orig_data[BY_HOUR]
781 = (impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX); 792 = (short)(impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX);
782 impl->orig_data[BY_MINUTE] 793 impl->orig_data[BY_MINUTE]
783 = (impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX); 794 = (short)(impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX);
784 impl->orig_data[BY_SECOND] 795 impl->orig_data[BY_SECOND]
785 = (impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX); 796 = (short)(impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX);
786 impl->orig_data[BY_SET_POS] 797 impl->orig_data[BY_SET_POS]
787 = (impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX); 798 = (short)(impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX);
788 799
@@ -854,15 +865,20 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
854 865
855 setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,impl->dtstart.second, 866 setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,
867 impl->dtstart.second,
856 &(impl->last.second)); 868 &(impl->last.second));
857 869
858 setup_defaults(impl,BY_MINUTE,ICAL_MINUTELY_RECURRENCE,impl->dtstart.minute, 870 setup_defaults(impl,BY_MINUTE,ICAL_MINUTELY_RECURRENCE,
871 impl->dtstart.minute,
859 &(impl->last.minute)); 872 &(impl->last.minute));
860 873
861 setup_defaults(impl,BY_HOUR,ICAL_HOURLY_RECURRENCE,impl->dtstart.hour, 874 setup_defaults(impl,BY_HOUR,ICAL_HOURLY_RECURRENCE,
875 impl->dtstart.hour,
862 &(impl->last.hour)); 876 &(impl->last.hour));
863 877
864 setup_defaults(impl,BY_MONTH_DAY,ICAL_DAILY_RECURRENCE,impl->dtstart.day, 878 setup_defaults(impl,BY_MONTH_DAY,ICAL_DAILY_RECURRENCE,
879 impl->dtstart.day,
865 &(impl->last.day)); 880 &(impl->last.day));
866 881
867 setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,impl->dtstart.month, 882 setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,
883 impl->dtstart.month,
868 &(impl->last.month)); 884 &(impl->last.month));
@@ -876,3 +892,3 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
876 same day of the week as the start time . */ 892 same day of the week as the start time . */
877 impl->by_ptrs[BY_DAY][0] = icaltime_day_of_week(impl->dtstart); 893 impl->by_ptrs[BY_DAY][0] = (short)icaltime_day_of_week(impl->dtstart);
878 894
@@ -890,3 +906,3 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
890 906
891 short dow = impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last); 907 short dow = (short)(impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last));
892 908
@@ -903,6 +919,20 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
903 919
904 /* For YEARLY rule, begin by setting up the year days array */ 920 /* For YEARLY rule, begin by setting up the year days array . The
921 YEARLY rules work by expanding one year at a time. */
905 922
906 if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){ 923 if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){
907 expand_year_days(impl,impl->last.year); 924 struct icaltimetype next;
925
926 for (;;) {
927 expand_year_days(impl, impl->last.year);
928 if (impl->days[0] != ICAL_RECURRENCE_ARRAY_MAX)
929 break; /* break when no days are expanded */
930 increment_year(impl,impl->rule.interval);
931 }
932
933 /* Copy the first day into last. */
934 next = icaltime_from_day_of_year(impl->days[0], impl->last.year);
935
936 impl->last.day = next.day;
937 impl->last.month = next.month;
908 } 938 }
@@ -916,9 +946,9 @@ icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
916 946
917 short dow = icalrecurrencetype_day_day_of_week( 947 int dow = icalrecurrencetype_day_day_of_week(
918 impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); 948 impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
919 short pos = icalrecurrencetype_day_position( 949 int pos = icalrecurrencetype_day_position(
920 impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); 950 impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
921 951
922 short poscount = 0; 952 int poscount = 0;
923 days_in_month = 953 int days_in_month =
924 icaltime_days_in_month(impl->last.month, impl->last.year); 954 icaltime_days_in_month(impl->last.month, impl->last.year);
@@ -971,9 +1001,5 @@ void icalrecur_iterator_free(icalrecur_iterator* i)
971{ 1001{
1002 icalerror_check_arg_rv((i!=0),"impl");
972 1003
973 struct icalrecur_iterator_impl* impl = 1004 free(i);
974 (struct icalrecur_iterator_impl*)i;
975
976 icalerror_check_arg_rv((impl!=0),"impl");
977
978 free(impl);
979 1005
@@ -981,4 +1007,3 @@ void icalrecur_iterator_free(icalrecur_iterator* i)
981 1007
982 1008static void increment_year(icalrecur_iterator* impl, int inc)
983void increment_year(struct icalrecur_iterator_impl* impl, int inc)
984{ 1009{
@@ -987,6 +1012,6 @@ void increment_year(struct icalrecur_iterator_impl* impl, int inc)
987 1012
988/* Increment month is different that the other incement_* routines -- 1013/** Increment month is different that the other incement_* routines --
989 it figures out the interval for itself, and uses BYMONTH data if 1014 it figures out the interval for itself, and uses BYMONTH data if
990 available. */ 1015 available. */
991void increment_month(struct icalrecur_iterator_impl* impl) 1016static void increment_month(icalrecur_iterator* impl)
992{ 1017{
@@ -1037,3 +1062,3 @@ void increment_month(struct icalrecur_iterator_impl* impl)
1037 1062
1038void increment_monthday(struct icalrecur_iterator_impl* impl, int inc) 1063static void increment_monthday(icalrecur_iterator* impl, int inc)
1039{ 1064{
@@ -1043,4 +1068,4 @@ void increment_monthday(struct icalrecur_iterator_impl* impl, int inc)
1043 1068
1044 short days_in_month = 1069 int days_in_month =
1045 icaltime_days_in_month(impl->last.month,impl->last.year); 1070 icaltime_days_in_month(impl->last.month, impl->last.year);
1046 1071
@@ -1056,5 +1081,5 @@ void increment_monthday(struct icalrecur_iterator_impl* impl, int inc)
1056 1081
1057void increment_hour(struct icalrecur_iterator_impl* impl, int inc) 1082static void increment_hour(icalrecur_iterator* impl, int inc)
1058{ 1083{
1059 short days; 1084 int days;
1060 1085
@@ -1070,5 +1095,5 @@ void increment_hour(struct icalrecur_iterator_impl* impl, int inc)
1070 1095
1071void increment_minute(struct icalrecur_iterator_impl* impl, int inc) 1096static void increment_minute(icalrecur_iterator* impl, int inc)
1072{ 1097{
1073 short hours; 1098 int hours;
1074 1099
@@ -1085,5 +1110,5 @@ void increment_minute(struct icalrecur_iterator_impl* impl, int inc)
1085 1110
1086void increment_second(struct icalrecur_iterator_impl* impl, int inc) 1111static void increment_second(icalrecur_iterator* impl, int inc)
1087{ 1112{
1088 short minutes; 1113 int minutes;
1089 1114
@@ -1104,3 +1129,3 @@ void test_increment()
1104{ 1129{
1105 struct icalrecur_iterator_impl impl; 1130 icalrecur_iterator impl;
1106 1131
@@ -1134,13 +1159,13 @@ void test_increment()
1134 1159
1135short next_second(struct icalrecur_iterator_impl* impl) 1160static int next_second(icalrecur_iterator* impl)
1136{ 1161{
1137 1162
1138 short has_by_data = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1163 int has_by_second = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1139 short this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE); 1164 int this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE);
1140 1165
1141 short end_of_data = 0; 1166 int end_of_data = 0;
1142 1167
1143 assert(has_by_data || this_frequency); 1168 assert(has_by_second || this_frequency);
1144 1169
1145 if( has_by_data ){ 1170 if( has_by_second ){
1146 /* Ignore the frequency and use the byrule data */ 1171 /* Ignore the frequency and use the byrule data */
@@ -1161,3 +1186,3 @@ short next_second(struct icalrecur_iterator_impl* impl)
1161 1186
1162 } else if( !has_by_data && this_frequency ){ 1187 } else if( !has_by_second && this_frequency ){
1163 /* Compute the next value from the last time and the frequency interval*/ 1188 /* Compute the next value from the last time and the frequency interval*/
@@ -1170,3 +1195,3 @@ short next_second(struct icalrecur_iterator_impl* impl)
1170 1195
1171 if(has_by_data && end_of_data && this_frequency ){ 1196 if(has_by_second && end_of_data && this_frequency ){
1172 increment_minute(impl,1); 1197 increment_minute(impl,1);
@@ -1178,11 +1203,11 @@ short next_second(struct icalrecur_iterator_impl* impl)
1178 1203
1179int next_minute(struct icalrecur_iterator_impl* impl) 1204static int next_minute(icalrecur_iterator* impl)
1180{ 1205{
1181 1206
1182 short has_by_data = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1207 int has_by_minute = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1183 short this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE); 1208 int this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE);
1184 1209
1185 short end_of_data = 0; 1210 int end_of_data = 0;
1186 1211
1187 assert(has_by_data || this_frequency); 1212 assert(has_by_minute || this_frequency);
1188 1213
@@ -1193,3 +1218,3 @@ int next_minute(struct icalrecur_iterator_impl* impl)
1193 1218
1194 if( has_by_data ){ 1219 if( has_by_minute ){
1195 /* Ignore the frequency and use the byrule data */ 1220 /* Ignore the frequency and use the byrule data */
@@ -1209,3 +1234,3 @@ int next_minute(struct icalrecur_iterator_impl* impl)
1209 1234
1210 } else if( !has_by_data && this_frequency ){ 1235 } else if( !has_by_minute && this_frequency ){
1211 /* Compute the next value from the last time and the frequency interval*/ 1236 /* Compute the next value from the last time and the frequency interval*/
@@ -1217,3 +1242,3 @@ int next_minute(struct icalrecur_iterator_impl* impl)
1217 1242
1218 if(has_by_data && end_of_data && this_frequency ){ 1243 if(has_by_minute && end_of_data && this_frequency ){
1219 increment_hour(impl,1); 1244 increment_hour(impl,1);
@@ -1224,11 +1249,11 @@ int next_minute(struct icalrecur_iterator_impl* impl)
1224 1249
1225int next_hour(struct icalrecur_iterator_impl* impl) 1250static int next_hour(icalrecur_iterator* impl)
1226{ 1251{
1227 1252
1228 short has_by_data = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1253 int has_by_hour = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1229 short this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE); 1254 int this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE);
1230 1255
1231 short end_of_data = 0; 1256 int end_of_data = 0;
1232 1257
1233 assert(has_by_data || this_frequency); 1258 assert(has_by_hour || this_frequency);
1234 1259
@@ -1238,3 +1263,3 @@ int next_hour(struct icalrecur_iterator_impl* impl)
1238 1263
1239 if( has_by_data ){ 1264 if( has_by_hour ){
1240 /* Ignore the frequency and use the byrule data */ 1265 /* Ignore the frequency and use the byrule data */
@@ -1253,3 +1278,3 @@ int next_hour(struct icalrecur_iterator_impl* impl)
1253 1278
1254 } else if( !has_by_data && this_frequency ){ 1279 } else if( !has_by_hour && this_frequency ){
1255 /* Compute the next value from the last time and the frequency interval*/ 1280 /* Compute the next value from the last time and the frequency interval*/
@@ -1262,3 +1287,3 @@ int next_hour(struct icalrecur_iterator_impl* impl)
1262 1287
1263 if(has_by_data && end_of_data && this_frequency ){ 1288 if(has_by_hour && end_of_data && this_frequency ){
1264 increment_monthday(impl,1); 1289 increment_monthday(impl,1);
@@ -1270,9 +1295,9 @@ int next_hour(struct icalrecur_iterator_impl* impl)
1270 1295
1271int next_day(struct icalrecur_iterator_impl* impl) 1296static int next_day(icalrecur_iterator* impl)
1272{ 1297{
1273 1298
1274 short has_by_data = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1299 int has_by_day = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1275 short this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE); 1300 int this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE);
1276 1301
1277 assert(has_by_data || this_frequency); 1302 assert(has_by_day || this_frequency);
1278 1303
@@ -1298,10 +1323,10 @@ int next_day(struct icalrecur_iterator_impl* impl)
1298 1323
1299int next_yearday(struct icalrecur_iterator_impl* impl) 1324static int next_yearday(icalrecur_iterator* impl)
1300{ 1325{
1301 1326
1302 short has_by_data = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1327 int has_by_yearday = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1303 1328
1304 short end_of_data = 0; 1329 int end_of_data = 0;
1305 1330
1306 assert(has_by_data ); 1331 assert(has_by_yearday );
1307 1332
@@ -1323,3 +1348,3 @@ int next_yearday(struct icalrecur_iterator_impl* impl)
1323 1348
1324 if(has_by_data && end_of_data){ 1349 if(has_by_yearday && end_of_data){
1325 increment_year(impl,1); 1350 increment_year(impl,1);
@@ -1331,58 +1356,11 @@ int next_yearday(struct icalrecur_iterator_impl* impl)
1331 1356
1332/* This routine is only called by next_week. It is certain that BY_DAY
1333has data */
1334
1335int next_weekday_by_week(struct icalrecur_iterator_impl* impl)
1336{
1337
1338 short end_of_data = 0;
1339 short start_of_week, dow;
1340 struct icaltimetype next;
1341
1342 if (next_hour(impl) == 0){
1343 return 0;
1344 }
1345
1346 assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
1347
1348 while(1) {
1349
1350 impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */
1351
1352 /* Are we at the end of the BYDAY array? */
1353 if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]
1354 ==ICAL_RECURRENCE_ARRAY_MAX){
1355
1356 impl->by_indices[BY_DAY] = 0; /* Reset to 0 */
1357 end_of_data = 1; /* Signal that we're at the end */
1358 }
1359
1360 /* Add the day of week offset to to the start of this week, and use
1361 that to get the next day */
1362 dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]];
1363 start_of_week = icaltime_start_doy_of_week(impl->last);
1364
1365 dow--; /*Sun is 1, not 0 */
1366
1367 if(dow+start_of_week <1 && !end_of_data){
1368 /* The selected date is in the previous year. */
1369 continue;
1370 }
1371
1372 next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year);
1373
1374 impl->last.day = next.day;
1375 impl->last.month = next.month;
1376 impl->last.year = next.year;
1377
1378 return end_of_data;
1379 }
1380 1357
1381} 1358/* Returns the day of the month for the current month of t that is the
1359 pos'th instance of the day-of-week dow */
1382 1360
1383int nth_weekday(short dow, short pos, struct icaltimetype t){ 1361static int nth_weekday(int dow, int pos, struct icaltimetype t){
1384 1362
1385 short days_in_month = icaltime_days_in_month(t.month,t.year); 1363 int days_in_month = icaltime_days_in_month(t.month, t.year);
1386 short end_dow, start_dow; 1364 int end_dow, start_dow;
1387 short wd; 1365 int wd;
1388 1366
@@ -1430,4 +1408,21 @@ int nth_weekday(short dow, short pos, struct icaltimetype t){
1430 1408
1409static int is_day_in_byday(icalrecur_iterator* impl,struct icaltimetype tt){
1410
1411 int idx;
1431 1412
1432int next_month(struct icalrecur_iterator_impl* impl) 1413 for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
1414 int dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
1415 int pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
1416 int this_dow = icaltime_day_of_week(tt);
1417
1418 if( (pos == 0 && dow == this_dow ) || /* Just a dow, like "TU" or "FR" */
1419 (nth_weekday(dow,pos,tt) == tt.day)){ /*pos+wod: "3FR" or -1TU" */
1420 return 1;
1421 }
1422 }
1423
1424 return 0;
1425}
1426
1427static int next_month(icalrecur_iterator* impl)
1433{ 1428{
@@ -1435,3 +1430,3 @@ int next_month(struct icalrecur_iterator_impl* impl)
1435 1430
1436 short this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE); 1431 int this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE);
1437 1432
@@ -1447,10 +1442,13 @@ int next_month(struct icalrecur_iterator_impl* impl)
1447 1442
1448
1449 /* Now iterate through the occurrences within a month -- by days, 1443 /* Now iterate through the occurrences within a month -- by days,
1450 weeks or weekdays. */ 1444 weeks or weekdays. */
1445
1446 /*
1447 * Case 1:
1448 * Rules Like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13
1449 */
1451 1450
1452 if(has_by_data(impl,BY_DAY) && has_by_data(impl,BY_MONTH_DAY)){ 1451 if(has_by_data(impl,BY_DAY) && has_by_data(impl,BY_MONTH_DAY)){
1453 /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13 */ 1452 int day, idx,j;
1454 short day, idx,j; 1453 int days_in_month = icaltime_days_in_month(impl->last.month,
1455 short days_in_month = icaltime_days_in_month(impl->last.month,
1456 impl->last.year); 1454 impl->last.year);
@@ -1465,7 +1463,7 @@ int next_month(struct icalrecur_iterator_impl* impl)
1465 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ 1463 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
1466 short dow = 1464 int dow =
1467 icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]); 1465 icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
1468 short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]); 1466 int pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
1469 short mday = BYMDPTR[j]; 1467 int mday = BYMDPTR[j];
1470 short this_dow; 1468 int this_dow;
1471 1469
@@ -1490,5 +1488,9 @@ int next_month(struct icalrecur_iterator_impl* impl)
1490 1488
1491 1489
1490 /*
1491 * Case 2:
1492 * Rules Like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR
1493 */
1494
1492 } else if(has_by_data(impl,BY_DAY)){ 1495 } else if(has_by_data(impl,BY_DAY)){
1493 /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR */
1494 /* For this case, the weekdays are relative to the 1496 /* For this case, the weekdays are relative to the
@@ -1496,27 +1498,18 @@ int next_month(struct icalrecur_iterator_impl* impl)
1496 1498
1497 short day, idx; 1499 /* This code iterates through the remaining days in the month
1498 short days_in_month = icaltime_days_in_month(impl->last.month, 1500 and checks if each day is listed in the BY_DAY array. This
1499 impl->last.year); 1501 seems very inneficient, but I think it is the simplest way to
1502 account for both BYDAY=1FR (First friday in month) and
1503 BYDAY=FR ( every friday in month ) */
1500 1504
1505 int day;
1506 int days_in_month = icaltime_days_in_month(impl->last.month,
1507 impl->last.year);
1501 assert( BYDAYPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX); 1508 assert( BYDAYPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);
1502 1509
1503 /* Iterate through the remaining days in the month and check if
1504 each day is listed in the BY_DAY array. This seems very
1505 inneficient, but I think it is the simplest way to account
1506 for both BYDAY=1FR (First friday in month) and BYDAY=FR (
1507 every friday in month ) */
1508
1509 for(day = impl->last.day+1; day <= days_in_month; day++){ 1510 for(day = impl->last.day+1; day <= days_in_month; day++){
1510 for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){ 1511 impl->last.day = day;
1511 short dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]); 1512 if(is_day_in_byday(impl,impl->last)){
1512 short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]); 1513 data_valid = 1;
1513 short this_dow; 1514 break;
1514
1515 impl->last.day = day;
1516 this_dow = icaltime_day_of_week(impl->last);
1517
1518 if( (pos == 0 && dow == this_dow ) ||
1519 (nth_weekday(dow,pos,impl->last) == day)){
1520 goto DEND;
1521 }
1522 } 1515 }
@@ -1524,4 +1517,2 @@ int next_month(struct icalrecur_iterator_impl* impl)
1524 1517
1525 DEND:
1526
1527 if ( day > days_in_month){ 1518 if ( day > days_in_month){
@@ -1529,8 +1520,21 @@ int next_month(struct icalrecur_iterator_impl* impl)
1529 increment_month(impl); 1520 increment_month(impl);
1530 data_valid = 0; /* signal that impl->last is invalid */ 1521
1522 /* Did moving to the next month put us on a valid date? if
1523 so, note that the new data is valid, if, not, mark it
1524 invalid */
1525
1526 if(is_day_in_byday(impl,impl->last)){
1527 data_valid = 1;
1528 } else {
1529 data_valid = 0; /* signal that impl->last is invalid */
1530 }
1531 } 1531 }
1532 1532
1533 /*
1534 * Case 3
1535 * Rules Like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3
1536 */
1537
1533 } else if (has_by_data(impl,BY_MONTH_DAY)) { 1538 } else if (has_by_data(impl,BY_MONTH_DAY)) {
1534 /* Cases like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3 */ 1539 int day;
1535 short day;
1536 1540
@@ -1550,4 +1554,3 @@ int next_month(struct icalrecur_iterator_impl* impl)
1550 if (day < 0) { 1554 if (day < 0) {
1551 day = icaltime_days_in_month(impl->last.month,impl->last.year)+ 1555 day = icaltime_days_in_month(impl->last.month, impl->last.year) + day + 1;
1552 day + 1;
1553 } 1556 }
@@ -1560,3 +1563,3 @@ int next_month(struct icalrecur_iterator_impl* impl)
1560 1563
1561 return data_valid; /* Signal that the data is valid */ 1564 return data_valid;
1562 1565
@@ -1564,10 +1567,64 @@ int next_month(struct icalrecur_iterator_impl* impl)
1564 1567
1568static int next_weekday_by_week(icalrecur_iterator* impl)
1569{
1570
1571 int end_of_data = 0;
1572 int start_of_week, dow;
1573 struct icaltimetype next;
1574
1575 if (next_hour(impl) == 0){
1576 return 0;
1577 }
1578
1579 if(!has_by_data(impl,BY_DAY)){
1580 return 1;
1581 }
1582
1583 /* If we get here, we need to step to tne next day */
1584
1585 for (;;) {
1586 struct icaltimetype tt = icaltime_null_time();
1587 BYDAYIDX++; /* Look at next elem in BYDAY array */
1588
1589 /* Are we at the end of the BYDAY array? */
1590 if (BYDAYPTR[BYDAYIDX]==ICAL_RECURRENCE_ARRAY_MAX){
1591 BYDAYIDX = 0; /* Reset to 0 */
1592 end_of_data = 1; /* Signal that we're at the end */
1593 }
1594
1595 /* Add the day of week offset to to the start of this week, and use
1596 that to get the next day */
1597 /* ignore position of dow ("4FR"), only use dow ("FR")*/
1598 dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[BYDAYIDX]);
1599 tt.year = impl->last.year;
1600 tt.day = impl->last.day;
1601 tt.month = impl->last.month;
1602
1603 start_of_week = icaltime_start_doy_of_week(tt);
1604
1605 dow--; /* Set Sunday to be 0 */
1606
1607 if(dow+start_of_week <1){
1608 /* The selected date is in the previous year. */
1609 if(!end_of_data){
1610 continue;
1611 }
1612 }
1613
1614 next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year);
1615
1616 impl->last.day = next.day;
1617 impl->last.month = next.month;
1618 impl->last.year = next.year;
1619
1620 return end_of_data;
1621 }
1622
1623}
1565 1624
1566int next_week(struct icalrecur_iterator_impl* impl) 1625static int next_week(icalrecur_iterator* impl)
1567{ 1626{
1568 short has_by_data = (impl->by_ptrs[BY_WEEK_NO][0]!=ICAL_RECURRENCE_ARRAY_MAX); 1627 int end_of_data = 0;
1569 short this_frequency = (impl->rule.freq == ICAL_WEEKLY_RECURRENCE);
1570 short end_of_data = 0;
1571 1628
1572 /* Increment to the next week day */ 1629 /* Increment to the next week day, if there is data at a level less than a week */
1573 if (next_weekday_by_week(impl) == 0){ 1630 if (next_weekday_by_week(impl) == 0){
@@ -1579,4 +1636,4 @@ int next_week(struct icalrecur_iterator_impl* impl)
1579 1636
1580 1637 if( has_by_data(impl,BY_WEEK_NO)){
1581 if( has_by_data){ 1638 /*FREQ=WEEKLY;BYWEEK=20*/
1582 /* Use the Week Number byrule data */ 1639 /* Use the Week Number byrule data */
@@ -1604,4 +1661,4 @@ int next_week(struct icalrecur_iterator_impl* impl)
1604 1661
1605 } else if( !has_by_data && this_frequency ){ 1662 } else {
1606 /* If there is no BY_WEEK_NO data, just jump forward 7 days. */ 1663 /* Jump to the next week */
1607 increment_monthday(impl,7*impl->rule.interval); 1664 increment_monthday(impl,7*impl->rule.interval);
@@ -1609,4 +1666,3 @@ int next_week(struct icalrecur_iterator_impl* impl)
1609 1666
1610 1667 if( has_by_data(impl,BY_WEEK_NO) && end_of_data){
1611 if(has_by_data && end_of_data && this_frequency ){
1612 increment_year(impl,1); 1668 increment_year(impl,1);
@@ -1618,4 +1674,4 @@ int next_week(struct icalrecur_iterator_impl* impl)
1618 1674
1619/* Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */ 1675/** Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */
1620pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year) 1676static pvl_list expand_by_day(icalrecur_iterator* impl, int year)
1621{ 1677{
@@ -1625,3 +1681,3 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1625 1681
1626 short start_dow, end_dow, end_year_day, start_doy; 1682 int start_dow, end_dow, end_year_day;
1627 struct icaltimetype tmp = impl->last; 1683 struct icaltimetype tmp = impl->last;
@@ -1633,10 +1689,10 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1633 1689
1690 /* Find the day that 1st Jan falls on, 1 (Sun) to 7 (Sat). */
1634 start_dow = icaltime_day_of_week(tmp); 1691 start_dow = icaltime_day_of_week(tmp);
1635 start_doy = icaltime_start_doy_of_week(tmp);
1636 1692
1637 /* Get the last day of the year*/ 1693 /* Get the last day of the year*/
1638 tmp.year++; 1694 tmp.year= year;
1639 tmp = icaltime_normalize(tmp); 1695 tmp.month = 12;
1640 tmp.day--; 1696 tmp.day = 31;
1641 tmp = icaltime_normalize(tmp); 1697 tmp.is_date = 1;
1642 1698
@@ -1646,5 +1702,6 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1646 for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){ 1702 for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
1647 short dow = 1703 /* This is 1 (Sun) to 7 (Sat). */
1704 int dow =
1648 icalrecurrencetype_day_day_of_week(BYDAYPTR[i]); 1705 icalrecurrencetype_day_day_of_week(BYDAYPTR[i]);
1649 short pos = icalrecurrencetype_day_position(BYDAYPTR[i]); 1706 int pos = icalrecurrencetype_day_position(BYDAYPTR[i]);
1650 1707
@@ -1654,12 +1711,9 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1654 days of the year with this day-of-week*/ 1711 days of the year with this day-of-week*/
1655 int week; 1712 int doy, tmp_start_doy;
1656 for(week = 0; week < 52 ; week ++){
1657 short doy = start_doy + (week * 7) + dow-1;
1658 1713
1659 if(doy > end_year_day){ 1714 tmp_start_doy = ((dow + 7 - start_dow) % 7) + 1;
1660 break; 1715
1661 } else { 1716 for (doy = tmp_start_doy; doy <= end_year_day; doy += 7)
1662 pvl_push(days_list,(void*)(int)doy); 1717 pvl_push(days_list,(void*)(int)doy);
1663 } 1718
1664 }
1665 } else if ( pos > 0) { 1719 } else if ( pos > 0) {
@@ -1673,3 +1727,3 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1673 1727
1674 /* THen just multiple the position times 7 to get the pos'th day in the year */ 1728 /* Then just multiple the position times 7 to get the pos'th day in the year */
1675 pvl_push(days_list,(void*)(first+ (pos-1) * 7)); 1729 pvl_push(days_list,(void*)(first+ (pos-1) * 7));
@@ -1698,3 +1752,3 @@ pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
1698 1752
1699int expand_year_days(struct icalrecur_iterator_impl* impl,short year) 1753static int expand_year_days(icalrecur_iterator* impl, int year)
1700{ 1754{
@@ -1705,3 +1759,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1705 1759
1706 t = icaltime_null_time(); 1760 t = icaltime_null_date();
1707 1761
@@ -1709,7 +1763,8 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1709 1763
1710 t.is_date = 1; /* Needed to make day_of_year routines work property */
1711
1712 memset(&t,0,sizeof(t));
1713 memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days)); 1764 memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days));
1714 1765
1766 /* The flags and the following switch statement select which code
1767 to use to expand the yers days, based on which BY-rules are
1768 present. */
1769
1715 flags = (HBD(BY_DAY) ? 1<<BY_DAY : 0) + 1770 flags = (HBD(BY_DAY) ? 1<<BY_DAY : 0) +
@@ -1725,3 +1780,7 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1725 /* FREQ=YEARLY; */ 1780 /* FREQ=YEARLY; */
1781 t = impl->dtstart;
1782 t.year = impl->last.year;
1726 1783
1784 impl->days[days_index++] = (short)icaltime_day_of_year(t);
1785
1727 break; 1786 break;
@@ -1732,5 +1791,4 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1732 for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ 1791 for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
1733 struct icaltimetype t; 1792 int month = impl->by_ptrs[BY_MONTH][j];
1734 short month = impl->by_ptrs[BY_MONTH][j]; 1793 int doy;
1735 short doy;
1736 1794
@@ -1743,3 +1801,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1743 1801
1744 impl->days[days_index++] = doy; 1802 impl->days[days_index++] = (short)doy;
1745 1803
@@ -1753,4 +1811,4 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1753 { 1811 {
1754 short month_day = impl->by_ptrs[BY_MONTH_DAY][k]; 1812 int month_day = impl->by_ptrs[BY_MONTH_DAY][k];
1755 short doy; 1813 int doy;
1756 1814
@@ -1763,3 +1821,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1763 1821
1764 impl->days[days_index++] = doy; 1822 impl->days[days_index++] = (short)doy;
1765 1823
@@ -1775,5 +1833,5 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1775 { 1833 {
1776 short month = impl->by_ptrs[BY_MONTH][j]; 1834 int month = impl->by_ptrs[BY_MONTH][j];
1777 short month_day = impl->by_ptrs[BY_MONTH_DAY][k]; 1835 int month_day = impl->by_ptrs[BY_MONTH_DAY][k];
1778 short doy; 1836 int doy;
1779 1837
@@ -1786,3 +1844,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1786 1844
1787 impl->days[days_index++] = doy; 1845 impl->days[days_index++] = (short)doy;
1788 1846
@@ -1797,4 +1855,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1797 1855
1798 struct icaltimetype t; 1856 int dow;
1799 short dow;
1800 1857
@@ -1821,3 +1878,2 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1821 /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/ 1878 /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/
1822 int days_index = 0;
1823 pvl_elem i; 1879 pvl_elem i;
@@ -1827,3 +1883,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1827 for(i=pvl_head(days);i!=0;i=pvl_next(i)){ 1883 for(i=pvl_head(days);i!=0;i=pvl_next(i)){
1828 short day = (short)(int)pvl_data(i); 1884 short day = (short)(*((int*)pvl_data(i)));
1829 impl->days[days_index++] = day; 1885 impl->days[days_index++] = day;
@@ -1839,27 +1895,55 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1839 1895
1840 int days_index = 0;
1841 pvl_elem itr;
1842 pvl_list days = expand_by_day(impl,year);
1843 1896
1844 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ 1897 for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
1845 short doy = (short)(int)pvl_data(itr); 1898 int month = impl->by_ptrs[BY_MONTH][j];
1846 struct icaltimetype tt; 1899 int days_in_month = icaltime_days_in_month(month,year);
1847 short j; 1900 int first_dow, last_dow, doy_offset;
1848 1901
1849 tt = icaltime_from_day_of_year(doy,year); 1902 t.year = year;
1903 t.month = month;
1904 t.day = 1;
1905 t.is_date = 1;
1850 1906
1851 for(j=0; 1907 first_dow = icaltime_day_of_week(t);
1852 impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;
1853 j++){
1854 short month = impl->by_ptrs[BY_MONTH][j];
1855 1908
1856 if(tt.month == month){ 1909 /* This holds the day offset used to calculate the day of the year
1857 impl->days[days_index++] = doy; 1910 from the month day. Just add the month day to this. */
1858 } 1911 doy_offset = icaltime_day_of_year(t) - 1;
1859 }
1860 1912
1861 } 1913 t.day = days_in_month;
1914 last_dow = icaltime_day_of_week(t);
1862 1915
1863 pvl_free(days); 1916 for(k=0;impl->by_ptrs[BY_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++){
1917 short day_coded = impl->by_ptrs[BY_DAY][k];
1918 enum icalrecurrencetype_weekday dow =
1919 icalrecurrencetype_day_day_of_week(day_coded);
1920 int pos = icalrecurrencetype_day_position(day_coded);
1921 int first_matching_day, last_matching_day, day, month_day;
1922
1923 /* Calculate the first day in the month with the given weekday,
1924 and the last day. */
1925 first_matching_day = ((dow + 7 - first_dow) % 7) + 1;
1926 last_matching_day = days_in_month - ((last_dow + 7 - dow) % 7);
1927
1928 if (pos == 0) {
1929 /* Add all of instances of the weekday within the month. */
1930 for (day = first_matching_day; day <= days_in_month; day += 7)
1931 impl->days[days_index++] = (short)(doy_offset + day);
1932
1933 } else if (pos > 0) {
1934 /* Add the nth instance of the weekday within the month. */
1935 month_day = first_matching_day + (pos - 1) * 7;
1936
1937 if (month_day <= days_in_month)
1938 impl->days[days_index++] = (short)(doy_offset + month_day);
1864 1939
1940 } else {
1941 /* Add the -nth instance of the weekday within the month.*/
1942 month_day = last_matching_day + (pos + 1) * 7;
1943
1944 if (month_day > 0)
1945 impl->days[days_index++] = (short)(doy_offset + month_day);
1946 }
1947 }
1948 }
1865 break; 1949 break;
@@ -1870,3 +1954,2 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1870 1954
1871 int days_index = 0;
1872 pvl_elem itr; 1955 pvl_elem itr;
@@ -1875,5 +1958,4 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1875 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ 1958 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
1876 short day = (short)(int)pvl_data(itr); 1959 short day = (short)(*((int*)pvl_data(itr)));
1877 struct icaltimetype tt; 1960 struct icaltimetype tt;
1878 short j;
1879 1961
@@ -1882,3 +1964,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1882 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ 1964 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
1883 short mday = BYMDPTR[j]; 1965 int mday = BYMDPTR[j];
1884 1966
@@ -1899,3 +1981,2 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1899 1981
1900 int days_index = 0;
1901 pvl_elem itr; 1982 pvl_elem itr;
@@ -1904,5 +1985,5 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1904 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ 1985 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
1905 short day = (short)(int)pvl_data(itr); 1986 short day = (short)(*((int*)pvl_data(itr)));
1906 struct icaltimetype tt; 1987 struct icaltimetype tt;
1907 short i,j; 1988 int i;
1908 1989
@@ -1912,4 +1993,4 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1912 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ 1993 for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
1913 short mday = BYMDPTR[j]; 1994 int mday = BYMDPTR[j];
1914 short month = BYMONPTR[i]; 1995 int month = BYMONPTR[i];
1915 1996
@@ -1932,3 +2013,2 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1932 2013
1933 int days_index = 0;
1934 pvl_elem itr; 2014 pvl_elem itr;
@@ -1937,5 +2017,5 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1937 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ 2017 for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
1938 short day = (short)(int)pvl_data(itr); 2018 short day = (short)(*((int*)pvl_data(itr)));
1939 struct icaltimetype tt; 2019 struct icaltimetype tt;
1940 short i; 2020 int i;
1941 2021
@@ -1944,5 +2024,5 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1944 for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){ 2024 for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
1945 short weekno = BYWEEKPTR[i]; 2025 int weekno = BYWEEKPTR[i];
1946 2026 int this_weekno = icaltime_week_number(tt);
1947 if(weekno== icaltime_week_number(tt)){ 2027 if(weekno== this_weekno){
1948 impl->days[days_index++] = day; 2028 impl->days[days_index++] = day;
@@ -1965,4 +2045,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1965 for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ 2045 for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
1966 short doy = impl->by_ptrs[BY_YEAR_DAY][j]; 2046 impl->days[days_index++] = impl->by_ptrs[BY_YEAR_DAY][j];
1967 impl->days[days_index++] = doy;
1968 } 2047 }
@@ -1982,3 +2061,3 @@ int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
1982 2061
1983int next_year(struct icalrecur_iterator_impl* impl) 2062static int next_year(icalrecur_iterator* impl)
1984{ 2063{
@@ -1986,5 +2065,4 @@ int next_year(struct icalrecur_iterator_impl* impl)
1986 2065
1987 /* Next_year does it's own interatio in days, so the next level down is hours */
1988 if (next_hour(impl) == 0){ 2066 if (next_hour(impl) == 0){
1989 return 1; 2067 return 0;
1990 } 2068 }
@@ -1993,11 +2071,12 @@ int next_year(struct icalrecur_iterator_impl* impl)
1993 impl->days_index = 0; 2071 impl->days_index = 0;
2072
2073 for (;;) {
1994 increment_year(impl,impl->rule.interval); 2074 increment_year(impl,impl->rule.interval);
1995 expand_year_days(impl,impl->last.year); 2075 expand_year_days(impl,impl->last.year);
2076 if (impl->days[0] != ICAL_RECURRENCE_ARRAY_MAX)
2077 break;
1996 } 2078 }
1997
1998 if(impl->days[0] == ICAL_RECURRENCE_ARRAY_MAX) {
1999 return 0;
2000 } 2079 }
2001 2080
2002 next = icaltime_from_day_of_year(impl->days[impl->days_index],impl->last.year); 2081 next = icaltime_from_day_of_year(impl->days[impl->days_index], impl->last.year);
2003 2082
@@ -2009,4 +2088,4 @@ int next_year(struct icalrecur_iterator_impl* impl)
2009 2088
2010int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl, 2089int icalrecur_check_rulepart(icalrecur_iterator* impl,
2011 short v, enum byrule byrule) 2090 int v, enum byrule byrule)
2012{ 2091{
@@ -2025,4 +2104,4 @@ int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl,
2025 2104
2026int check_contract_restriction(struct icalrecur_iterator_impl* impl, 2105static int check_contract_restriction(icalrecur_iterator* impl,
2027 enum byrule byrule, short v) 2106 enum byrule byrule, int v)
2028{ 2107{
@@ -2050,18 +2129,18 @@ int check_contract_restriction(struct icalrecur_iterator_impl* impl,
2050 2129
2051int check_contracting_rules(struct icalrecur_iterator_impl* impl) 2130static int check_contracting_rules(icalrecur_iterator* impl)
2052{ 2131{
2053 2132
2054 int day_of_week=0; 2133 int day_of_week = icaltime_day_of_week(impl->last);
2055 int week_no=0; 2134 int week_no = icaltime_week_number(impl->last);
2056 int year_day=0; 2135 int year_day = icaltime_day_of_year(impl->last);
2057 2136
2058 if ( 2137 if (
2059 check_contract_restriction(impl,BY_SECOND,impl->last.second) && 2138 check_contract_restriction(impl,BY_SECOND, impl->last.second) &&
2060 check_contract_restriction(impl,BY_MINUTE,impl->last.minute) && 2139 check_contract_restriction(impl,BY_MINUTE, impl->last.minute) &&
2061 check_contract_restriction(impl,BY_HOUR,impl->last.hour) && 2140 check_contract_restriction(impl,BY_HOUR, impl->last.hour) &&
2062 check_contract_restriction(impl,BY_DAY,day_of_week) && 2141 check_contract_restriction(impl,BY_DAY, day_of_week) &&
2063 check_contract_restriction(impl,BY_WEEK_NO,week_no) && 2142 check_contract_restriction(impl,BY_WEEK_NO, week_no) &&
2064 check_contract_restriction(impl,BY_MONTH_DAY,impl->last.day) && 2143 check_contract_restriction(impl,BY_MONTH_DAY, impl->last.day) &&
2065 check_contract_restriction(impl,BY_MONTH,impl->last.month) && 2144 check_contract_restriction(impl,BY_MONTH, impl->last.month) &&
2066 check_contract_restriction(impl,BY_YEAR_DAY,year_day) ) 2145 check_contract_restriction(impl,BY_YEAR_DAY, year_day) )
2067 { 2146 {
@@ -2074,7 +2153,5 @@ int check_contracting_rules(struct icalrecur_iterator_impl* impl)
2074 2153
2075struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr) 2154struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *impl)
2076{ 2155{
2077 int valid = 1; 2156 int valid = 1;
2078 struct icalrecur_iterator_impl* impl =
2079 (struct icalrecur_iterator_impl*)itr;
2080 2157
@@ -2122,3 +2199,3 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
2122 case ICAL_YEARLY_RECURRENCE:{ 2199 case ICAL_YEARLY_RECURRENCE:{
2123 valid = next_year(impl); 2200 next_year(impl);
2124 break; 2201 break;
@@ -2137,3 +2214,3 @@ struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
2137 } while(!check_contracting_rules(impl) 2214 } while(!check_contracting_rules(impl)
2138 || icaltime_compare(impl->last,impl->dtstart) <= 0 2215 || icaltime_compare(impl->last,impl->dtstart) < 0
2139 || valid == 0); 2216 || valid == 0);
@@ -2168,12 +2245,11 @@ void icalrecurrencetype_clear(struct icalrecurrencetype *recur)
2168 2245
2169/* The 'day' element of icalrecurrencetype_weekday is encoded to allow 2246/** The 'day' element of icalrecurrencetype_weekday is encoded to
2170reporesentation of both the day of the week ( Monday, Tueday), but 2247 * allow representation of both the day of the week ( Monday, Tueday),
2171also the Nth day of the week ( First tuesday of the month, last 2248 * but also the Nth day of the week ( First tuesday of the month, last
2172thursday of the year) These routines decode the day values. 2249 * thursday of the year) These routines decode the day values.
2173 2250 *
2174The day's position in the period ( Nth-ness) and the numerical value 2251 * The day's position in the period ( Nth-ness) and the numerical
2175of the day are encoded together as: pos*7 + dow 2252 * value of the day are encoded together as: pos*7 + dow
2176 2253 *
2177A position of 0 means 'any' or 'every' 2254 * A position of 0 means 'any' or 'every'
2178
2179 */ 2255 */
@@ -2185,5 +2261,5 @@ enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day)
2185 2261
2186short icalrecurrencetype_day_position(short day) 2262int icalrecurrencetype_day_position(short day)
2187{ 2263{
2188 short wd, pos; 2264 int wd, pos;
2189 2265
@@ -2200,3 +2276,3 @@ short icalrecurrencetype_day_position(short day)
2200 2276
2201struct {icalrecurrencetype_weekday wd; const char * str; } 2277static struct {icalrecurrencetype_weekday wd; const char * str; }
2202wd_map[] = { 2278wd_map[] = {
@@ -2240,3 +2316,3 @@ icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str)
2240 2316
2241struct { 2317static struct {
2242 icalrecurrencetype_frequency kind; 2318 icalrecurrencetype_frequency kind;
@@ -2278,6 +2354,7 @@ icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str)
2278 2354
2279/* Fill an array with the 'count' number of occurrences generated by 2355/** Fill an array with the 'count' number of occurrences generated by
2280 the rrule. Note that the times are returned in UTC, but the times 2356 * the rrule. Note that the times are returned in UTC, but the times
2281 are calculated in local time. YOu will have to convert the results 2357 * are calculated in local time. YOu will have to convert the results
2282 back into local time before using them. */ 2358 * back into local time before using them.
2359 */
2283 2360
@@ -2294,3 +2371,3 @@ int icalrecur_expand_recurrence(char* rule, time_t start,
2294 2371
2295 icstart = icaltime_from_timet(start,0); 2372 icstart = icaltime_from_timet_with_zone(start,0,0);
2296 2373