#include "common.h"
/*
- freq = rrFreq;
- until = rrUntil;
- count = rrCount;
- interval = rrInterval;
- bysecond = rrBySecondList;
- byminute = rrByMinuteList;
- byhour = rrByHourList;
- byday = rrByDayList;
- bymonthday = rrByMonthDayList;
- byyearday = rrByYearDayList;
- byweekno = rrByWeekNumberList;
- bymonth = rrByMonthList;
- bysetpos = rrBySetPosList;
- wkst = rrWeekStart;
- */
+ freq = rrFreq;
+ until = rrUntil;
+ count = rrCount;
+ interval = rrInterval;
+ bysecond = rrBySecondList;
+ byminute = rrByMinuteList;
+ byhour = rrByHourList;
+ byday = rrByDayList;
+ bymonthday = rrByMonthDayList;
+ byyearday = rrByYearDayList;
+ byweekno = rrByWeekNumberList;
+ bymonth = rrByMonthList;
+ bysetpos = rrBySetPosList;
+ wkst = rrWeekStart;
+*/
+// TODO: private API in the header file?!
@interface iCalRecurrenceRule (PrivateAPI)
+
- (iCalWeekDay)weekDayFromICalRepresentation:(NSString *)_day;
- (NSString *)iCalRepresentationForWeekDay:(iCalWeekDay)_weekDay;
- (NSString *)freq;
- (NSString *)byDayList;
- (void)_processRule;
-- (void)setRrule:(NSString *)_rrule;
+- (void)setRrule:(NSString *)_rrule; // TODO: weird name?
+
@end
@implementation iCalRecurrenceRule
-+ (void)initialize {
- static BOOL didInit = NO;
-
- if (didInit) return;
- didInit = YES;
-}
-
+ (id)recurrenceRuleWithICalRepresentation:(NSString *)_iCalRep {
- iCalRecurrenceRule *r;
-
- r = [[[self alloc] init] autorelease];
- [r setRrule:_iCalRep];
- return r;
+ return [[[self alloc] initWithString:_iCalRep] autorelease];
}
-- (id)init {
- self = [super init];
- if (self) {
+- (id)init { /* designated initializer */
+ if ((self = [super init]) != nil) {
self->byDay.weekStart = iCalWeekDayMonday;
self->interval = 1;
}
return self;
}
+- (id)initWithString:(NSString *)_str {
+ if ((self = [self init]) != nil) {
+ [self setRrule:_str];
+ }
+ return self;
+}
+
- (void)dealloc {
[self->untilDate release];
[self->rrule release];
}
-/* Accessors */
+/* accessors */
- (void)setFrequency:(iCalRecurrenceFrequency)_frequency {
self->frequency = _frequency;
}
-/* Private */
+/* private */
- (iCalWeekDay)weekDayFromICalRepresentation:(NSString *)_day {
- _day = [_day uppercaseString];
- if ([_day isEqualToString:@"MO"])
- return iCalWeekDayMonday;
- else if ([_day isEqualToString:@"TU"])
- return iCalWeekDayTuesday;
- else if ([_day isEqualToString:@"WE"])
- return iCalWeekDayWednesday;
- else if ([_day isEqualToString:@"TH"])
- return iCalWeekDayThursday;
- else if ([_day isEqualToString:@"FR"])
- return iCalWeekDayFriday;
- else if ([_day isEqualToString:@"SA"])
- return iCalWeekDaySaturday;
- else if ([_day isEqualToString:@"SU"])
- return iCalWeekDaySunday;
- else
- [NSException raise:NSGenericException
- format:@"Incorrect weekDay '%@' specified!", _day];
+ if ([_day length] > 1) {
+ /* be tolerant */
+ unichar c0, c1;
+
+ c0 = [_day characterAtIndex:0];
+ if (c0 == 'm' || c0 == 'M') return iCalWeekDayMonday;
+ if (c0 == 'w' || c0 == 'W') return iCalWeekDayWednesday;
+ if (c0 == 'f' || c0 == 'F') return iCalWeekDayFriday;
+
+ c1 = [_day characterAtIndex:1];
+ if (c0 == 't' || c0 == 't') {
+ if (c1 == 'u' || c1 == 'U') return iCalWeekDayTuesday;
+ if (c1 == 'h' || c1 == 'H') return iCalWeekDayThursday;
+ }
+ if (c0 == 's' || c0 == 'S') {
+ if (c1 == 'a' || c1 == 'A') return iCalWeekDaySaturday;
+ if (c1 == 'u' || c1 == 'U') return iCalWeekDaySunday;
+ }
+ }
+
+ // TODO: do not raise but rather return an error value?
+ [NSException raise:NSGenericException
+ format:@"Incorrect weekDay '%@' specified!", _day];
return iCalWeekDayMonday; /* keep compiler happy */
}
- (NSString *)iCalRepresentationForWeekDay:(iCalWeekDay)_weekDay {
switch (_weekDay) {
- case iCalWeekDayMonday:
- return @"MO";
- case iCalWeekDayTuesday:
- return @"TU";
- case iCalWeekDayWednesday:
- return @"WE";
- case iCalWeekDayThursday:
- return @"TH";
- case iCalWeekDayFriday:
- return @"FR";
- case iCalWeekDaySaturday:
- return @"SA";
- case iCalWeekDaySunday:
- return @"SU";
- default:
- return @"MO";
+ case iCalWeekDayMonday: return @"MO";
+ case iCalWeekDayTuesday: return @"TU";
+ case iCalWeekDayWednesday: return @"WE";
+ case iCalWeekDayThursday: return @"TH";
+ case iCalWeekDayFriday: return @"FR";
+ case iCalWeekDaySaturday: return @"SA";
+ case iCalWeekDaySunday: return @"SU";
+ default: return @"MO"; // TODO: return error?
}
}
- (NSString *)freq {
switch (self->frequency) {
- case iCalRecurrenceFrequenceWeekly:
- return @"WEEKLY";
- case iCalRecurrenceFrequenceMonthly:
- return @"MONTHLY";
- case iCalRecurrenceFrequenceDaily:
- return @"DAILY";
- case iCalRecurrenceFrequenceYearly:
- return @"YEARLY";
- case iCalRecurrenceFrequenceHourly:
- return @"HOURLY";
- case iCalRecurrenceFrequenceMinutely:
- return @"MINUTELY";
- case iCalRecurrenceFrequenceSecondly:
- return @"SECONDLY";
+ case iCalRecurrenceFrequenceWeekly: return @"WEEKLY";
+ case iCalRecurrenceFrequenceMonthly: return @"MONTHLY";
+ case iCalRecurrenceFrequenceDaily: return @"DAILY";
+ case iCalRecurrenceFrequenceYearly: return @"YEARLY";
+ case iCalRecurrenceFrequenceHourly: return @"HOURLY";
+ case iCalRecurrenceFrequenceMinutely: return @"MINUTELY";
+ case iCalRecurrenceFrequenceSecondly: return @"SECONDLY";
default:
return @"UNDEFINED?";
}
}
/*
- TODO:
- Each BYDAY value can also be preceded by a positive (+n) or negative
- (-n) integer. If present, this indicates the nth occurrence of the
- specific day within the MONTHLY or YEARLY RRULE. For example, within
- a MONTHLY rule, +1MO (or simply 1MO) represents the first Monday
- within the month, whereas -1MO represents the last Monday of the
- month. If an integer modifier is not present, it means all days of
- this type within the specified frequency. For example, within a
- MONTHLY rule, MO represents all Mondays within the month.
+ TODO:
+ Each BYDAY value can also be preceded by a positive (+n) or negative
+ (-n) integer. If present, this indicates the nth occurrence of the
+ specific day within the MONTHLY or YEARLY RRULE. For example, within
+ a MONTHLY rule, +1MO (or simply 1MO) represents the first Monday
+ within the month, whereas -1MO represents the last Monday of the
+ month. If an integer modifier is not present, it means all days of
+ this type within the specified frequency. For example, within a
+ MONTHLY rule, MO represents all Mondays within the month.
*/
- (NSString *)byDayList {
NSMutableString *s;
needsComma = NO;
mask = self->byDay.mask;
day = iCalWeekDayMonday;
+
for (i = 0; i < 7; i++) {
if (mask & day) {
if (needsComma)
/* Rule */
- (void)setRrule:(NSString *)_rrule {
- ASSIGN(self->rrule, _rrule);
+ ASSIGNCOPY(self->rrule, _rrule);
[self _processRule];
}
unsigned i, count;
props = [self->rrule componentsSeparatedByString:@";"];
- count = [props count];
- for (i = 0; i < count; i++) {
+ for (i = 0, count = [props count]; i < count; i++) {
NSString *prop, *key, *value;
NSRange r;
prop = [props objectAtIndex:i];
r = [prop rangeOfString:@"="];
- if (r.length) {
+ if (r.length > 0) {
key = [prop substringToIndex:r.location];
value = [prop substringFromIndex:NSMaxRange(r)];
}
self->frequency = iCalRecurrenceFrequenceMinutely;
else if ([_freq isEqualToString:@"SECONDLY"])
self->frequency = iCalRecurrenceFrequenceSecondly;
- else
+ else {
[NSException raise:NSGenericException
format:@"Incorrect frequency '%@' specified!", _freq];
+ }
}
- (void)setInterval:(NSString *)_interval {
self->byDay.mask = 0;
days = [_byDayList componentsSeparatedByString:@","];
- count = [days count];
- for (i = 0; i < count; i++) {
+ for (i = 0, count = [days count]; i < count; i++) {
NSString *iCalDay;
iCalWeekDay day;
}
-/* Description */
+/* description */
- (NSString *)iCalRepresentation {
NSMutableString *s;
s = [NSMutableString stringWithCapacity:80];
+
[s appendString:@"FREQ="];
[s appendString:[self freq]];
- if ([self repeatInterval] != 1) {
+
+ if ([self repeatInterval] != 1)
[s appendFormat:@";INTERVAL=%d", [self repeatInterval]];
- }
+
if (![self isInfinite]) {
if ([self repeatCount] > 0) {
[s appendFormat:@";COUNT=%d", [self repeatCount]];
return s;
}
-
-@end
+@end /* iCalRecurrenceRule */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include <NGiCal/iCalRecurrenceRule.h>
+#include "common.h"
+
+static int usage(NSArray *args) {
+ fprintf(stderr,
+ "usage: %s <rrule> <startdate> <enddate>\n"
+ "\n"
+ "sample:\n"
+ " %s 'FREQ=MONTHLY;BYDAY=2TU' 20050901 20060301\n",
+ [[args objectAtIndex:0] cString],
+ [[args objectAtIndex:0] cString]);
+ return 1;
+}
+
+static int runIt(NSArray *args) {
+ iCalRecurrenceRule *rrule;
+ NSCalendarDate *from, *to;
+ NSString *pattern;
+ NSString *s;
+
+ if ([args count] < 4)
+ return usage(args);
+
+ pattern = [args objectAtIndex:1];
+ s = [[args objectAtIndex:2] stringByAppendingString:@" 00:00"];
+ from = [NSCalendarDate dateWithString:s calendarFormat:@"%Y%m%d %H:%M"];
+ s = [[args objectAtIndex:3] stringByAppendingString:@" 23:59"];
+ to = [NSCalendarDate dateWithString:s calendarFormat:@"%Y%m%d %H:%M"];
+
+ if (from == nil || to == nil || ![pattern isNotEmpty])
+ return usage(args);
+
+ if ((rrule = [[iCalRecurrenceRule alloc] initWithString:pattern]) == nil) {
+ usage(args);
+ fprintf(stderr, "error: could not parse reccurence rule: '%s'\n",
+ [pattern cString]);
+ return 2;
+ }
+
+ NSLog(@"from: %@ to: %@", from, to);
+ NSLog(@"rrule: %@", rrule);
+
+ return 0;
+}
+
+int main(int argc, char **argv, char **env) {
+ NSAutoreleasePool *pool;
+ int rc;
+
+ pool = [[NSAutoreleasePool alloc] init];
+#if LIB_FOUNDATION_LIBRARY
+ [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+ rc = runIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
+ [pool release];
+ return rc;
+}