propagate from branch 'ca.inverse.sogo.1_3_15' (head cd39fe0df424d1e5afd5dcfa4b1c94ad707fed24)

to branch 'ca.inverse.sogo' (head 94d7b980dccff8cbae9bff2eaee5dbefc75a7dfd)

Monotone-Parent: 94d7b980dccff8cbae9bff2eaee5dbefc75a7dfd
Monotone-Parent: cd39fe0df424d1e5afd5dcfa4b1c94ad707fed24
Monotone-Revision: 6331064cc925005acad759e8c6eac99b6b7071cd

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2012-04-23T21:19:11
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2012-04-23 21:19:11 +00:00
commit 306f999901
5 changed files with 117 additions and 73 deletions

View File

@ -1,3 +1,10 @@
2012-04-23 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* iCalMonthlyRecurrenceCalculator.m (NGMonthDaySet_clear): make
use of memset, which is expected to be faster.
(-recurrenceRangesWithinCalendarDateRange:): added handling of
"BYSETPOS" for "BYDAY" sets.
2012-04-20 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2012-04-20 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* iCalTrigger.m (-nextAlarmDate): new method including most of * iCalTrigger.m (-nextAlarmDate): new method including most of

View File

@ -21,6 +21,7 @@
02111-1307, USA. 02111-1307, USA.
*/ */
#import <Foundation/NSString.h>
#import <NGExtensions/NSCalendarDate+misc.h> #import <NGExtensions/NSCalendarDate+misc.h>
#import "iCalRecurrenceCalculator.h" #import "iCalRecurrenceCalculator.h"
@ -34,7 +35,6 @@
#import "NSCalendarDate+ICal.h" #import "NSCalendarDate+ICal.h"
#import <string.h> #import <string.h>
#import <math.h>
@interface iCalRecurrenceCalculator (PrivateAPI) @interface iCalRecurrenceCalculator (PrivateAPI)
@ -49,14 +49,11 @@
typedef BOOL NGMonthSet[12]; typedef BOOL NGMonthSet[12];
typedef BOOL NGMonthDaySet[32]; // 0 is unused typedef BOOL NGMonthDaySet[32]; // 0 is unused
static void static inline void
NGMonthDaySet_clear (NGMonthDaySet *daySet) NGMonthDaySet_clear (NGMonthDaySet *daySet)
{ {
register unsigned i; memset (daySet, 0, sizeof (NGMonthDaySet));
for (i = 0; i <= 31; i++)
(*daySet)[i] = NO;
} }
static void static void
@ -201,7 +198,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
YES, YES, YES, YES, YES, YES, YES, YES, YES, YES, YES, YES,
YES, YES, YES, YES, YES, YES YES, YES, YES, YES, YES, YES
}; };
NSArray *byMonth, *byMonthDay; // array of ints (-31..-1 and 1..31) NSArray *byMonth, *byMonthDay, *bySetPos; // array of ints (-31..-1 and 1..31)
NGMonthDaySet byPositiveMonthDaySet, byNegativeMonthDaySet; NGMonthDaySet byPositiveMonthDaySet, byNegativeMonthDaySet;
iCalByDayMask *byDayMask; iCalByDayMask *byDayMask;
@ -216,6 +213,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
byMonth = [rrule byMonth]; byMonth = [rrule byMonth];
byMonthDay = [rrule byMonthDay]; byMonthDay = [rrule byMonthDay];
byDayMask = [rrule byDayMask]; byDayMask = [rrule byDayMask];
bySetPos = [rrule bySetPos];
diff = 0; diff = 0;
if (![rrule isInfinite]) if (![rrule isInfinite])
@ -239,7 +237,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
if ([until compare: rStart] == NSOrderedAscending) if ([until compare: rStart] == NSOrderedAscending)
// Range starts after last occurrence // Range starts after last occurrence
return nil; return nil;
if ([until compare: rEnd] == NSOrderedDescending) if ([until compare: rEnd] == NSOrderedAscending)
// Range ends after last occurence; adjust end date // Range ends after last occurence; adjust end date
rEnd = until; rEnd = until;
} }
@ -334,43 +332,81 @@ static inline unsigned iCalDoWForNSDoW (int dow)
if (byDayMask) if (byDayMask)
{ {
unsigned int firstDoWInMonth, currentWeekDay; if (!didByFill)
unsigned int weekDaysCount[7], currentWeekDaysCount[7]; NGMonthDaySet_clear (&monthDays);
int i, positiveOrder, negativeOrder;
firstDoWInMonth = [[cursor firstDayOfMonth] dayOfWeek]; if (bySetPos)
{
NSUInteger monthDay;
NSInteger currentPos;
iCalWeekDay currentWeekDay;
if (!didByFill) currentWeekDay = [[cursor firstDayOfMonth] dayOfWeek];
NGMonthDaySet_clear (&monthDays); currentPos = 1;
for (monthDay = 0; monthDay <= numDaysInMonth; monthDay++)
{
if ([byDayMask occursOnDay: currentWeekDay])
{
if ([bySetPos containsObject:
[NSString stringWithFormat: @"%d", currentPos]])
monthDays[monthDay+1] = YES;
currentPos++;
}
currentWeekDay = (currentWeekDay + 1) % 7;
}
// Fill weekDaysCount to handle negative positions currentWeekDay = [[cursor lastDayOfMonth] dayOfWeek];
currentWeekDay = firstDoWInMonth; currentPos = -1;
memset(weekDaysCount, 0, 7 * sizeof(unsigned int)); for (monthDay = numDaysInMonth; monthDay > 0; monthDay--)
for (i = 1; i <= numDaysInMonth; i++) {
{ if ([byDayMask occursOnDay: currentWeekDay])
weekDaysCount[currentWeekDay]++; {
currentWeekDay++; if ([bySetPos containsObject:
currentWeekDay = fmod (currentWeekDay, 7); [NSString stringWithFormat: @"%d", currentPos]])
} monthDays[monthDay] = YES;
currentPos--;
}
if (currentWeekDay > 0)
currentWeekDay--;
else
currentWeekDay = 6;
}
}
else
{
unsigned int firstDoWInMonth, currentWeekDay;
unsigned int weekDaysCount[7], currentWeekDaysCount[7];
int i, positiveOrder, negativeOrder;
currentWeekDay = firstDoWInMonth; firstDoWInMonth = [[cursor firstDayOfMonth] dayOfWeek];
memset(currentWeekDaysCount, 0, 7 * sizeof(unsigned int));
for (i = 1; i <= numDaysInMonth; i++) // Fill weekDaysCount to handle negative positions
{ currentWeekDay = firstDoWInMonth;
if (!didByFill || monthDays[i]) memset(weekDaysCount, 0, 7 * sizeof(unsigned int));
{ for (i = 1; i <= numDaysInMonth; i++)
positiveOrder = currentWeekDaysCount[currentWeekDay] + 1; {
negativeOrder = currentWeekDaysCount[currentWeekDay] - weekDaysCount[currentWeekDay]; weekDaysCount[currentWeekDay]++;
monthDays[i] = (([byDayMask occursOnDay: (iCalWeekDay)currentWeekDay currentWeekDay = (currentWeekDay + 1) % 7;
withWeekNumber: positiveOrder]) || }
([byDayMask occursOnDay: (iCalWeekDay)currentWeekDay
withWeekNumber: negativeOrder])); currentWeekDay = firstDoWInMonth;
} memset(currentWeekDaysCount, 0, 7 * sizeof(unsigned int));
currentWeekDaysCount[currentWeekDay]++; for (i = 1; i <= numDaysInMonth; i++)
currentWeekDay++; {
currentWeekDay = fmod (currentWeekDay, 7); if (!didByFill || monthDays[i])
} {
didByFill = YES; positiveOrder = currentWeekDaysCount[currentWeekDay] + 1;
negativeOrder = currentWeekDaysCount[currentWeekDay] - weekDaysCount[currentWeekDay];
monthDays[i] = (([byDayMask occursOnDay: (iCalWeekDay)currentWeekDay
withWeekNumber: positiveOrder]) ||
([byDayMask occursOnDay: (iCalWeekDay)currentWeekDay
withWeekNumber: negativeOrder]));
}
currentWeekDaysCount[currentWeekDay]++;
currentWeekDay = (currentWeekDay + 1) % 7;
}
}
didByFill = YES;
} }
if (didByFill) if (didByFill)

View File

@ -92,6 +92,8 @@ extern NSString *iCalWeekDayString[];
- (NSArray *) byMonth; - (NSArray *) byMonth;
- (BOOL) hasByMask; - (BOOL) hasByMask;
- (NSArray *) bySetPos;
/* count and untilDate are mutually exclusive */ /* count and untilDate are mutually exclusive */
- (void) setRepeatCount: (int) _repeatCount; - (void) setRepeatCount: (int) _repeatCount;

View File

@ -183,6 +183,7 @@
*/ */
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h> #import <Foundation/NSEnumerator.h>
#import <Foundation/NSException.h> #import <Foundation/NSException.h>
#import <NGExtensions/NSString+Ext.h> #import <NGExtensions/NSString+Ext.h>
@ -583,6 +584,19 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
} }
} }
- (NSArray *) bySetPos
{
NSArray *lists, *bySetPos;
lists = [self valuesForKey: @"bysetpos"];
if ([lists count] > 0)
bySetPos = [lists objectAtIndex: 0];
else
bySetPos = nil;
return bySetPos;
}
// - (iCalWeekDay) weekDayForiCalRepre: (NSString *) _weekDay // - (iCalWeekDay) weekDayForiCalRepre: (NSString *) _weekDay
// { // {
// iCalWeekDay day; // iCalWeekDay day;

View File

@ -90,7 +90,6 @@
startDate = [[currentRule objectAtIndex: 0] asCalendarDate]; startDate = [[currentRule objectAtIndex: 0] asCalendarDate];
endDate = [startDate dateByAddingYears: 0 months: 0 days: 0 hours: 1 minutes: 0 seconds: 0]; endDate = [startDate dateByAddingYears: 0 months: 0 days: 0 hours: 1 minutes: 0 seconds: 0];
recurrenceRule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation: [currentRule objectAtIndex: 1]]; recurrenceRule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation: [currentRule objectAtIndex: 1]];
// NSLog(@"%@: %@", startDate, recurrenceRule);
firRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate firRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
endDate: endDate]; endDate: endDate];
@ -107,22 +106,12 @@
[[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat], [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat],
[currentOccurrence descriptionWithCalendarFormat: dateFormat]]; [currentOccurrence descriptionWithCalendarFormat: dateFormat]];
testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error); testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error);
// if ([currentOccurrence compare: [[occurrences objectAtIndex: j] startDate]] != NSOrderedSame)
// NSLog(@"Expected: %@ Obtained: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
// else
// NSLog(@" %@ Matched: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
} }
error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)", error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)",
[currentRule objectAtIndex: 1], [currentRule objectAtIndex: 1],
[occurrences count], [occurrences count],
[currentRule count] - 2]; [currentRule count] - 2];
testWithMessage([currentRule count] - [occurrences count] == 2, error); testWithMessage([currentRule count] - [occurrences count] == 2, error);
// for (; i < [currentRule count]; i++)
// NSLog(@"Expected additional date : %@", [[currentRule objectAtIndex: i] asCalendarDate]);
// for (; j < [occurrences count]; j++)
// NSLog(@"Found additional date : %@", [[occurrences objectAtIndex: j] startDate]);
} }
} }
@ -169,6 +158,23 @@
@"19980129T090000Z", @"19980129T090000Z",
@"19980226T090000Z", @"19980226T090000Z",
nil], nil],
// Second friday of the month, until Feb 26 1998
[NSArray arrayWithObjects: @"19980101T090000Z",
@"FREQ=MONTHLY;BYDAY=FR;BYSETPOS=2;UNTIL=19980428T090000Z",
@"19980101T090000Z",
@"19980109T090000Z",
@"19980213T090000Z",
@"19980313T090000Z",
@"19980410fT090000Z",
nil],
// Last friday of the month, until Feb 26 1998
[NSArray arrayWithObjects: @"19980101T090000Z",
@"FREQ=MONTHLY;BYDAY=MO,WE;BYSETPOS=-2;UNTIL=19980331T090000Z",
@"19980101T090000Z",
@"19980126T090000Z",
@"19980223T090000Z",
@"19980325T090000Z",
nil],
nil]; nil];
NSString *dateFormat = @"%a %Y-%m-%d %H:%M"; NSString *dateFormat = @"%a %Y-%m-%d %H:%M";
@ -204,22 +210,12 @@
[[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat], [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat],
[currentOccurrence descriptionWithCalendarFormat: dateFormat]]; [currentOccurrence descriptionWithCalendarFormat: dateFormat]];
testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error); testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error);
// if ([currentOccurrence compare: [[occurrences objectAtIndex: j] startDate]] != NSOrderedSame)
// NSLog(@"Expected: %@ Obtained: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
// else
// NSLog(@" %@ Matched: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
} }
error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)", error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)",
[currentRule objectAtIndex: 1], [currentRule objectAtIndex: 1],
[occurrences count], [occurrences count],
[currentRule count] - 2]; [currentRule count] - 2];
testWithMessage([currentRule count] - [occurrences count] == 2, error); testWithMessage([currentRule count] - [occurrences count] == 2, error);
// for (; i < [currentRule count]; i++)
// NSLog(@"Expected additional date : %@", [[currentRule objectAtIndex: i] asCalendarDate]);
// for (; j < [occurrences count]; j++)
// NSLog(@"Found additional date : %@", [[occurrences objectAtIndex: j] startDate]);
} }
} }
@ -363,7 +359,6 @@
startDate = [[currentRule objectAtIndex: 0] asCalendarDate]; startDate = [[currentRule objectAtIndex: 0] asCalendarDate];
endDate = [startDate dateByAddingYears: 0 months: 0 days: 0 hours: 1 minutes: 0 seconds: 0]; endDate = [startDate dateByAddingYears: 0 months: 0 days: 0 hours: 1 minutes: 0 seconds: 0];
recurrenceRule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation: [currentRule objectAtIndex: 1]]; recurrenceRule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation: [currentRule objectAtIndex: 1]];
// NSLog(@"%@: %@", startDate, recurrenceRule);
firRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate firRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
endDate: endDate]; endDate: endDate];
@ -380,22 +375,12 @@
[[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat], [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat],
[currentOccurrence descriptionWithCalendarFormat: dateFormat]]; [currentOccurrence descriptionWithCalendarFormat: dateFormat]];
testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error); testWithMessage([currentOccurrence isDateOnSameDay: [[occurrences objectAtIndex: j] startDate]], error);
// if ([currentOccurrence compare: [[occurrences objectAtIndex: j] startDate]] != NSOrderedSame)
// NSLog(@"Expected: %@ Obtained: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
// else
// NSLog(@" %@ Matched: %@", [currentOccurrence descriptionWithCalendarFormat: dateFormat],
// [[[occurrences objectAtIndex: j] startDate] descriptionWithCalendarFormat: dateFormat]);
} }
error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)", error = [NSString stringWithFormat: @"Unexpected number of occurrences for recurrence rule %@ (found %i, expected %i)",
[currentRule objectAtIndex: 1], [currentRule objectAtIndex: 1],
[occurrences count], [occurrences count],
[currentRule count] - 2]; [currentRule count] - 2];
testWithMessage([currentRule count] - [occurrences count] == 2, error); testWithMessage([currentRule count] - [occurrences count] == 2, error);
// for (; i < [currentRule count]; i++)
// NSLog(@"Expected additional date : %@", [[currentRule objectAtIndex: i] asCalendarDate]);
// for (; j < [occurrences count]; j++)
// NSLog(@"Found additional date : %@", [[occurrences objectAtIndex: j] startDate]);
} }
} }