/* NSString+NGCards.m - this file is part of SOPE * * Copyright (C) 2006-2009 Inverse inc. * * Author: Wolfgang Sourdeau * * 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 #import #import #import #import "NSString+NGCards.h" static NSString *commaSeparator = nil; @implementation NSString (NGCardsExtensions) - (void) _initCommaSeparator { commaSeparator = [NSMutableString stringWithFormat: @"%c", 255]; [commaSeparator retain]; } - (NSString *) foldedForVersitCards { NSMutableString *foldedString; unsigned int length; NSRange subStringRange; foldedString = [NSMutableString string]; length = [self length]; if (length < 76) [foldedString appendString: self]; else { subStringRange = NSMakeRange (0, 75); [foldedString appendFormat: @"%@\r\n", [self substringWithRange: subStringRange]]; subStringRange = NSMakeRange (75, 74); while ((length - subStringRange.location) > 74) { [foldedString appendFormat: @" %@\r\n", [self substringWithRange: subStringRange]]; subStringRange.location += 74; } subStringRange.length = length - subStringRange.location; [foldedString appendFormat: @" %@", [self substringWithRange: subStringRange]]; } return foldedString; } - (NSArray *) asCardAttributeValues { NSMutableArray *values; NSEnumerator *rawValues; NSString *tmpString, *rawValue, *newString; values = [NSMutableArray array]; if (!commaSeparator) [self _initCommaSeparator]; tmpString = [self stringByReplacingString: @"\\," withString: commaSeparator]; rawValues = [[tmpString componentsSeparatedByString: @","] objectEnumerator]; while ((rawValue = [rawValues nextObject])) { newString = [rawValue stringByReplacingString: commaSeparator withString: @","]; [values addObject: [newString stringByTrimmingSpaces]]; } return values; } - (NSString *) escapedForCards { NSString *string; string = [self stringByReplacingString: @"\\" withString: @"\\\\"]; // string = [string stringByReplacingString: @"," // withString: @"\\,"]; // string = [string stringByReplacingString: @":" // withString: @"\\:"]; string = [string stringByReplacingString: @";" withString: @"\\;"]; string = [string stringByReplacingString: @"\n" withString: @"\\n"]; string = [string stringByReplacingString: @"\r" withString: @"\\r"]; return string; } - (NSString *) unescapedFromCard { NSString *string; string = [self stringByReplacingString: @"\\," withString: @","]; string = [string stringByReplacingString: @"\\:" withString: @":"]; string = [string stringByReplacingString: @"\\;" withString: @";"]; string = [string stringByReplacingString: @"\\n" withString: @"\n"]; string = [string stringByReplacingString: @"\\r" withString: @"\r"]; string = [string stringByReplacingString: @"\\\\" withString: @"\\"]; string = [string stringByReplacingString: @"\\N" // Outlook lameness withString: @"\n"]; return string; } - (NSTimeInterval) durationAsTimeInterval { /* eg: DURATION:PT1H P - "period" P2H30M - "2 hours 30 minutes" dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week) dur-date = dur-day [dur-time] dur-time = "T" (dur-hour / dur-minute / dur-second) dur-week = 1*DIGIT "W" dur-hour = 1*DIGIT "H" [dur-minute] dur-minute = 1*DIGIT "M" [dur-second] dur-second = 1*DIGIT "S" dur-day = 1*DIGIT "D" */ unsigned i, len; NSTimeInterval ti; BOOL isNegative, isTime; int val; unichar c; ti = 0.0; i = 0; c = [self characterAtIndex: i]; if (c == '-') { isNegative = YES; i++; } else { isNegative = NO; } c = [self characterAtIndex: i]; if (c == 'P') { val = 0; len = [self length]; isTime = NO; for (i++; i < len; i++) { c = [self characterAtIndex: i]; if (c == 't' || c == 'T') { isTime = YES; val = 0; } else if (isdigit (c)) val = (val * 10) + (c - 48); else { switch (c) { case 'W': /* week */ ti += (val * 7 * 24 * 60 * 60); break; case 'D': /* day */ ti += (val * 24 * 60 * 60); break; case 'H': /* hour */ ti += (val * 60 * 60); break; case 'M': /* min */ ti += (val * 60); break; case 'S': /* sec */ ti += val; break; default: [self logWithFormat: @"cannot process duration unit: '%c'", c]; break; } val = 0; } } } else NSLog(@"Cannot parse iCal duration value: '%@'", self); if (isNegative) ti = -ti; return ti; } - (NSCalendarDate *) asCalendarDate { NSRange cursor; NSCalendarDate *date; NSTimeZone *utc; unsigned int length; int year, month, day, hour, minute, second; length = [self length]; if (length > 7) { cursor = NSMakeRange(0, 4); year = [[self substringWithRange: cursor] intValue]; cursor.location += cursor.length; cursor.length = 2; month = [[self substringWithRange: cursor] intValue]; cursor.location += cursor.length; day = [[self substringWithRange: cursor] intValue]; if (length > 14) { cursor.location += cursor.length + 1; hour = [[self substringWithRange: cursor] intValue]; cursor.location += cursor.length; minute = [[self substringWithRange: cursor] intValue]; cursor.location += cursor.length; second = [[self substringWithRange: cursor] intValue]; } else { hour = 0; minute = 0; second = 0; } utc = [NSTimeZone timeZoneWithAbbreviation: @"GMT"]; date = [NSCalendarDate dateWithYear: year month: month day: day hour: hour minute: minute second: second timeZone: utc]; } else date = nil; return date; } - (BOOL) isAllDayDate { return ([self length] == 8); } - (NSArray *) componentsWithSafeSeparator: (unichar) separator { NSMutableArray *components; NSRange currentRange; unichar *stringBuffer; unichar currentChar; unsigned int count, length; BOOL escaped; components = [NSMutableArray array]; length = [self length]; stringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * length); [self getCharacters: stringBuffer]; currentRange = NSMakeRange(0, 0); escaped = NO; count = 0; while (count < length) { if (escaped) currentRange.length++; else { currentChar = *(stringBuffer + count); if (currentChar == '\\') escaped = YES; else if (currentChar == separator) { [components addObject: [self substringWithRange: currentRange]]; currentRange = NSMakeRange (count + 1, 0); } else currentRange.length++; } count++; } [components addObject: [self substringWithRange: currentRange]]; NSZoneFree (NULL, stringBuffer); return components; } - (NSString *) rfc822Email { unsigned idx; idx = NSMaxRange([self rangeOfString:@":"]); if ((idx > 0) && ([self length] > idx)) return [self substringFromIndex: idx]; return self; } @end