This is NSString.m in view mode; [Download] [Up]
/* NSString.m Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. All rights reserved. Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro> This file is part of libFoundation. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. We disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall we be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include <ctype.h> #include <Foundation/common.h> #include <Foundation/NSArray.h> #include <Foundation/NSDictionary.h> #include <Foundation/NSCoder.h> #include <Foundation/NSException.h> #include <Foundation/exceptions/StringExceptions.h> #include <Foundation/exceptions/GeneralExceptions.h> #include <Foundation/NSCharacterSet.h> #include <Foundation/NSString.h> #include <Foundation/NSConcreteString.h> /* General ideas in NSString class cluster implementation The NSString class is an abstract class that uses only unicode representation and handles in an inefficient manner since it operates on abstract strings accessing characters one by one using characterAtIndex: method. Currently there is only one abstract subclass of classes designed to implement ANSI C strings in the default encoding provided by the operating system (assumed ASCII or ASCII extension like NEXTSTEP). This type of strings are called NS8BitString since they uses characters (usually represented on 8 bits) for immutable classes and NSMutable8BitString for mutable ones respectively. This tree of classes is implemented based on `__compact8BitBytes' method that returns a pointer to the internal representation of the string as char[], with all characters compact, with no gap. Unicode and encodings will be supported in the future when I will know how to handle the following (If you know about these please send me a message) - convert between different encodings - convert characters to upper/lower cases - handle composed character sequences So for the time being only NS8BitString/NSMutable8BitString are used but their use in the future will be limited to ...WithCString... methods and the strings generated by the compiler with @"" construct (which should generate unicode ones some day in the future). There is another problem: methods like initWithCharacters... and initWithCString assume that the underlying support is 16Bit respectively 8Bit but it is sent to an instance allocated with [NSString alloc]. So we make NSString alloc method to return a temporary string that will allocate and initialize the concrete class that will hold the character in initWith... methods. This class is NSTemporaryString. Thus one must use constructs like var = [[NSString alloc] initWith...] var = [NSString stringWith...] but not var = [NSString alloc] [var initWith...] since the second line will return an instance different from the one in var. */ /*************************** * NSString abstract class ***************************/ @implementation NSString + (void)initialize { /* Force linking of NSString categories (path utilities) */ NSUserName(); } /* Getting a string's length */ - (unsigned int)length { [self subclassResponsibility:_cmd]; return 0; } /* Accessing characters */ - (unichar)characterAtIndex:(unsigned int)index { [self subclassResponsibility:_cmd]; return 0; } - (void)getCharacters:(unichar*)buffer { NSRange range = {0, [self length]}; [self getCharacters:buffer range:range]; } - (void)getCharacters:(unichar*)buffer range:(NSRange)aRange { int i = 0; IMP imp = [self methodForSelector:@selector(characterAtIndex:)]; if (aRange.location + aRange.length > [self length]) THROW([[IndexOutOfRangeException alloc] initWithFormat:@"range (%d,%d) in string %x of length %d", aRange.location, aRange.length, self, [self length]]); for (i = 0; i < aRange.length; i++) buffer[i] = (unichar)(int)(*imp)(self, @selector(characterAtIndex:), aRange.location + i); } /* Combining strings */ - (NSString*)stringByAppendingString:(NSString*)aString { NSMutableString *string = [self mutableCopy]; [string appendString:aString]; return [string autorelease]; } - (NSString*)stringByAppendingFormat:(NSString*)format,... { NSMutableString *string = [self mutableCopy]; va_list va; va_start(va, format); [string appendFormat:format arguments:va]; va_end(va); return string; } - (NSString*)stringByAppendingFormat:(NSString*)format arguments:(va_list)argList { NSMutableString *string = [self mutableCopy]; [string appendFormat:format arguments:argList]; return [string autorelease]; } - (NSString*)stringByPrependingString:(NSString*)aString { return [aString stringByAppendingString:self]; } - (NSString*)stringByPrependingFormat:(NSString*)format,... { NSString *string; va_list va; va_start(va, format); string = Avsprintf(format, va); va_end(va); return [string stringByAppendingString:self]; } - (NSString*)stringByPrependingFormat:(NSString*)format arguments:(va_list)argList { NSString *string = Avsprintf(format, argList); return [string stringByAppendingString:self]; } /* Dividing strings */ - (NSArray*)componentsSeparatedByString:(NSString*)separator { int first = 0, last = 0; int slen = [separator length]; NSMutableArray* components = [NSMutableArray new]; while((first = [self indexOfString:separator fromIndex:last]) != NSNotFound) { NSRange range = {last, first - last}; [components addObject:[self substringWithRange:range]]; last = first + slen; } if([self length] >= last) { NSString* lastComponent = [self substringFromIndex:last]; [components addObject:lastComponent]; } return [components autorelease]; } - (NSString*)substringWithRange:(NSRange)aRange { // UNICODE [self subclassResponsibility:_cmd]; return nil; } - (NSString*)substringFromIndex:(unsigned int)index { NSRange range = {index, [self length] - index}; return [self substringWithRange:range]; } - (NSString*)substringToIndex:(unsigned int)index { NSRange range = {0, index}; return [self substringWithRange:range]; } /* Finding characters and substrings */ - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet { NSRange range = {0, [self length]}; return [self rangeOfCharacterFromSet:aSet options:0 range:range]; } - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet options:(unsigned int)mask { NSRange range = {0, [self length]}; return [self rangeOfCharacterFromSet:aSet options:mask range:range]; } - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet options:(unsigned int)mask range:(NSRange)aRange { // UNICODE NSRange range = {0, 0}; [self subclassResponsibility:_cmd]; return range; } - (NSRange)rangeOfString:(NSString*)string { NSRange range = {0, [self length]}; return [self rangeOfString:string options:0 range:range]; } - (NSRange)rangeOfString:(NSString*)string options:(unsigned int)mask { NSRange range = {0, [self length]}; return [self rangeOfString:string options:mask range:range]; } - (NSRange)rangeOfString:(NSString*)aString options:(unsigned int)mask range:(NSRange)aRange { // UNICODE // ENCODINGS NSRange range = {0, 0}; [self subclassResponsibility:_cmd]; return range; } - (unsigned int)indexOfString:(NSString*)substring { NSRange range = {0, [self length]}; range = [self rangeOfString:substring options:0 range:range]; return range.length ? range.location : NSNotFound; } - (unsigned int)indexOfString:(NSString*)substring fromIndex:(unsigned)index { NSRange range = {index, [self length]-index}; range = [self rangeOfString:substring options:0 range:range]; return range.length ? range.location : NSNotFound; } - (unsigned int)indexOfString:(NSString*)substring range:(NSRange)range { range = [self rangeOfString:substring options:0 range:range]; return range.length ? range.location : NSNotFound; } /* Determining composed character sequences */ - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(unsigned int)anIndex { NSRange range; int length = [self length]; if (anIndex >= length) THROW([[IndexOutOfRangeException alloc] initWithFormat:@"index %d out of range in string %x of length %d", anIndex, self, length]); // UNICODE range.location = anIndex; range.length = 1; return range; } /* Converting string contents into a property list */ - propertyList { extern id readPropertyListFrom(NSString* string); return readPropertyListFrom(self); } - (NSMutableDictionary*)propertyListFromStringsFileFormat { extern id readDictionary(NSString *_string); return readDictionary(self); } /* Identifying and comparing strings */ - (NSComparisonResult)caseInsensitiveCompare:(NSString*)aString { NSRange range = {0, [self length]}; return [self compare:aString options:NSCaseInsensitiveSearch range:range]; } - (NSComparisonResult)compare:(id)aString { NSRange range = {0, [self length]}; return [self compare:aString options:0 range:range]; } - (NSComparisonResult)compare:(NSString*)aString options:(unsigned int)mask { NSRange range = {0, [self length]}; return [self compare:aString options:mask range:range]; } - (NSComparisonResult)compare:(NSString*)aString options:(unsigned int)mask range:(NSRange)aRange { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return NSOrderedSame; } - (BOOL)hasPrefix:(NSString*)aString { int mLen = [self length]; int aLen = [aString length]; NSRange range = {0, aLen}; if (aLen > mLen) return NO; return [self compare:aString options:0 range:range] == NSOrderedSame; } - (BOOL)hasSuffix:(NSString*)aString { int mLen = [self length]; int aLen = [aString length]; NSRange range = {mLen-aLen, aLen}; if (aLen > mLen) return NO; return [self compare:aString options:0 range:range] == NSOrderedSame; } - (BOOL)isEqual:(id)anObject { if (self == anObject) return YES; if ([anObject isKindOfClass:[NSString class]]) { NSRange range = {0, [self length]}; return [self compare:anObject options:0 range:range] == NSOrderedSame; } return NO; } - (BOOL)isEqualToString:(NSString*)aString { NSRange range = {0, [self length]}; if (self == aString) return YES; return [self compare:aString options:0 range:range] == NSOrderedSame; } - (unsigned int)hash { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return 0; } /* Getting a shared prefix */ - (NSString*)commonPrefixWithString:(NSString*)aString options:(unsigned int)mask { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return nil; } /* Changing case */ - (NSString*)capitalizedString { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return nil; } - (NSString*)lowercaseString { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return nil; } - (NSString*)uppercaseString { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return nil; } /* Getting C strings */ - (const char*)cString { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return NULL; } - (unsigned int)cStringLength { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return 0; } - (void)getCString:(char*)buffer { NSRange range = {0, [self length]}; [self getCString:buffer maxLength:NSMaximumStringLength range:range remainingRange:NULL]; } - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength { NSRange range = {0, [self length]}; [self getCString:buffer maxLength:maxLength range:range remainingRange:NULL]; } - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; } /* Getting numeric values */ - (double)doubleValue { // UNICODE // ENCODINGS double val = 0; const char *str = [self cString]; sscanf(str ? str : "", " %lf ", &val); return val; } - (float)floatValue { // UNICODE // ENCODINGS float val = 0; const char *str = [self cString]; sscanf(str ? str : "", " %f ", &val); return val; } - (int)intValue { // UNICODE // ENCODINGS int val = 0; const char *str = [self cString]; sscanf(str ? str : "", " %d ", &val); return val; } /* Working with encodings */ + (NSStringEncoding*)availableStringEncodings { // UNICODE // ENCODINGS static NSStringEncoding availableEncodings[] = { NSASCIIStringEncoding, 0 }; return availableEncodings; } + (NSStringEncoding)defaultCStringEncoding { // UNICODE // ENCODINGS return NSASCIIStringEncoding; } + (NSString*)localizedNameOfStringEncoding:(NSStringEncoding)encoding { switch(encoding) { case NSASCIIStringEncoding: return @"NSASCIIStringEncoding"; case NSNEXTSTEPStringEncoding: return @"NSNEXTSTEPStringEncoding"; case NSJapaneseEUCStringEncoding: return @"NSJapaneseEUCStringEncoding"; case NSUTF8StringEncoding: return @"NSUTF8StringEncoding"; case NSISOLatin1StringEncoding: return @"NSISOLatin1StringEncoding"; case NSSymbolStringEncoding: return @"NSSymbolStringEncoding"; case NSNonLossyASCIIStringEncoding: return @"NSNonLossyASCIIStringEncoding"; case NSShiftJISStringEncoding: return @"NSShiftJISStringEncoding"; case NSISOLatin2StringEncoding: return @"NSISOLatin2StringEncoding"; case NSUnicodeStringEncoding: return @"NSUnicodeStringEncoding"; case NSAdobeStandardCyrillicStringEncoding: return @"NSAdobeStandardCyrillicStringEncoding"; case NSWinLatin1StringEncoding: return @"NSWinLatin1StringEncoding"; default: return @"Invalid encoding"; } } - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding { id data = [self dataUsingEncoding:encoding allowLossyConversion:NO]; return data ? YES : NO; } - (NSData*)dataUsingEncoding:(NSStringEncoding)encoding { return [self dataUsingEncoding:encoding allowLossyConversion:NO]; } - (NSData*)dataUsingEncoding:(NSStringEncoding)encoding allowLossyConversion:(BOOL)flag { // UNICODE // ENCODINGS [self notImplemented:_cmd]; return nil; } - (NSStringEncoding)fastestEncoding { // UNICODE // ENCODINGS return NSASCIIStringEncoding; } - (NSStringEncoding)smallestEncoding { // UNICODE // ENCODINGS return NSASCIIStringEncoding; } - (BOOL)getBytes:(void*)bytes maxLength:(unsigned int)maxLength inEncoding:(NSStringEncoding)encoding allowLossesInConversion:(BOOL)allowLossesInConversion fromRange:(NSRange)fromRange usedRange:(NSRange*)usedRange remainingRange:(NSRange*)remainingRange { // UNICODE // ENCODINGS [self notImplemented:_cmd]; return NO; } /* Writing to a file */ - (BOOL)writeToFile:(NSString*)path atomically:(BOOL)flag { // UNICODE [self subclassResponsibility:_cmd]; return NO; } /* Encoding methods */ - (void)encodeWithCoder:(NSCoder*)aCoder { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; } - initWithCoder:(NSCoder*)aDecoder { // UNICODE // ENCODINGS [self subclassResponsibility:_cmd]; return nil; } /* NSCopying methods */ - (id)copyWithZone:(NSZone*)zone { return [[NSString allocWithZone:zone] initWithString:self]; } /* NSMutableCopying methods */ - (id)mutableCopyWithZone:(NSZone*)zone { return [[NSMutableString allocWithZone:zone] initWithString:self]; } /* NSObject protocol */ - (NSString*)description { return self; } @end /* NSString */ /********************************* * NSMutableString abstract class *********************************/ @implementation NSMutableString /* * Modifying a string */ - (void)appendFormat:(NSString*)format,... { va_list va; va_start(va, format); [self appendFormat:format arguments:va]; va_end(va); } - (void)appendFormat:(NSString*)format arguments:(va_list)argList; { // FIX : Vsprinf(self, format, argList) [self appendString:Avsprintf(format, argList)]; } - (void)appendString:(NSString*)aString { NSRange range = {[self length], 0}; [self replaceCharactersInRange:range withString:aString]; } - (void)prependFormat:(NSString*)format,... { NSRange range = {0, 0}; va_list va; va_start(va, format); [self replaceCharactersInRange:range withString:Avsprintf(format, va)]; va_end(va); } - (void)prependFormat:(NSString*)format arguments:(va_list)argList { NSRange range = {0, 0}; [self replaceCharactersInRange:range withString:Avsprintf(format, argList)]; } - (void)prependString:(NSString*)aString { NSRange range = {0, 0}; [self replaceCharactersInRange:range withString:aString]; } - (void)deleteCharactersInRange:(NSRange)range { [self replaceCharactersInRange:range withString:nil]; } - (void)insertString:(NSString*)aString atIndex:(unsigned)index { NSRange range = {index, 0}; [self replaceCharactersInRange:range withString:aString]; } - (void)setString:(NSString*)aString { NSRange range = {0, [self length]}; [self replaceCharactersInRange:range withString:aString]; } - (void)replaceCharactersInRange:(NSRange)aRange withString:(NSString*)aString { [self subclassResponsibility:_cmd]; } - (id)copyWithZone:(NSZone*)zone { return [[NSString allocWithZone:zone] initWithString:self]; } @end /* NSMutableString */ /********************************* * NSString creation methods *********************************/ @implementation NSString(NSStringCreation) + (id)allocWithZone:(NSZone *)zone { return (self == [NSString class]) ? [NSTemporaryString allocWithZone:zone] : NSAllocateObject(self, 0, zone); } + (id)localizedStringWithFormat:(NSString*)format,... { va_list va; NSString* string; va_start(va, format); string = [[[self alloc] initWithFormat:format arguments:va] autorelease]; va_end(va); return string; } + (id)stringWithCharacters:(const unichar*)chars length:(unsigned int)length { return [[[self alloc] initWithCharacters:chars length:length] autorelease]; } + (id)stringWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length freeWhenDone:(BOOL)flag { return [[[self alloc] initWithCharactersNoCopy:chars length:length freeWhenDone:flag] autorelease]; } + (id)stringWithCString:(const char*)byteString { return [[[self alloc] initWithCString:byteString] autorelease]; } + (id)stringWithCString:(const char*)byteString length:(unsigned int)length { return [[[self alloc] initWithCString:byteString length:length] autorelease]; } + (id)stringWithCStringNoCopy:(char*)byteString length:(unsigned int)length freeWhenDone:(BOOL)flag { return [[[self alloc] initWithCStringNoCopy:byteString length:length freeWhenDone:flag] autorelease]; } + (NSString*)stringWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag { return [[[self alloc] initWithCStringNoCopy:byteString freeWhenDone:flag] autorelease]; } + (id)stringWithFormat:(NSString*)format,... { va_list va; NSString* string; va_start(va, format); string = [[[self alloc] initWithFormat:format arguments:va] autorelease]; va_end(va); return string; } + (id)stringWithFormat:(NSString*)format arguments:(va_list)argList { return [[[self alloc] initWithFormat:format arguments:argList] autorelease]; } + (id)stringWithContentsOfFile:(NSString*)path { return [[[self alloc] initWithContentsOfFile:path] autorelease]; } @end /* NSString(NSStringCreation) */ @implementation NSMutableString(NSStringCreation) + (id)allocWithZone:(NSZone *)zone { return (self == [NSMutableString class]) ? [NSMutableTemporaryString allocWithZone:zone] : NSAllocateObject(self, 0, zone); } + (id)stringWithCapacity:(unsigned int)capacity { return [[[self alloc] initWithCapacity:capacity] autorelease]; } @end /* NSMutableString(NSStringCreation) */ /**************************** * Initializing strings ****************************/ @implementation NSMutableString(NSStringInitialization) - initWithCapacity:(unsigned int)capacity { [self subclassResponsibility:_cmd]; return nil; } - initWithCharacters:(const unichar*)chars length:(unsigned int)length { [self notImplemented:_cmd]; return nil; } - initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length freeWhenDone:(BOOL)flag { [self notImplemented:_cmd]; return nil; } - initWithCString:(const char*)byteString { return[self initWithString:[[[NSString alloc] initWithCStringNoCopy:(char*)byteString freeWhenDone:NO] autorelease]]; } - initWithCString:(const char*)byteString length:(unsigned int)length { return [self initWithString:[[[NSString alloc] initWithCStringNoCopy:(char*)byteString length:length freeWhenDone:NO] autorelease]]; } - initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag { return [self initWithString:[[[NSString alloc] initWithCStringNoCopy:byteString freeWhenDone:flag] autorelease]]; } - initWithCStringNoCopy:(char*)byteString length:(unsigned int)length freeWhenDone:(BOOL)flag { return[self initWithString:[[[NSString alloc] initWithCStringNoCopy:byteString length:length freeWhenDone:flag] autorelease]]; } - initWithString:(NSString*)aString { [self subclassResponsibility:_cmd]; return nil; } - initWithFormat:(NSString*)format, ... { id str; va_list va; va_start(va, format); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format arguments:(va_list)argList { return [self initWithString:Avsprintf(format, argList)]; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary, ... { id str; va_list va; va_start(va, dictionary); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary arguments:(va_list)argList { return [self initWithFormat:format arguments:argList]; } - initWithData:(NSData*)data encoding:(NSStringEncoding)encoding { // UNICODE // ENCODINGS [self notImplemented:_cmd]; return nil; } - initWithContentsOfFile:(NSString*)path { // UNICODE // ENCODINGS [self notImplemented:_cmd]; return nil; } @end /**************************** * Allocate concrete strings ****************************/ /* * Classes used for allocation of NSString concrete instances */ @implementation NSTemporaryString + allocWithZone:(NSZone*)zone { // OPT - keep a list of deallocated but not freed instances here NSTemporaryString* obj = NSAllocateObject(self, 0, zone); obj->_zone = zone; return obj; } - (void)collect { [self dealloc]; } - (NSZone*)zone { return _zone; } /* * Methods that return strings */ - init { id str = @""; [self collect]; return str; } - initWithCharacters:(const unichar*)chars length:(unsigned int)length { // UNICODE [self notImplemented:_cmd]; [self collect]; return nil; } - initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length freeWhenDone:(BOOL)flag { // UNICODE [self notImplemented:_cmd]; [self collect]; return nil; } - initWithCString:(const char*)byteString { int length = Strlen(byteString); id str = [[NSInline8BitString allocForCapacity:length zone:_zone] initWithCString:byteString length:length]; [self collect]; return str; } - initWithCString:(const char*)byteString length:(unsigned int)length { id str = [[NSInline8BitString allocForCapacity:length zone:_zone] initWithCString:byteString length:length]; [self collect]; return str; } - initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag { id str = flag ? [NSOwned8BitString allocWithZone:_zone] : [NSNonOwned8BitString allocWithZone:_zone]; str = [str initWithCString:byteString length:Strlen(byteString) copy:NO]; [self collect]; return str; } - initWithCStringNoCopy:(char*)byteString length:(unsigned int)length freeWhenDone:(BOOL)flag { id str = flag ? [NSOwnedOpen8BitString allocWithZone:_zone] : [NSNonOwnedOpen8BitString allocWithZone:_zone]; str = [str initWithCString:byteString length:length copy:NO]; [self collect]; return str; } - initWithString:(NSString*)aString { id str = [aString copyWithZone:_zone]; [self collect]; return str; } - initWithFormat:(NSString*)format, ... { id str; va_list va; va_start(va, format); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format arguments:(va_list)argList { id str = Avsprintf(format, argList); [self collect]; return [str copyWithZone:_zone]; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary, ... { id str; va_list va; va_start(va, dictionary); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary arguments:(va_list)argList { return [self initWithFormat:format arguments:argList]; } - initWithData:(NSData*)data encoding:(NSStringEncoding)encoding { // UNICODE [self notImplemented:_cmd]; [self collect]; return nil; } - initWithContentsOfFile:(NSString*)path { id str; int fd = open([path cString], O_RDONLY); struct stat fstat_buf; char* bytes = NULL; if((fd == -1) || (fstat(fd, &fstat_buf) == -1)) return nil; bytes = NSZoneMalloc(_zone, fstat_buf.st_size + 1); if (read(fd, bytes, fstat_buf.st_size) != fstat_buf.st_size) { Free(bytes); return nil; } close(fd); bytes[fstat_buf.st_size]=0; str = [[NSOwned8BitString allocWithZone:_zone] initWithCString:bytes length:fstat_buf.st_size copy:NO]; [self collect]; return str; } @end /* NSTemporaryString */ @implementation NSMutableTemporaryString + allocWithZone:(NSZone*)zone { // OPT - keep a list of deallocated but not freed instances here NSMutableTemporaryString* obj = NSAllocateObject(self, 0, zone); obj->_zone = zone; return obj; } - (void)collect { [self release]; } /* * Methods that return strings */ - initWithCapacity:(unsigned int)capacity { id str = [[NSMutableSimple8BitString allocWithZone:_zone] initWithCapacity:capacity]; [self collect]; return str; } - init { id str = [[NSMutableSimple8BitString allocWithZone:_zone] init]; [self collect]; return str; } - initWithCString:(const char*)byteString { int length = Strlen(byteString); id str = [[NSMutableSimple8BitString allocWithZone:_zone] initWithCString:(char*)byteString length:length copy:YES]; [self collect]; return str; } - initWithCString:(const char*)byteString length:(unsigned int)length { id str = [[NSMutableSimple8BitString allocWithZone:_zone] initWithCString:(char*)byteString length:length copy:YES]; [self collect]; return str; } - initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag { id str = [NSMutableSimple8BitString allocWithZone:_zone]; str = [str initWithCString:byteString length:Strlen(byteString) copy:!flag]; [self collect]; return str; } - initWithCStringNoCopy:(char*)byteString length:(unsigned int)length freeWhenDone:(BOOL)flag { id str = [NSMutableSimple8BitString allocWithZone:_zone]; str = [str initWithCString:byteString length:Strlen(byteString) copy:!flag]; [self collect]; return str; } - initWithString:(NSString*)aString { id str = [[NSMutableSimple8BitString allocWithZone:_zone] initWithString:aString]; [self collect]; return str; } - initWithFormat:(NSString*)format, ... { id str; va_list va; va_start(va, format); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format arguments:(va_list)argList { id str = [[NSMutableSimple8BitString allocWithZone:_zone] init]; [str appendFormat:format arguments:argList]; [self collect]; return str; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary, ... { id str; va_list va; va_start(va, dictionary); str = [self initWithFormat:format arguments:va]; va_end(va); return str; } - initWithFormat:(NSString*)format locale:(NSDictionary*)dictionary arguments:(va_list)argList { return [self initWithFormat:format arguments:argList]; } - initWithData:(NSData*)data encoding:(NSStringEncoding)encoding { // UNICODE [self notImplemented:_cmd]; [self collect]; return nil; } - initWithContentsOfFile:(NSString*)path { id str; int fd = open([path cString], O_RDONLY); struct stat fstat_buf; char* bytes = NULL; if((fd == -1) || (fstat(fd, &fstat_buf) == -1)) return nil; bytes = NSZoneMalloc(_zone, fstat_buf.st_size + 1); if (read(fd, bytes, fstat_buf.st_size) != fstat_buf.st_size) { Free(bytes); return nil; } close(fd); bytes[fstat_buf.st_size]=0; str = [[NSMutableSimple8BitString allocWithZone:_zone] initWithCString:bytes length:fstat_buf.st_size copy:NO]; [self collect]; return str; } @end /* NSMutableTemporaryString */ /* * Used for forcing linking of this category */ static void __dummyNSStringfile () { extern void __dummyNSStringFilePathfile(); __dummyNSStringFilePathfile(); __dummyNSStringfile(); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.