/* iCalByDayMask.m - this file is part of SOPE * * Copyright (C) 2010-2015 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #import #import #import #import "iCalByDayMask.h" @interface iCalByDayMask (PrivateAPI) - (int) _iCalWeekOccurrenceIntValue: (iCalWeekOccurrence) weekOccurrence; @end @implementation iCalByDayMask + (id) byDayMaskWithDays: (iCalWeekOccurrences) theDays { id o; o = [[self alloc] initWithDays: theDays]; AUTORELEASE(o); return o; } - (id) initWithDays: (iCalWeekOccurrences) theDays { self = [super init]; if (self) { memcpy (days, theDays, sizeof(iCalWeekOccurrences)); } return self; } + (id) byDayMaskWithWeekDays { id o; iCalWeekOccurrences d; d[iCalWeekDaySunday] = 0; d[iCalWeekDayMonday] = iCalWeekOccurrenceAll; d[iCalWeekDayTuesday] = iCalWeekOccurrenceAll; d[iCalWeekDayWednesday] = iCalWeekOccurrenceAll; d[iCalWeekDayThursday] = iCalWeekOccurrenceAll; d[iCalWeekDayFriday] = iCalWeekOccurrenceAll; d[iCalWeekDaySaturday] = 0; o = [[self alloc] initWithDays: d]; AUTORELEASE(o); return o; } + (id) byDayMaskWithRuleString: (NSString *) byDayRule { id o; o = [[self alloc] initWithRuleString: byDayRule]; AUTORELEASE(o); return o; } - (id) initWithRuleString: (NSString *) byDayRule { NSArray *values; unsigned int count, max; NSString *value; unichar c, chars[2]; unsigned int valueLength, i, digitStart, order; iCalWeekDay day; BOOL reverse; self = [super init]; if (self) { memset(days, 0, 7 * sizeof(iCalWeekOccurrence)); if ([byDayRule length] > 0) { values = [byDayRule componentsSeparatedByString: @","]; max = [values count]; for (count = 0; count < max; count++) { value = [[values objectAtIndex: count] uppercaseString]; valueLength = [value length]; if (valueLength > 1) { day = iCalWeekDayUnknown; reverse = NO; digitStart = 0; order = 0; [value getCharacters: chars range: NSMakeRange(valueLength - 2, 2)]; switch (chars[0]) { case 'M': day = iCalWeekDayMonday; break; case 'W': day = iCalWeekDayWednesday; break; case 'F': day = iCalWeekDayFriday; break; case 'T': if (chars[1] == 'U') day = iCalWeekDayTuesday; else if (chars[1] == 'H') day = iCalWeekDayThursday; break; case 'S': if (chars[1] == 'A') day = iCalWeekDaySaturday; else if (chars[1] == 'U') day = iCalWeekDaySunday; break; } if (day != iCalWeekDayUnknown) { c = [value characterAtIndex: 0]; if (c == '-') { digitStart = 1; reverse = YES; c = [value characterAtIndex: 1]; } else if (c == '+') { digitStart = 1; c = [value characterAtIndex: 1]; } i = digitStart; while (i < valueLength && isdigit(c)) { i++; c = [value characterAtIndex: i]; } if (i != digitStart) order = [[value substringWithRange: NSMakeRange(digitStart, (i - digitStart))] intValue]; if (order > 0 && order < 6) { order = pow (2, order - 1); if (reverse) order = order << 5; days[day] |= order; //NSLog(@"*** iCalByDayMask [%i] %@ : day = %i, order = %i, result = %i", count, byDayRule, day, order, days[day]); } else { days[day] = iCalWeekOccurrenceAll; } } } } } } return self; } + (id) byDayMaskWithDaysAndOccurrences: (NSArray *) values { id o; o = [[self alloc] initWithDaysAndOccurrences: values]; AUTORELEASE(o); return o; } - (id) initWithDaysAndOccurrences: (NSArray *) values { unsigned int count, max; NSString *value; unichar c, chars[2]; unsigned int valueLength, i, digitStart, order; iCalWeekDay day; id mask; BOOL reverse; self = [super init]; if (self) { memset(days, 0, 7 * sizeof(iCalWeekOccurrence)); max = [values count]; for (count = 0; count < max; count++) { mask = [values objectAtIndex: count]; if (![mask isKindOfClass: [NSDictionary class]]) continue; value = [[mask objectForKey: @"day"] uppercaseString]; valueLength = [value length]; if (valueLength > 1) { day = iCalWeekDayUnknown; reverse = NO; digitStart = 0; order = 0; [value getCharacters: chars range: NSMakeRange(0, valueLength)]; switch (chars[0]) { case 'M': day = iCalWeekDayMonday; break; case 'W': day = iCalWeekDayWednesday; break; case 'F': day = iCalWeekDayFriday; break; case 'T': if (chars[1] == 'U') day = iCalWeekDayTuesday; else if (chars[1] == 'H') day = iCalWeekDayThursday; break; case 'S': if (chars[1] == 'A') day = iCalWeekDaySaturday; else if (chars[1] == 'U') day = iCalWeekDaySunday; break; } if (day != iCalWeekDayUnknown) { value = [mask objectForKey: @"occurrence"]; valueLength = [value length]; if (valueLength > 0) { c = [value characterAtIndex: 0]; if (c == '-') { digitStart = 1; reverse = YES; } else if (c == '+') { digitStart = 1; } i = digitStart; while (i < valueLength) { c = [value characterAtIndex: i]; i++; if (!isdigit(c)) break; } if (i != digitStart) order = [[value substringWithRange: NSMakeRange(digitStart, (i - digitStart))] intValue]; } if (order > 0 && order < 6) { order = pow (2, order - 1); if (reverse) order = order << 5; days[day] |= order; //NSLog(@"*** iCalByDayMask [%i] %@ : day = %i, order = %i, result = %i", count, byDayRule, day, order, days[day]); } else { days[day] = iCalWeekOccurrenceAll; } } } } } return self; } - (void) dealloc { [super dealloc]; } /** * The week occurrence has no meaning for a DAILY or WEEKLY frequency; * therefore, this method ignores the week occurrence. */ - (BOOL) occursOnDay: (iCalWeekDay) weekDay { return days[weekDay] > 0; } - (BOOL) occursOnDay: (iCalWeekDay) weekDay withWeekOccurrence: (iCalWeekOccurrence) occurrence { return (days[weekDay] & occurrence) > 0; } - (BOOL) occursOnDay: (iCalWeekDay) weekDay withWeekNumber: (int) week { unsigned int absWeek, order; absWeek = abs (week); order = 0; if (absWeek > 0 && absWeek < 6) { order = pow (2, absWeek - 1); if (week < 0) order = order << 5; } return ((days[weekDay] & order) > 0); } - (BOOL) isWeekDays { return (days[iCalWeekDaySunday] == 0 && days[iCalWeekDayMonday] == iCalWeekOccurrenceAll && days[iCalWeekDayTuesday] == iCalWeekOccurrenceAll && days[iCalWeekDayWednesday] == iCalWeekOccurrenceAll && days[iCalWeekDayThursday] == iCalWeekOccurrenceAll && days[iCalWeekDayFriday] == iCalWeekOccurrenceAll && days[iCalWeekDaySaturday] == 0); } - (iCalWeekDay) firstDay { int i; iCalWeekDay day; day = -1; for (i = 0; day == -1 && i < 7; i++) { if (days[i]) day = i; } return day; } - (int) firstOccurrence { int occurrence; iCalWeekDay day; occurrence = 0; day = [self firstDay]; if (day > -1 && days[day] != iCalWeekOccurrenceAll) occurrence = [self _iCalWeekOccurrenceIntValue: days[day]]; return occurrence; } - (iCalWeekOccurrences *) weekDayOccurrences { return &days; } - (int) _iCalWeekOccurrenceIntValue: (iCalWeekOccurrence) weekOccurrence { int i = 0; switch (weekOccurrence) { case iCalWeekOccurrenceFirst: i = 1; break; case iCalWeekOccurrenceSecond: i = 2; break; case iCalWeekOccurrenceThird: i = 3; break; case iCalWeekOccurrenceFourth: i = 4; break; case iCalWeekOccurrenceFifth: i = 5; break; case iCalWeekOccurrenceLast: i = -1; break; case iCalWeekOccurrenceSecondLast: i = -2; break; case iCalWeekOccurrenceThirdLast: i = -3; break; case iCalWeekOccurrenceFourthLast: i = -4; break; case iCalWeekOccurrenceFifthLast: i = -5; break; case iCalWeekOccurrenceAll: i = 0; break; } return i; } - (NSString *) asRuleString { NSMutableArray *rules; NSMutableString *rule; int i; rules = [NSMutableArray array]; for (i = 0; i < 7; i++) { if (days[i]) { rule = [NSMutableString string]; if (days[i] != iCalWeekOccurrenceAll) [rule appendFormat: @"%i", [self _iCalWeekOccurrenceIntValue: days[i]]]; [rule appendString: iCalWeekDayString[i]]; [rules addObject: rule]; } } return [rules componentsJoinedByString: @","]; } - (NSString *) asRuleStringWithIntegers { unsigned int i; NSMutableString *s; s = [NSMutableString string]; for (i = 0; i < 7; i++) if (days[i] > 0) { [s appendFormat: @"%d,", i]; } [s deleteSuffix: @","]; return s; } - (NSArray *) asRuleArray { NSMutableArray *rules; NSMutableDictionary *rule; int i; rules = [NSMutableArray array]; for (i = 0; i < 7; i++) { if (days[i]) { rule = [NSMutableDictionary dictionary]; if (days[i] != iCalWeekOccurrenceAll) [rule setObject: [NSNumber numberWithInt: [self _iCalWeekOccurrenceIntValue: days[i]]] forKey: @"occurrence"]; [rule setObject: iCalWeekDayString[i] forKey: @"day"]; [rules addObject: rule]; } } return rules; } @end /* iCalByDayMask */