]> err.no Git - sope/commitdiff
added ievalrrule tool
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 19 Sep 2005 21:44:06 +0000 (21:44 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 19 Sep 2005 21:44:06 +0000 (21:44 +0000)
minor improvs in iCalRecurrenceRule

git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1116 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

sope-ical/NGiCal/ChangeLog
sope-ical/NGiCal/Version
sope-ical/NGiCal/iCalRecurrenceRule.h
sope-ical/NGiCal/iCalRecurrenceRule.m
sope-ical/NGiCal/tests/README
sope-ical/samples/ChangeLog
sope-ical/samples/GNUmakefile
sope-ical/samples/GNUmakefile.preamble
sope-ical/samples/ievalrrule.m [new file with mode: 0644]
sope-ical/samples/vcfparsetest.m

index c8502f931779cabf5ae144102ed0fbbfbbbcd051..ebe1c60d375de154cf8878d9a691ea19b3b759ae 100644 (file)
@@ -1,3 +1,8 @@
+2005-09-19  Helge Hess  <helge.hess@opengroupware.org>
+
+       * iCalRecurrenceRule.m: minor code improvements, more tolerant on
+         invalid iCal rrule input (v4.5.61)
+
 2005-08-16  Helge Hess  <helge.hess@opengroupware.org>
 
        * GNUmakefile, GNUmakefile.preamble: added OSX framework compilation
index a5b5ba42b732373f6175837bc19cf4de133c7808..1b7555321ef1c4b6a29b8ad5ac6d567fd48d40ad 100644 (file)
@@ -2,7 +2,7 @@
 
 MAJOR_VERSION=4
 MINOR_VERSION=5
-SUBMINOR_VERSION:=60
+SUBMINOR_VERSION:=61
 
 # v4.5.40 requires NGExtensions v4.5.145
 # v4.5.37 requires NGExtensions v4.5.140
index 96e77e949f1ff91a8935644379a04fdc6d659da7..9cc99901386676e2d3b90a0d415b09f283936c8e 100644 (file)
 #import <Foundation/NSObject.h>
 
 /*
- iCalRecurrenceRule
 iCalRecurrenceRule
  
- Encapsulates a (probably complex) recurrence rule by offering
- a high level API.
 Encapsulates a (probably complex) recurrence rule by offering
 a high level API.
  
- NOTE: as of now, only a very limited subset of RFC2445 is implemented.
- Please see the unit tests for what is covered.
 NOTE: as of now, only a very limited subset of RFC2445 is implemented.
       Please see the unit tests for what is covered.
 */
 
 typedef enum {
@@ -71,26 +71,35 @@ typedef enum {
 }
 
 + (id)recurrenceRuleWithICalRepresentation:(NSString *)_iCalRep;
+- (id)initWithString:(NSString *)_str;
+
+/* accessors */
 
 - (void)setFrequency:(iCalRecurrenceFrequency)_frequency;
 - (iCalRecurrenceFrequency)frequency;
+
 - (void)setRepeatInterval:(int)_repeatInterval;
 - (int)repeatInterval;
+
 - (void)setWeekStart:(iCalWeekDay)_weekStart;
 - (iCalWeekDay)weekStart;
+
 - (void)setByDayMask:(unsigned)_mask;
 - (unsigned)byDayMask;
   
 /* count and untilDate are mutually exclusive */
+
 - (void)setRepeatCount:(unsigned)_repeatCount;
 - (unsigned)repeatCount;
+
 - (void)setUntilDate:(NSCalendarDate *)_untilDate;
 - (NSCalendarDate *)untilDate;
 
 - (BOOL)isInfinite;
 
 /* parse complete iCal RRULE */
-- (void)setRrule:(NSString *)_rrule;
+
+- (void)setRrule:(NSString *)_rrule; // TODO: weird name? (better: RRule?)
 
 - (NSString *)iCalRepresentation;
 
index a502ed9d815ef4ecaa6af8795b5f8a8ccea743f4..55a1a1db2af1700838885290e8dce59cff9d1f6f 100644 (file)
 #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];
@@ -84,7 +82,7 @@
 }
 
 
-/* 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 */
index cff29bb3c776c4655db6dc0c159dbe013562dff5..5541041c02b7571f7100a2ee769f31e8e7d18285 100644 (file)
@@ -1,5 +1,3 @@
-$Id$
-
 This folder contains unit tests for the NGiCal project.
 
 It uses SEN:TE's OCUnit project which can be found at
index 1ca2105ee4c62ffd5b2559b5aafd7c14259e190d..611bc48d88401cd2090b2bf39cc57325c4a2173c 100644 (file)
@@ -1,3 +1,7 @@
+2005-09-19  Helge Hess  <helge.hess@opengroupware.org>
+
+       * ievalrrule.m: started tool to evaluate iCal rrules on the shell
+
 2005-08-16  Helge Hess  <helge.hess@opengroupware.org>
 
        * link tools against OSX frameworks if configured so
index 61b8e8a55d3ae3e006c8ec2eaf9fa828b4f4cbcd..afeb8f0c279f64f2bcf869e727463be21e63261d 100644 (file)
@@ -3,12 +3,13 @@
 -include ../../config.make
 include $(GNUSTEP_MAKEFILES)/common.make
 
-TOOL_NAME = icalparsetest icalds vcf2xml vcfparsetest
+TOOL_NAME = icalparsetest icalds vcf2xml vcfparsetest ievalrrule
 
 icalparsetest_OBJC_FILES = icalparsetest.m
 icalds_OBJC_FILES        = icalds.m
 vcf2xml_OBJC_FILES       = vcf2xml.m
 vcfparsetest_OBJC_FILES  = vcfparsetest.m
+ievalrrule_OBJC_FILES    = ievalrrule.m
 
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/tool.make
index ce9af8e826f8333c92ab3289c17905a346aa0b03..2c704e392e581197be44fe4d59f7d6c05cd12cf2 100644 (file)
@@ -16,6 +16,7 @@ icalparsetest_PCH_FILE = common.h
 icalds_PCH_FILE        = common.h
 vcf2xml_PCH_FILE       = common.h
 vcfparsetest_PCH_FILE  = common.h
+ievalrrule_PCH_FILE    = common.h
 
 
 # dependencies
@@ -24,6 +25,7 @@ ifneq ($(frameworks),yes)
 icalparsetest_TOOL_LIBS += -lNGiCal
 icalds_TOOL_LIBS        += -lNGiCal
 vcfparsetest_TOOL_LIBS  += -lNGiCal
+ievalrrule_TOOL_LIBS    += -lNGiCal
 
 ADDITIONAL_TOOL_LIBS += \
        -lNGStreams -lNGExtensions -lEOControl  \
@@ -32,6 +34,7 @@ else
 icalparsetest_TOOL_LIBS += -framework NGiCal
 icalds_TOOL_LIBS        += -framework NGiCal
 vcfparsetest_TOOL_LIBS  += -framework NGiCal
+ievalrrule_TOOL_LIBS    += -framework NGiCal
 
 ADDITIONAL_TOOL_LIBS += \
        -framework NGStreams -framework NGExtensions -framework EOControl \
diff --git a/sope-ical/samples/ievalrrule.m b/sope-ical/samples/ievalrrule.m
new file mode 100644 (file)
index 0000000..1ce1111
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  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;
+}
index 26289af274b2c4b0dc93efbf034651b186f3af2d..54af86b42b672a6c23f4d0a449927cc51e2614e9 100644 (file)
@@ -103,13 +103,12 @@ int main(int argc, char **argv, char **env)  {
   vcsparsetest *tool;
   int rc;
 
+  pool = [[NSAutoreleasePool alloc] init];
 #if LIB_FOUNDATION_LIBRARY  
   [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
 #endif
   
-  pool = [[NSAutoreleasePool alloc] init];
-  
-  if ((tool = [[vcsparsetest alloc] init])) {
+  if ((tool = [[vcsparsetest alloc] init]) != nil) {
     NS_DURING
       rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]];
     NS_HANDLER