Wired Foundation  2.0
A foundation framework for the Wired implementation on Mac OS X
NSString-WIFoundation.m
00001 /* $Id$ */
00002 
00003 /*
00004  *  Copyright (c) 2003-2009 Axel Andersson
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *  1. Redistributions of source code must retain the above copyright
00011  *     notice, this list of conditions and the following disclaimer.
00012  *  2. Redistributions in binary form must reproduce the above copyright
00013  *     notice, this list of conditions and the following disclaimer in the
00014  *     documentation and/or other materials provided with the distribution.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00017  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
00020  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00023  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00024  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00025  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026  * POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00029 #import <WiredFoundation/NSScanner-WIFoundation.h>
00030 #import <WiredFoundation/NSString-WIFoundation.h>
00031 
00032 @implementation NSString(WIFoundation)
00033 
00034 + (id)stringWithFormat:(NSString *)format arguments:(va_list)arguments {
00035         return [[[self alloc] initWithFormat:format arguments:arguments] autorelease];
00036 }
00037 
00038 
00039 
00040 + (id)stringWithData:(NSData *)data encoding:(NSStringEncoding)encoding {
00041         return [[[self alloc] initWithData:data encoding:encoding] autorelease];
00042 }
00043 
00044 
00045 
00046 + (id)stringWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding {
00047         return [[[self alloc] initWithBytes:bytes length:length encoding:encoding] autorelease];
00048 }
00049 
00050 
00051 
00052 + (id)stringWithRandomCharactersFromString:(NSString *)characters length:(NSUInteger)length {
00053         NSMutableString         *string;
00054         NSUInteger                      count;
00055         
00056         string = [NSMutableString string];
00057         count = [characters length];
00058         
00059         while(length > 0) {
00060                 [string appendFormat:@"%C", [characters characterAtIndex:random() % count]];
00061                 
00062                 length--;
00063         }
00064         
00065         return string;
00066 }
00067 
00068 
00069 
00070 + (id)UUIDString { 
00071         NSString                *string;
00072         CFUUIDRef               uuidRef;
00073         CFStringRef             stringRef;
00074 
00075         uuidRef = CFUUIDCreate(NULL);
00076         stringRef = CFUUIDCreateString(NULL, uuidRef);
00077         CFRelease(uuidRef);
00078         
00079         string = [[self alloc] initWithString:(NSString *) stringRef];
00080         
00081         CFRelease(stringRef);
00082         
00083         return [string autorelease];
00084 }
00085 
00086 
00087 
00088 #pragma mark -
00089 
00090 - (NSUInteger)UTF8StringLength {
00091         return strlen([self UTF8String]);
00092 }
00093 
00094 
00095 
00096 - (unsigned long long)unsignedLongLongValue {
00097         return (unsigned long long) [self longLongValue];
00098 }
00099 
00100 
00101 
00102 - (unsigned int)unsignedIntValue {
00103         return (unsigned int) [self intValue];
00104 }
00105 
00106 
00107 
00108 - (NSUInteger)unsignedIntegerValue {
00109         return (NSUInteger) [self integerValue];
00110 }
00111 
00112 
00113 
00114 #pragma mark -
00115 
00116 - (BOOL)containsSubstring:(NSString *)string {
00117         return ([self rangeOfString:string].location != NSNotFound);
00118 }
00119  
00120 
00121 - (BOOL)containsSubstring:(NSString *)string options:(NSUInteger)options {
00122         return ([self rangeOfString:string options:options].location != NSNotFound);
00123 }
00124  
00125 
00126 - (BOOL)containsCharactersFromSet:(NSCharacterSet *)set {
00127         return ([self rangeOfCharacterFromSet:set].location != NSNotFound);
00128 }
00129 
00130 
00131 
00132 - (BOOL)isComposedOfCharactersFromSet:(NSCharacterSet *)set {
00133         return ![self containsCharactersFromSet:[set invertedSet]];
00134 }
00135 
00136 
00137 
00138 #pragma mark -
00139 
00140 - (NSArray *)componentsSeparatedByCharactersFromSet:(NSCharacterSet *)set {
00141         NSScanner               *scanner;
00142         NSMutableArray  *components;
00143         NSCharacterSet  *invertedSet;
00144         NSString                *string;
00145 
00146         if([self length] == 0)
00147                 return NULL;
00148 
00149         if(![self containsCharactersFromSet:set])
00150                 return [NSArray arrayWithObject:self];
00151 
00152         scanner = [NSScanner scannerWithString:self];
00153         components = [NSMutableArray array];
00154         invertedSet = [set invertedSet];
00155                 
00156         while(![scanner isAtEnd]) {
00157                 [scanner scanUpToCharactersFromSet:set intoString:&string];
00158                 [scanner scanUpToCharactersFromSet:invertedSet intoString:NULL];
00159                 
00160                 if([string length] > 0)
00161                         [components addObject:string];
00162         }
00163 
00164         return components;
00165 }
00166 
00167 
00168 
00169 #pragma mark -
00170 
00171 - (NSString *)stringByReplacingOccurencesOfString:(NSString *)target withString:(NSString *)replacement {
00172         NSMutableString         *string;
00173 
00174         string = [self mutableCopy];
00175 
00176         [string replaceOccurrencesOfString:target
00177                                                         withString:replacement
00178                                                            options:0
00179                                                                  range:NSMakeRange(0, [string length])];
00180 
00181         return [string autorelease];
00182 }
00183 
00184 
00185 
00186 - (NSString *)stringByReplacingOccurencesOfStrings:(NSArray *)targets withString:(NSString *)replacement {
00187         NSMutableString         *string;
00188         NSEnumerator            *enumerator;
00189         NSString                        *target;
00190 
00191         string = [self mutableCopy];
00192         enumerator = [targets objectEnumerator];
00193 
00194         while((target = [enumerator nextObject])) {
00195                 [string replaceOccurrencesOfString:target
00196                                                                 withString:replacement
00197                                                                    options:0
00198                                                                          range:NSMakeRange(0, [string length])];
00199         }
00200 
00201         return [string autorelease];
00202 }
00203 
00204 
00205 
00206 #pragma mark -
00207 
00208 - (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding charactersToLeaveUnescaped:(NSString *)charactersToLeaveUnescaped {
00209         return [(NSString *) CFURLCreateStringByAddingPercentEscapes(NULL,
00210                                                                                                                                  (CFStringRef) self,
00211                                                                                                                                  (CFStringRef) charactersToLeaveUnescaped,
00212                                                                                                                                  NULL,
00213                                                                                                                                  CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
00214 }
00215 
00216 
00217 
00218 - (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding legalURLCharactersToBeEscaped:(NSString *)legalURLCharactersToBeEscaped {
00219         return [(NSString *) CFURLCreateStringByAddingPercentEscapes(NULL,
00220                                                                                                                                  (CFStringRef) self,
00221                                                                                                                                  NULL,
00222                                                                                                                                  (CFStringRef) legalURLCharactersToBeEscaped,
00223                                                                                                                                  CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease];
00224 }
00225 
00226 
00227 
00228 #pragma mark -
00229 
00230 - (NSString *)stringByReplacingPathExtensionWithExtension:(NSString *)extension {
00231         return [[self stringByDeletingPathExtension] stringByAppendingPathExtension:extension];
00232 }
00233 
00234 
00235 
00236 #pragma mark -
00237 
00238 - (NSString *)stringByApplyingFilter:(WITextFilter *)filter {
00239         NSMutableString *string;
00240         
00241         string = [self mutableCopy];
00242         [string applyFilter:filter];
00243         
00244         return [string autorelease];
00245 }
00246 
00247 
00248 
00249 #pragma mark -
00250 
00251 - (NSComparisonResult)caseInsensitiveAndNumericCompare:(NSString *)string { 
00252         return [self compare:string
00253                                  options:NSCaseInsensitiveSearch | NSNumericSearch
00254                                    range:NSMakeRange(0, [self length])
00255                                   locale:[NSLocale currentLocale]];
00256 }
00257 
00258 
00259 
00260 - (NSComparisonResult)finderCompare:(NSString *)string { 
00261         return /* NSWidthInsensitiveSearch *//* NSForcedOrderingSearch */[self compare:string
00262                                  options:NSCaseInsensitiveSearch | NSNumericSearch | 256  | 512 
00263                                    range:NSMakeRange(0, [self length])
00264                                   locale:[NSLocale currentLocale]];
00265 }
00266 
00267 @end
00268 
00269 
00270 
00271 @implementation NSString(WIStringChecksumming)
00272 
00273 - (NSString *)SHA1 {
00274         CC_SHA1_CTX                             c;
00275         static unsigned char    hex[] = "0123456789abcdef";
00276         unsigned char                   sha[CC_SHA1_DIGEST_LENGTH];
00277         char                                    text[CC_SHA1_DIGEST_LENGTH * 2 + 1];
00278         NSUInteger                              i;
00279         
00280         CC_SHA1_Init(&c);
00281         CC_SHA1_Update(&c, [self UTF8String], (CC_LONG)[self UTF8StringLength]);
00282         CC_SHA1_Final(sha, &c);
00283         
00284         for(i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
00285                 text[i + i]                     = hex[sha[i] >> 4];
00286                 text[i + i + 1]         = hex[sha[i] & 0x0F];
00287         }
00288         
00289         text[i + i] = '\0';
00290         
00291         return [NSString stringWithUTF8String:text];
00292 }
00293 
00294 @end
00295 
00296 
00297 
00298 @implementation NSString(WIHumanReadableStringFormatting)
00299 
00300 + (NSString *)humanReadableStringForTimeInterval:(NSTimeInterval)interval {
00301         NSString                *string;
00302         NSUInteger              days, hours, minutes, seconds;
00303         BOOL                    past = NO;
00304 
00305         interval = rint(interval);
00306 
00307         if(interval < 0) {
00308                 past = YES;
00309                 interval = -interval;
00310         }
00311 
00312         days = interval / 86400;
00313         interval -= days * 86400;
00314 
00315         hours = interval / 3600;
00316         interval -= hours * 3600;
00317 
00318         minutes = interval / 60;
00319         interval -= minutes * 60;
00320 
00321         seconds = interval;
00322 
00323         if(days > 0) {
00324                 string = [NSSWF:
00325                         WILS(@"%lu:%0.2lu:%0.2lu:%0.2lu days", @"NSString-WIFoundation: time strings (days, hours, minutes, seconds)"),
00326                         days, hours, minutes, seconds];
00327         }
00328         else if(hours > 0) {
00329                 string = [NSSWF:
00330                         WILS(@"%0.2lu:%0.2lu:%0.2lu hours", @"NSString-WIFoundation: time strings (hours, minutes, seconds)"),
00331                         hours, minutes, seconds];
00332         }
00333         else if(minutes > 0) {
00334                 string = [NSSWF:
00335                         WILS(@"%0.2lu:%0.2lu minutes", @"NSString-WIFoundation: time strings (minutes, seconds)"),
00336                         minutes, seconds];
00337         }
00338         else {
00339                 string = [NSSWF:
00340                         WILS(@"00:%0.2lu seconds", @"NSString-WIFoundation: time string (minutes, seconds)"),
00341                         seconds];
00342         }
00343 
00344         if(past)
00345                 string = [NSSWF:WILS(@"%@ ago", @"NSString-WIFoundation: time string"), string];
00346 
00347         return string;
00348 }
00349 
00350 
00351 
00352 + (NSString *)humanReadableStringForSizeInBytes:(unsigned long long)size {
00353         static NSNumberFormatter        *formatter;
00354         double                                          kb, mb, gb, tb, pb;
00355 
00356         if(!formatter) {
00357                 formatter = [[NSNumberFormatter alloc] init];
00358                 [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
00359                 [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
00360                 [formatter setMaximumFractionDigits:1];
00361         }
00362 
00363         if(size < 1000) {
00364                 return [NSSWF:WILS(@"%llu bytes", @"NSString-WIFoundation: byte size strings"),
00365                         size];
00366         }
00367 
00368         kb = (double) size / 1024.0;
00369 
00370         if(kb < 1000) {
00371                 return [NSSWF:WILS(@"%@ KB", @"NSString-WIFoundation: byte size strings"),
00372                         [formatter stringForObjectValue:[NSNumber numberWithDouble:kb]]];
00373         }
00374 
00375         mb = (double) kb / 1024.0;
00376 
00377         if(mb < 1000) {
00378                 return [NSSWF:WILS(@"%@ MB", @"NSString-WIFoundation: byte size strings"),
00379                         [formatter stringForObjectValue:[NSNumber numberWithDouble:mb]]];
00380         }
00381 
00382         gb = (double) mb / 1024.0;
00383 
00384         if(gb < 1000) {
00385                 return [NSSWF:WILS(@"%@ GB", @"NSString-WIFoundation: byte size strings"),
00386                         [formatter stringForObjectValue:[NSNumber numberWithDouble:gb]]];
00387         }
00388 
00389         tb = (double) gb / 1024.0;
00390 
00391         if(tb < 1000) {
00392                 return [NSSWF:WILS(@"%@ TB", @"NSString-WIFoundation: byte size strings"),
00393                         [formatter stringForObjectValue:[NSNumber numberWithDouble:tb]]];
00394         }
00395 
00396         pb = (double) tb / 1024.0;
00397 
00398         if(pb < 1000) {
00399                 return [NSSWF:WILS(@"%@ PB", @"NSString-WIFoundation: byte size strings"),
00400                         [formatter stringForObjectValue:[NSNumber numberWithDouble:pb]]];
00401         }
00402 
00403         return NULL;
00404 }
00405 
00406 
00407 
00408 + (NSString *)humanReadableStringForSizeInBytes:(unsigned long long)size withBytes:(BOOL)bytes {
00409         static NSNumberFormatter   *formatter;
00410         NSString                                        *string;
00411 
00412         string = [NSString humanReadableStringForSizeInBytes:size];
00413 
00414         if(size > 1024 && bytes) {
00415                 if(!formatter) {
00416                         formatter = [[NSNumberFormatter alloc] init];
00417                         [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
00418                         [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
00419                 }
00420 
00421                 string = [NSSWF:@"%@ (%@ %@)",
00422                         string,
00423                         [formatter stringForObjectValue:[NSNumber numberWithUnsignedLongLong:size]],
00424                         size == 1
00425                                 ? WILS(@"byte", @"NSString-WIFoundation: 'byte' singular")
00426                                 : WILS(@"bytes", @"NSString-WIFoundation: 'byte' plural")];
00427         }
00428 
00429         return string;
00430 }
00431 
00432 
00433 
00434 + (NSString *)humanReadableStringForSizeInBits:(unsigned long long)size {
00435         static NSNumberFormatter        *formatter;
00436         double                                          kb, mb, gb, tb, pb;
00437         
00438         if(!formatter) {
00439                 formatter = [[NSNumberFormatter alloc] init];
00440                 [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
00441                 [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
00442                 [formatter setMaximumFractionDigits:1];
00443         }
00444         
00445         if(size < 1000) {
00446                 return [NSSWF:WILS(@"%llu bits", @"NSString-WIFoundation: bit size strings"),
00447                         size];
00448         }
00449         
00450         kb = (double) size / 1024.0;
00451         
00452         if(kb < 1000) {
00453                 return [NSSWF:WILS(@"%@ kbit", @"NSString-WIFoundation: bit size strings"),
00454                         [formatter stringForObjectValue:[NSNumber numberWithDouble:kb]]];
00455         }
00456         
00457         mb = (double) kb / 1024.0;
00458         
00459         if(mb < 1000) {
00460                 return [NSSWF:WILS(@"%@ Mbit", @"NSString-WIFoundation: bit size strings"),
00461                         [formatter stringForObjectValue:[NSNumber numberWithDouble:mb]]];
00462         }
00463         
00464         gb = (double) mb / 1024.0;
00465         
00466         if(gb < 1000) {
00467                 return [NSSWF:WILS(@"%@ Gbit", @"NSString-WIFoundation: bit size strings"),
00468                         [formatter stringForObjectValue:[NSNumber numberWithDouble:gb]]];
00469         }
00470         
00471         tb = (double) gb / 1024.0;
00472         
00473         if(tb < 1000) {
00474                 return [NSSWF:WILS(@"%@ Tbit", @"NSString-WIFoundation: bit size strings"),
00475                         [formatter stringForObjectValue:[NSNumber numberWithDouble:tb]]];
00476         }
00477         
00478         pb = (double) tb / 1024.0;
00479         
00480         if(pb < 1000) {
00481                 return [NSSWF:WILS(@"%@ Pbit", @"NSString-WIFoundation: bit size strings"),
00482                         [formatter stringForObjectValue:[NSNumber numberWithDouble:pb]]];
00483         }
00484         
00485         return NULL;
00486 }
00487 
00488 
00489 
00490 + (NSString *)humanReadableStringForBandwidth:(NSUInteger)speed {
00491         if(speed > 0) {
00492                 if(speed <= 3600)
00493                         return WILS(@"28.8k Modem", @"NSString-WIFoundation: bandwidth strings");
00494                 else if(speed <= 4200)
00495                         return WILS(@"33.6k Modem", @"NSString-WIFoundation: bandwidth strings");
00496                 else if(speed <= 7000)
00497                         return WILS(@"56k Modem", @"NSString-WIFoundation: bandwidth strings");
00498                 else if(speed <= 8000)
00499                         return WILS(@"64k ISDN", @"NSString-WIFoundation: bandwidth strings");
00500                 else if(speed <= 16000)
00501                         return WILS(@"128k ISDN/DSL", @"NSString-WIFoundation: bandwidth strings");
00502                 else if(speed <= 32000)
00503                         return WILS(@"256k DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00504                 else if(speed <= 48000)
00505                         return WILS(@"384k DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00506                 else if(speed <= 64000)
00507                         return WILS(@"512k DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00508                 else if(speed <= 96000)
00509                         return WILS(@"768k DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00510                 else if(speed <= 128000)
00511                         return WILS(@"1M DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00512                 else if(speed <= 256000)
00513                         return WILS(@"2M DSL/Cable", @"NSString-WIFoundation: bandwidth strings");
00514                 else if(speed <= 1280000)
00515                         return WILS(@"10M LAN", @"NSString-WIFoundation: bandwidth strings");
00516                 else if(speed <= 12800000)
00517                         return WILS(@"100M LAN", @"NSString-WIFoundation: bandwidth strings");
00518         }
00519         
00520         return WILS(@"Unknown", @"NSString-WIFoundation: bandwidth strings");
00521 }
00522 
00523 @end
00524 
00525 
00526 
00527 @implementation NSString(WIWiredVersionStringFormatting)
00528 
00529 - (NSString *)wiredVersion {
00530         NSString                        *unknown, *client, *clientVersion, *os, *osVersion, *arch;
00531         NSScanner                       *scanner;
00532         const NXArchInfo        *info;
00533 
00534         // "Wired Client/1.0 (Darwin; 7.3.0; powerpc) (OpenSSL 0.9.6i Feb 19 2003; CoreFoundation 299.3; AppKit 743.20)"
00535 
00536         unknown = WILS(@"Unknown", @"NSString-WIFoundation: unknown Wired client");
00537         scanner = [NSScanner scannerWithString:self];
00538         [scanner setCharactersToBeSkipped:NULL];
00539 
00540         if(![scanner scanUpToString:@"/" intoString:&client])
00541                 return unknown;
00542 
00543         if(![scanner scanString:@"/" intoString:NULL])
00544                 return unknown;
00545 
00546         if(![scanner scanUpToString:@" " intoString:&clientVersion])
00547                 return unknown;
00548 
00549         if(![scanner scanString:@" (" intoString:NULL])
00550                 return unknown;
00551 
00552         if(![scanner scanUpToString:@";" intoString:&os])
00553                 return unknown;
00554 
00555         if(![scanner scanString:@"; " intoString:NULL])
00556                 return unknown;
00557 
00558         if(![scanner scanUpToString:@";" intoString:&osVersion])
00559                 return unknown;
00560 
00561         if(![scanner scanString:@"; " intoString:NULL])
00562                 return unknown;
00563 
00564         if(![scanner scanUpToString:@")" intoString:&arch])
00565                 return unknown;
00566 
00567         if([arch isEqualToString:@"powerpc"])
00568                 arch = @"ppc";
00569         
00570         info = NXGetArchInfoFromName([arch UTF8String]);
00571         
00572         if(info)
00573                 arch = [NSSWF:@"%s", info->description];
00574 
00575         return [NSSWF:
00576                 WILS(@"%@ %@ on %@ %@ (%@)", @"NSString-WIFoundation: Wired client version (client, client version, os, os version, architecture)"),
00577                 client, clientVersion, os, osVersion, arch];
00578 }
00579 
00580 @end
00581 
00582 
00583 
00584 @implementation NSMutableString(WIFoundation)
00585 
00586 - (void)deleteCharactersToIndex:(NSUInteger)index {
00587         [self deleteCharactersInRange:NSMakeRange(0, index)];
00588 }
00589 
00590 
00591 
00592 - (void)deleteCharactersFromIndex:(NSUInteger)index {
00593         [self deleteCharactersInRange:NSMakeRange(index, [self length] - index)];
00594 }
00595 
00596 
00597 
00598 - (NSUInteger)replaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement {
00599         return [self replaceOccurrencesOfString:target withString:replacement options:0 range:NSMakeRange(0, [self length])];
00600 }
00601 
00602 
00603 
00604 - (NSUInteger)replaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSUInteger)options {
00605         return [self replaceOccurrencesOfString:target withString:replacement options:options range:NSMakeRange(0, [self length])];
00606 }
00607 
00608 
00609 
00610 - (void)trimCharactersInSet:(NSCharacterSet *)characterSet {
00611         [self setString:[self stringByTrimmingCharactersInSet:characterSet]];
00612 }
00613 
00614 
00615 
00616 - (void)applyFilter:(WITextFilter *)filter {
00617         [filter performSelector:@selector(filter:) withObject:self];
00618 }
00619 
00620 @end
 All Classes