/libFoundation/Foundation/NSString.m
http://sope-appserver.googlecode.com/ · Objective C · 2495 lines · 1871 code · 437 blank · 187 comment · 344 complexity · 2a48239224ce3d32fc94baa473eb857e MD5 · raw file
Large files are truncated click here to view the full file
- /*
- 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 <stdio.h>
- #include <ctype.h>
- #include <Foundation/common.h>
- #include <Foundation/NSArray.h>
- #include <Foundation/NSAutoreleasePool.h>
- #include <Foundation/NSData.h>
- #include <Foundation/NSDictionary.h>
- #include <Foundation/NSCoder.h>
- #include <Foundation/NSURL.h>
- #include <Foundation/NSURLHandle.h>
- #include <Foundation/NSException.h>
- #include <Foundation/exceptions/StringExceptions.h>
- #include <Foundation/exceptions/GeneralExceptions.h>
- #include <Foundation/PropertyListParser.h>
- #include <Foundation/NSCharacterSet.h>
- #include <Foundation/NSString.h>
- #include <Foundation/NSThread.h>
- #include <Foundation/NSNotification.h>
- #include <Foundation/NSConcreteString.h>
- #include <Foundation/NSPathUtilities.h>
- #include <Foundation/NSByteOrder.h>
- #include "PrivateThreadData.h"
- #include "NSObject+PropLists.h"
- #include <locale.h>
- #include <netinet/in.h>
- int NSConvertUTF16toUTF8(unichar **sourceStart,
- const unichar *sourceEnd,
- unsigned char **targetStart,
- const unsigned char *targetEnd);
- int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd,
- unichar **targetStart, const unichar *targetEnd);
- id NSInitStringWithData(NSString *self, NSData *data,
- NSStringEncoding encoding);
- NSData *dataUsingEncoding(NSString *self,
- NSStringEncoding encoding, BOOL flag);
- /*
- 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.
- */
- #define USE_SINGLE8BITSTRING 1
- // #define HAS_UNICODE_STRING 1
- /***************************
- * NSString abstract class
- ***************************/
- #if USE_SINGLE8BITSTRING
- static id Single8BitStringStore[256];
- static Class Single8BitStringClass = Nil;
- static inline id _getSingle8BitString(unsigned char _byte) {
- register id str;
-
- if (Single8BitStringClass == Nil) {
- Single8BitStringClass = [NSCharacter8BitString class];
- memset(Single8BitStringStore, 0, sizeof(Single8BitStringStore));
- }
-
- if ((str = Single8BitStringStore[(int)_byte]) == nil) {
- str = [[Single8BitStringClass allocWithZone:nil]
- initWithCString:(char *)&_byte length:1];
- Single8BitStringStore[(unsigned int)_byte] = str;
- #if DEBUG && 0
- printf("%s: add str[%p] for char %c\n", __PRETTY_FUNCTION__,
- str, _byte);
- #endif
- }
- return str;
- }
- #endif
- @implementation NSString
- static Class NSStringClass = Nil;
- + (void)initialize
- {
- const char *cstr;
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- #ifndef __WIN32__
- /* required for toupper/tolower to work with umlauts */
- if ((cstr = getenv("LC_CTYPE")))
- setlocale(LC_CTYPE, cstr);
- if ((cstr = getenv("LC_COLLATE")))
- setlocale(LC_COLLATE, cstr);
- #endif
-
- 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
- {
- register unsigned int i = 0;
- IMP imp = [self methodForSelector:@selector(characterAtIndex:)];
- if (aRange.location + aRange.length > [self length]) {
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"range (%d,%d) in string %x of length %d",
- aRange.location, aRange.length, self, [self length]] raise];
- }
-
- for (i = 0; i < aRange.length; i++) {
- buffer[i] = (unichar)(long)(*imp)(self, @selector(characterAtIndex:),
- aRange.location + i);
- }
- }
- /* Combining strings */
- - (NSString *)stringByAppendingString:(NSString *)aString
- {
- unichar *buf;
- unsigned len1, len2;
- NSString *s;
-
- len1 = [self length];
- len2 = [aString length];
-
- if (len2 == 0)
- return [[self copy] autorelease];
-
- buf = calloc(len1 + len2 + 1, sizeof(unichar));
- [self getCharacters:buf];
- [aString getCharacters:&(buf[len1])];
- buf[len1 + len2] = 0;
- s = [NSStringClass stringWithCharacters:buf length:(len1 + len2)];
- free(buf);
- return s;
- }
- - (NSString*)stringByAppendingFormat:(NSString*)format,...
- {
- NSMutableString *string = [self mutableCopy];
- va_list va;
-
- va_start(va, format);
- [string appendFormat:format arguments:va];
- va_end(va);
- return AUTORELEASE(string);
- }
- - (NSString*)stringByAppendingFormat:(NSString*)format
- arguments:(va_list)argList
- {
- NSMutableString *string = [self mutableCopy];
- [string appendFormat:format arguments:argList];
- return AUTORELEASE(string);
- }
- - (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
- {
- unsigned int first = 0, last = 0;
- unsigned int slen;
- NSMutableArray *components;
- if ((slen = [separator length]) == 0)
- return [NSArray arrayWithObject:self];
- if ([self length] == 0)
- return [NSArray arrayWithObject:self];
-
- components = [NSMutableArray arrayWithCapacity:16];
- while ((first = [self indexOfString:separator fromIndex:last]) !=NSNotFound) {
- NSRange range;
- NSString *substring;
- range.location = last;
- range.length = (first - last);
- substring = [self substringWithRange:range];
- [components addObject:substring];
- last = first + slen;
- }
-
- if ([self length] >= last) {
- NSString *lastComponent;
-
- lastComponent = [self substringFromIndex:last];
- [components addObject:lastComponent];
- }
- return components;
- }
- - (NSString *)substringWithRange:(NSRange)aRange
- {
- unichar * buf;
- id rc;
- if (aRange.location + aRange.length > [self length] )
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"range (%d,%d) in string %x of length %d",
- aRange.location, aRange.length, self, [self length]] raise];
- if (aRange.length == 0)
- return @"";
- buf = MallocAtomic(sizeof(unichar) * (aRange.length + 1));
- [self getCharacters:buf range:aRange];
- rc = AUTORELEASE([[NSStringClass alloc]
- initWithCharactersNoCopy:buf
- length:aRange.length
- freeWhenDone:YES]);
- return rc;
- }
- - (NSString *)substringFromRange:(NSRange)aRange
- {
- return [self substringWithRange:aRange];
- }
- - (NSString *)substringFromIndex:(unsigned int)index
- {
- NSRange range;
-
- range.location = index;
- range.length = [self length]; //- index
- if (range.length < index) {
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"index %d in string %x of length %d",
- index, self, [self length]] raise];
- }
- range.length -= index;
-
- return [self substringWithRange:range];
- }
- - (NSString*)substringToIndex:(unsigned int)index
- {
- NSRange range = {0, index};
- return [self substringWithRange:range];
- }
- - (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)_set
- {
- unsigned len;
- unichar *buf;
- unsigned idx;
- unsigned ridx;
- BOOL (*isMem)(id,SEL,unichar);
-
- if ((len = [self length]) == 0)
- return [[self copy] autorelease];
-
- buf = calloc(len + 1, sizeof(unichar));
- [self getCharacters:buf];
-
- isMem = (void *)[_set methodForSelector:@selector(characterIsMember:)];
-
- for (idx = 0;
- (idx < len) && isMem(_set,@selector(characterIsMember:),buf[idx]);
- idx++)
- ;
- for (ridx = len-1;
- (ridx >= idx) && isMem(_set,@selector(characterIsMember:),buf[ridx]);
- ridx--)
- ;
-
- self = [NSStringClass stringWithCharacters:&(buf[idx])
- length:((ridx+1) - idx)];
- free(buf);
- return self;
- }
- /* 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
- // ENCODINGS - this code applies to the system's default encoding
- SEL characterIsMemberSel = @selector(characterIsMember:);
- IMP imp = [aSet methodForSelector:characterIsMemberSel];
- if (NSMaxRange(aRange) > [self length])
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"range %@ not in string 0x%08x of length %d",
- NSStringFromRange(aRange), self, [self length]] raise];
- if (mask & NSBackwardsSearch) {
- int i;
-
- for (i = aRange.length - 1; i >= aRange.location; i--) {
- unichar c = [self characterAtIndex:i];
- if ((*imp)(aSet, characterIsMemberSel, c) ||
- ((mask & NSCaseInsensitiveSearch)
- && ((islower(c)
- && (*imp)(aSet, characterIsMemberSel, toupper(c)))
- || (isupper(c)
- && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
- return NSMakeRange(i, 1);
- }
- }
- }
- else {
- unsigned int i, max;
- max = NSMaxRange(aRange);
- for (i = aRange.location; i < max; i++) {
- unichar c = [self characterAtIndex:i];
- if ((*imp)(aSet, characterIsMemberSel, c) ||
- ((mask & NSCaseInsensitiveSearch) &&
- ((islower(c)
- && (*imp)(aSet, characterIsMemberSel, toupper(c)))
- || (isupper(c)
- && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
- return NSMakeRange(i, 1);
- }
- }
- }
- return NSMakeRange(NSNotFound, 0);
- }
- - (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 - this code applies to the system's default encoding
- // islower needs to be replaced with proper NSCharacterSet calls (speed?)
- unsigned int i, a;
- NSRange range;
- if (aRange.location + aRange.length > [self length]) {
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"range (%d,%d) in string %x of length %d",
- aRange.location, aRange.length, self, [self length]] raise];
- }
-
- a = [aString length];
-
- if (a == 0 || aRange.length < a)
- return NSMakeRange(0,0);
- if (mask & NSAnchoredSearch) {
- range.location = aRange.location +
- ((mask & NSBackwardsSearch) ? aRange.length - a : 0);
- range.length = a;
-
- if ([self compare:aString options:mask range:range] == NSOrderedSame)
- return range;
- else
- return NSMakeRange(NSNotFound, 0);
- }
- if (mask & NSBackwardsSearch) {
- if (mask & NSCaseInsensitiveSearch) {
- // Backward case insensitive
- unichar cf;
- int n;
-
- cf = [aString characterAtIndex: 0 ];
- cf = islower(cf) ? toupper(cf) : cf;
- for (n = aRange.length - a; n >= 0; n--) {
- unichar ca = cf;
- unichar cm = [self characterAtIndex:n + aRange.location ];
- cm = islower(cm) ? toupper(cm) : cm;
- if (cm != ca)
- continue;
- for (i = 1; i < a; i++) {
- cm = [self characterAtIndex:n + i + aRange.location ];
- ca = [aString characterAtIndex:i];
- cm = islower(cm) ? toupper(cm) : cm;
- ca = islower(ca) ? toupper(ca) : ca;
- if (cm != ca)
- break;
- }
- if (i == a) {
- range.location = aRange.location + n;
- range.length = a;
- return range;
- }
- }
- }
- else {
- // Backward case sensitive
- int n;
-
- for (n = aRange.length - a; n >= 0; n--) {
- if ([self characterAtIndex:n + aRange.location]
- != [aString characterAtIndex:0])
- continue;
- for (i = 1; i < a; i++)
- if ([self characterAtIndex:(n + i + aRange.location)]
- != [aString characterAtIndex: i] )
- break;
- if (i == a) {
- range.location = aRange.location + n;
- range.length = a;
- return range;
- }
- }
- }
- }
- else {
- if (mask & NSCaseInsensitiveSearch) {
- // Forward case insensitive
- unsigned int n;
- unichar cf;
-
- cf = [aString characterAtIndex: n];
- cf = islower(cf) ? toupper(cf) : cf;
- for (n = 0; n + a <= aRange.length; n++) {
- unichar ca = cf;
- unichar cm = [self characterAtIndex: n + aRange.location ];
- cm = islower(cm) ? toupper(cm) : cm;
-
- if (cm != ca)
- continue;
- for (i = 1; i < a; i++) {
- cm = [self characterAtIndex:n + i + aRange.location];
- ca = [aString characterAtIndex:i];
- cm = islower(cm) ? toupper(cm) : cm;
- ca = islower(ca) ? toupper(ca) : ca;
- if (cm != ca)
- break;
- }
- if (i == a) {
- range.location = aRange.location + n;
- range.length = a;
- return range;
- }
- }
- }
- else {
- // Forward case sensitive
- unsigned int n;
- for (n = 0; n + a <= aRange.length; n++) {
- if ([self characterAtIndex:n + aRange.location]
- != [aString characterAtIndex: 0] )
- continue;
- for (i = 1; i < a; i++)
- if ([self characterAtIndex:n + i + aRange.location]
- != [aString characterAtIndex:i])
- break;
- if (i == a) {
- range.location = aRange.location + n;
- range.length = a;
- return range;
- }
- }
- }
- }
-
- range.location = NSNotFound;
- range.length = 0;
- 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;
- unsigned int length = [self length];
-
- if (anIndex >= length) {
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"index %d out of range in string %x of length %d",
- anIndex, self, length] raise];
- }
- // UNICODE
- range.location = anIndex;
- range.length = 1;
- return range;
- }
- /* Converting string contents into a property list */
- - (id)propertyList
- {
- return NSParsePropertyListFromString(self);
- }
- - (NSMutableDictionary*)propertyListFromStringsFileFormat
- {
- return NSParseStringsFromString(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 - this code applies to the system's default encoding
- unsigned int i, n, a;
- if (NSMaxRange(aRange) > [self length]) {
- [[[IndexOutOfRangeException alloc] initWithFormat:@"range %@ in string %x of length %d",
- NSStringFromRange(aRange), self, [self length]] raise];
- }
-
- a = [aString length];
- n = MIN(a, aRange.length);
- if (mask & NSCaseInsensitiveSearch) {
- for (i = 0; i < n; i++) {
- unichar cm = [self characterAtIndex:i + aRange.location];
- unichar ca = [aString characterAtIndex:i];
- cm = islower(cm) ? toupper(cm) : cm;
- ca = islower(ca) ? toupper(ca) : ca;
- if (cm < ca)
- return NSOrderedAscending;
- if (cm > ca)
- return NSOrderedDescending;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- if ([self characterAtIndex:i + aRange.location] <
- [aString characterAtIndex:i])
- return NSOrderedAscending;
- if ([self characterAtIndex:i + aRange.location] >
- [aString characterAtIndex:i])
- return NSOrderedDescending;
- }
- }
- if (aRange.length < a)
- return NSOrderedAscending;
- if (aRange.length > a)
- return NSOrderedDescending;
- return NSOrderedSame;
- }
- - (BOOL)hasPrefix:(NSString *)aString
- {
- int mLen = [self length];
- int aLen = [aString length];
- NSRange range = {0, aLen};
- #if DEBUG
- if (aString == nil) {
- NSLog(@"NOTE: [%@ hasPrefix:nil] does not work on MacOSX !", aString);
- #if 0 && DEBUG
- # warning ABORT CODE ENABLED - do not deploy!
- abort();
- #endif
- }
- #endif
-
- if (aLen == 0)
- return NO;
-
- 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 == 0)
- return NO;
-
- if (aLen > mLen)
- return NO;
-
- return [self compare:aString options:0 range:range] == NSOrderedSame;
- }
- - (BOOL)isEqual:(id)aString
- {
- register Class clazz;
- register BOOL i;
- NSRange range;
-
- if (self == aString)
- return YES;
- else if (aString == nil)
- return NO;
-
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
-
- i = NO;
- for (clazz = *(id *)aString; clazz; clazz = class_get_super_class(clazz)) {
- if (clazz == NSStringClass) {
- i = YES;
- break;
- }
- }
- if (i == NO)
- return NO;
-
- range.location = 0;
- range.length = [self length];
- return [self compare:aString options:0 range:range] == NSOrderedSame;
- }
- - (BOOL)isEqualToString:(NSString*)aString
- {
- NSRange range;
-
- if (self == aString)
- return YES;
- else if (aString == nil)
- return NO;
-
- range.location = 0;
- range.length = [self length];
- return [self compare:aString options:0 range:range] == NSOrderedSame;
- }
- - (unsigned)hash
- {
- unsigned hash = 0, hash2;
- int i, n = [self length];
- for(i = 0; i < n; i++) {
- hash <<= 4;
- // UNICODE - must use a for independent of composed characters
- hash += [self characterAtIndex:i];
- if((hash2 = hash & 0xf0000000))
- hash ^= (hash2 >> 24) ^ hash2;
- }
- return hash;
- }
- /* Getting a shared prefix */
- - (NSString *)commonPrefixWithString:(NSString*)aString
- options:(unsigned int)mask
- {
- NSRange range = {0, 0};
- int mLen;
- int aLen;
- int i;
-
- mLen = [self length];
- aLen = [aString length];
- if ((mLen == 0) || (aLen == 0)) return @"";
-
- for (i = 0; (i < mLen) && (i < aLen); i++) {
- unichar c1, c2;
-
- c1 = [self characterAtIndex:i];
- c2 = [self characterAtIndex:i];
-
- if (mask & NSCaseInsensitiveSearch) {
- // ENCODINGS - this code applies to the system's default encoding
- c1 = tolower(c1);
- c2 = tolower(c2);
- }
-
- if (c1 != c2)
- break;
- }
-
- range.length = i;
- return [self substringWithRange:range];
- }
- /* Changing case */
- - (NSString *)capitalizedString
- {
- // UNICODE
- // ENCODINGS - this code applies to the system's default encoding
- int i;
- BOOL f = YES;
- int length = [self cStringLength];
- unichar* buf = MallocAtomic(sizeof(unichar) * (length + 1));
- for (i = 0; i < length; i++) {
- unichar c = [self characterAtIndex:i];
- if (isspace(c))
- f = YES;
- if (f) {
- buf[i] = islower(c) ? toupper(c) : c;
- f = NO;
- }
- else
- buf[i] = isupper(c) ? tolower(c) : c;
- }
- buf[i] = 0;
- return AUTORELEASE([[NSStringClass alloc]
- initWithCharactersNoCopy:buf
- length:length
- freeWhenDone:YES]);
- }
- - (NSString *)lowercaseString
- {
- // UNICODE
- // ENCODINGS - this code applies to the system's default encoding
- int i;
- int length = [self cStringLength];
- unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
- for (i = 0; i < length; i++) {
- unichar c = [self characterAtIndex:i];
-
- buf[i] = isupper(c) ? tolower(c) : c;
- }
- buf[i] = 0;
- return AUTORELEASE([[NSStringClass alloc]
- initWithCharactersNoCopy:buf
- length:length
- freeWhenDone:YES]);
- }
- - (NSString *)uppercaseString
- {
- // UNICODE
- // ENCODINGS - this code applies to the system's default encoding
- int i;
- int length = [self cStringLength];
- unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
- for (i = 0; i < length; i++) {
- unichar c = [self characterAtIndex:i];
- buf[i] = islower(c) ? toupper(c) : c;
- }
- buf[i] = 0;
- return AUTORELEASE([[NSStringClass alloc]
- initWithCharactersNoCopy:buf
- length:length
- freeWhenDone:YES]);
- }
- /* Getting C strings */
- - (const char *)cString
- {
- // UNICODE
- // ENCODINGS
- [self subclassResponsibility:_cmd];
- return NULL;
- }
- - (unsigned int)cStringLength
- {
- // UNICODE
- // ENCODINGS
- [self subclassResponsibility:_cmd];
- return 0;
- }
- - (const char *)UTF8String
- {
- NSData *d;
- unsigned dlen;
- unsigned char *cstr;
-
- if ((d = [self dataUsingEncoding:NSUTF8StringEncoding]) == nil)
- return NULL;
-
- if ((dlen = [d length]) == 0) {
- static unsigned char c = '\0';
- return (const char *)&c;
- }
-
- cstr = NSZoneMallocAtomic([self zone], sizeof(unsigned char) * (dlen + 1));
- [d getBytes:cstr];
- cstr[dlen] = '\0';
- #if !LIB_FOUNDATION_BOEHM_GC
- [NSAutoreleasedPointer autoreleasePointer:cstr];
- #endif
- return (const char *)cstr;
- }
- - (void)getCString:(char *)buffer
- {
- NSRange range = {0, [self length]};
-
- [self getCString:buffer maxLength:NSMaximumStringLength
- range:range remainingRange:NULL];
- buffer[range.length] = '\0';
- }
- - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
- {
- NSRange range = {0, [self length]};
-
- [self getCString:buffer maxLength:maxLength
- range:range remainingRange:NULL];
- buffer[range.length] = '\0';
- }
- - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
- range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange
- {
- unsigned int toMove, i, cLength;
- unichar (*charAtIndex)(id,SEL,int);
- charAtIndex = (void*)[self methodForSelector:@selector(characterAtIndex:)];
-
- toMove = MIN(maxLength, aRange.length);
- cLength = [self cStringLength];
-
- if (aRange.location + aRange.length > cLength) {
- [[[IndexOutOfRangeException alloc]
- initWithFormat:@"range (%d,%d) in string %x of length %d",
- aRange.location, aRange.length, self, cLength] raise];
- }
- if (leftoverRange) {
- leftoverRange->location = aRange.location + toMove;
- leftoverRange->length = cLength - leftoverRange->location;
- }
- for (i = 0; i < toMove; i++) {
- buffer[i] = charAtIndex(self, @selector(characterAtIndex:),
- aRange.location + i);
- }
- if (toMove < maxLength)
- buffer[toMove] = '\0';
- }
- /* Getting numeric values */
- - (double)doubleValue
- {
- // UNICODE
- // ENCODINGS
- double val = 0.0;
- unsigned len;
- char *str;
-
- len = [self cStringLength];
- if (len == 0)
- return 0.0;
- if ((str = malloc(len + 1)) == NULL)
- return 0.0;
-
- [self getCString:str]; str[len] = '\0';
- sscanf(str ? str : "", " %lf ", &val);
- free(str);
- return val;
- }
- - (float)floatValue
- {
- // UNICODE
- // ENCODINGS
- float val = 0;
- unsigned len;
- char *str;
-
- if ((len = [self cStringLength]) == 0)
- return 0.0;
- if ((str = malloc(len + 1)) == NULL)
- return 0.0;
-
- [self getCString:str]; str[len] = '\0';
- sscanf(str ? str : "", " %f ", &val);
- free(str);
- return val;
- }
- - (int)intValue
- {
- // UNICODE
- // ENCODINGS
- int val = 0;
- unsigned len;
- char *str;
-
- if ((len = [self cStringLength]) == 0)
- return 0;
- if ((str = malloc(len + 1)) == NULL)
- return 0;
- [self getCString:str]; str[len] = '\0';
- sscanf(str ? str : "", " %d ", &val);
- free(str);
- return val;
- }
- /* Working with encodings */
- + (NSStringEncoding *)availableStringEncodings
- {
- // UNICODE
- // ENCODINGS
- static NSStringEncoding availableEncodings[] = {
- NSASCIIStringEncoding,
- NSISOLatin1StringEncoding,
- NSISOLatin9StringEncoding,
- NSUTF8StringEncoding,
- NSUnicodeStringEncoding,
- 0
- };
-
- return availableEncodings;
- }
- + (NSStringEncoding)defaultCStringEncoding
- {
- // UNICODE
- // ENCODINGS
- #if USE_LATIN9
- return NSISOLatin9StringEncoding;
- #else
- return NSISOLatin1StringEncoding;
- #endif
- }
- + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
- {
- switch(encoding) {
- case NSASCIIStringEncoding: return @"NSASCIIStringEncoding";
- case NSNEXTSTEPStringEncoding: return @"NSNEXTSTEPStringEncoding";
- case NSUTF8StringEncoding: return @"NSUTF8StringEncoding";
- case NSISOLatin1StringEncoding: return @"NSISOLatin1StringEncoding";
- case NSISOLatin9StringEncoding: return @"NSISOLatin9StringEncoding";
- case NSSymbolStringEncoding: return @"NSSymbolStringEncoding";
- case NSShiftJISStringEncoding: return @"NSShiftJISStringEncoding";
- case NSISOLatin2StringEncoding: return @"NSISOLatin2StringEncoding";
- case NSUnicodeStringEncoding: return @"NSUnicodeStringEncoding";
- case NSWinLatin1StringEncoding: return @"NSWinLatin1StringEncoding";
- case NSISO2022JPStringEncoding: return @"NSISO2022JPStringEncoding";
- case NSWindowsCP1251StringEncoding:
- return @"NSWindowsCP1251StringEncoding";
- case NSWindowsCP1252StringEncoding:
- return @"NSWindowsCP1252StringEncoding";
- case NSWindowsCP1253StringEncoding:
- return @"NSWindowsCP1253StringEncoding";
- case NSWindowsCP1254StringEncoding:
- return @"NSWindowsCP1254StringEncoding";
- case NSWindowsCP1250StringEncoding:
- return @"NSWindowsCP1250StringEncoding";
-
- case NSNonLossyASCIIStringEncoding:
- return @"NSNonLossyASCIIStringEncoding";
- case NSJapaneseEUCStringEncoding:
- return @"NSJapaneseEUCStringEncoding";
- case NSAdobeStandardCyrillicStringEncoding:
- return @"NSAdobeStandardCyrillicStringEncoding";
- default:
- return @"Invalid encoding";
- }
- }
- - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
- {
- id data;
- 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
- {
- return dataUsingEncoding(self, encoding, flag);
- }
- - (NSStringEncoding)fastestEncoding
- {
- // UNICODE
- // ENCODINGS
- return NSISOLatin1StringEncoding;
- }
- - (NSStringEncoding)smallestEncoding
- {
- // UNICODE
- // ENCODINGS
- return NSISOLatin1StringEncoding;
- }
- - (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 - remove this
- NSData *data;
- data = [self dataUsingEncoding:[NSStringClass defaultCStringEncoding]];
- //data = [NSData dataWithBytes:[self cString] length:[self length]];
- return writeToFile(path, data, flag);
- }
- /* Encoding methods */
- - (void)encodeWithCoder:(NSCoder *)aCoder
- {
- int length;
- unichar *buf;
-
- length = [self length];
- buf = MallocAtomic(sizeof(unichar) * length);
-
- [self getCharacters:buf];
- [aCoder encodeValueOfObjCType:@encode(int) at:&length];
- [aCoder encodeArrayOfObjCType:@encode(unichar) count:length at:buf];
- lfFree(buf);
- }
- - (id)initWithCoder:(NSCoder *)aDecoder
- {
- unichar* buf;
- int length;
- [aDecoder decodeValueOfObjCType:@encode(int) at:&length];
- buf = MallocAtomic (sizeof(unichar) * length);
- [aDecoder decodeArrayOfObjCType:@encode(unichar) count:length at:buf];
- self = AUTORELEASE(self);
- return [self initWithCharactersNoCopy:buf
- length:length
- freeWhenDone:YES];
- }
- /* NSCopying methods */
- - (id)copyWithZone:(NSZone *)zone
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
-
- return RETAIN(self);
- // return [[NSStringClass allocWithZone:zone] initWithString:self];
- }
- /* NSMutableCopying methods */
- - (id)mutableCopyWithZone:(NSZone*)zone
- {
- return [[NSMutableString allocWithZone:zone] initWithString:self];
- }
- /* NSObject protocol */
- - (NSString *)stringRepresentation
- {
- /*
- an implementation of this method must quote the string for
- use in property lists.
- */
- return [self subclassResponsibility:_cmd];
- }
- - (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
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- return [[NSStringClass allocWithZone:zone] initWithString:self];
- }
- @end /* NSMutableString */
- /*********************************
- * NSString creation methods
- *********************************/
- @implementation NSString(NSStringCreation)
- + (id)allocWithZone:(NSZone *)zone
- {
- static Class NSTemporaryStringClass = Nil;
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- if (NSTemporaryStringClass == Nil)
- NSTemporaryStringClass = [NSTemporaryString class];
-
- return (self == NSStringClass)
- ? [NSTemporaryStringClass allocWithZone:zone]
- : (id)NSAllocateObject(self, 0, zone);
- }
- + (id)localizedStringWithFormat:(NSString*)format,...
- {
- va_list va;
- NSString* string;
-
- va_start(va, format);
- string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
- va_end(va);
- return string;
- }
- + (id)string
- {
- return @"";
- }
- + (id)stringWithCharacters:(const unichar*)chars
- length:(unsigned int)length
- {
- return AUTORELEASE([[self alloc] initWithCharacters:chars length:length]);
- }
- + (id)stringWithCharactersNoCopy:(unichar*)chars
- length:(unsigned int)length freeWhenDone:(BOOL)flag
- {
- return AUTORELEASE([[self alloc] initWithCharactersNoCopy:chars
- length:length freeWhenDone:flag]);
- }
- + (id)stringWithString:(NSString*)aString
- {
- return [self stringWithCString:[aString cString]];
- }
- + (id)stringWithCString:(const char*)byteString
- {
- return AUTORELEASE([[self alloc] initWithCString:byteString]);
- }
- + (id)stringWithUTF8String:(const char *)bytes
- {
- register unsigned char *p;
- for (p = (unsigned char *)bytes; *p; p++) {
- if (*p > 127)
- return AUTORELEASE([[self alloc] initWithUTF8String:bytes]);
- }
- return [self stringWithCString:bytes];
- }
- + (NSString *)stringWithCString:(const char*)byteString
- length:(unsigned int)length
- {
- return AUTORELEASE([[self alloc]
- initWithCString:byteString length:length]);
- }
- + (NSString *)stringWithCStringNoCopy:(char*)byteString
- length:(unsigned int)length freeWhenDone:(BOOL)flag
- {
- return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
- length:length freeWhenDone:flag]);
- }
- + (id)stringWithCStringNoCopy:(char*)byteString
- freeWhenDone:(BOOL)flag
- {
- return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
- freeWhenDone:flag]);
- }
- + (id)stringWithFormat:(NSString*)format,...
- {
- va_list va;
- NSString* string;
-
- va_start(va, format);
- string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
- va_end(va);
- return string;
- }
- + (id)stringWithFormat:(NSString *)format arguments:(va_list)argList
- {
- return AUTORELEASE([[self alloc] initWithFormat:format
- arguments:argList]);
- }
- + (id)stringWithContentsOfFile:(NSString *)path
- {
- return AUTORELEASE([[self alloc] initWithContentsOfFile:path]);
- }
- + (id)stringWithContentsOfURL:(NSURL *)_url
- {
- return AUTORELEASE([[self alloc] initWithContentsOfURL:_url]);
- }
- @end /* NSString(NSStringCreation) */
- @implementation NSString(GSAdditions)
- - (NSString *)stringWithoutPrefix:(NSString *)_prefix
- {
- return ([self hasPrefix:_prefix])
- ? [self substringFromIndex:[_prefix length]]
- : (NSString *)[[self copy] autorelease];
- }
- - (NSString *)stringWithoutSuffix:(NSString *)_suffix
- {
- return ([self hasSuffix:_suffix])
- ? [self substringToIndex:([self length] - [_suffix length])]
- : (NSString *)[[self copy] autorelease];
- }
- - (NSString *)stringByReplacingString:(NSString *)_orignal
- withString:(NSString *)_replacement
- {
- /* very slow solution .. */
-
- if ([self indexOfString:_orignal] == NSNotFound)
- return [[self copy] autorelease];
-
- return [[self componentsSeparatedByString:_orignal]
- componentsJoinedByString:_replacement];
- }
- static NSCharacterSet *whiteSpaceSet = nil;
- static BOOL (*isWhiteSpaceSetMem)(id, SEL, unichar);
- - (NSString *)stringByTrimmingLeadWhiteSpaces
- {
- /* can't we share the implementation of lead and tail?! It is 98% similiar */
- unsigned len;
- unichar *buf;
- unsigned idx;
-
- if (whiteSpaceSet == nil) {
- whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
- isWhiteSpaceSetMem = (void *)
- [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
- }
-
- if ((len = [self length]) == 0)
- return @"";
-
- buf = calloc(len + 1, sizeof(unichar));
- [self getCharacters:buf];
-
- for (idx = 0;
- (idx < len) && isWhiteSpaceSetMem(whiteSpaceSet,
- @selector(characterIsMember:),
- buf[idx]);
- idx++)
- ;
-
- self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
- free(buf);
- return self;
- }
- - (NSString *)stringByTrimmingTailWhiteSpaces
- {
- unichar *buf;
- unsigned int idx;
- unsigned len;
- if (whiteSpaceSet == nil) {
- whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
- isWhiteSpaceSetMem = (void *)
- [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
- }
-
- if ((len = [self length]) == 0)
- return @"";
-
- buf = calloc(len + 2, sizeof(unichar));
- [self getCharacters:buf];
-
- for (idx = (len - 1);
- (idx >= 0) && isWhiteSpaceSetMem(whiteSpaceSet,
- @selector(characterIsMember:), buf[idx]);
- idx--)
- ;
-
- self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
- free(buf);
- return self;
- }
- - (NSString *)stringByTrimmingLeadSpaces
- {
- unsigned int len;
- unsigned int idx;
- unichar *buf;
-
- if ((len = [self length]) == 0)
- return @"";
-
- buf = calloc(len + 2, sizeof(unichar));
- [self getCharacters:buf];
-
- for (idx = 0; (idx < len) && isspace(buf[idx]); idx++)
- ;
-
- self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
- if (buf) free(buf);
- return self;
- }
- - (NSString *)stringByTrimmingTailSpaces
- {
- unsigned len;
- unichar *buf;
- int idx;
-
- if ((len = [self length]) == 0)
- return @"";
-
- buf = calloc(len + 2, sizeof(unichar));
- [self getCharacters:buf];
-
- for (idx = (len - 1); (idx >= 0) && isspace(buf[idx]); idx--)
- ;
-
- self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
- if (buf) free(buf);
- return self;
- }
- - (NSString *)stringByTrimmingWhiteSpaces
- {
- return [[self stringByTrimmingTailWhiteSpaces]
- stringByTrimmingLeadWhiteSpaces];
- }
- - (NSString *)stringByTrimmingSpaces
- {
- return [[self stringByTrimmingTailSpaces]
- stringByTrimmingLeadSpaces];
- }
- @end /* NSString(GSAdditions) */
- @implementation NSMutableString(GNUstepCompatibility)
- - (void)trimLeadSpaces
- {
- [self setString:[self stringByTrimmingLeadSpaces]];
- }
- - (void)trimTailSpaces
- {
- [self setString:[self stringByTrimmingTailSpaces]];
- }
- - (void)trimSpaces
- {
- [self setString:[self stringByTrimmingSpaces]];
- }
- @end /* NSMutableString(GNUstepCompatibility) */
- @implementation NSMutableString(NSStringCreation)
- + (id)allocWithZone:(NSZone *)zone
- {
- return (self == [NSMutableString class])
- ? [NSMutableTemporaryString allocWithZone:zone]
- : (id)NSAllocateObject(self, 0, zone);
- }
- + (id)stringWithCapacity:(unsigned int)capacity
- {
- return AUTORELEASE([[self alloc] initWithCapacity:capacity]);
- }
- + (id)string
- {
- return [self stringWithCapacity:0];
- }
- @end /* NSMutableString(NSStringCreation) */
- /****************************
- * Initializing strings
- ****************************/
- @implementation NSMutableString(NSStringInitialization)
- - (id)initWithCapacity:(unsigned int)capacity
- {
- [self subclassResponsibility:_cmd];
- return nil;
- }
- - (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
- {
- unsigned char *buffer;
- unsigned int i, j;
- BOOL isLower8BitEqual = NO;
- BOOL isLower7BitEqual = NO;
- unsigned int convertCount = 0;
-
- switch ([NSStringClass defaultCStringEncoding]) {
- case NSISOLatin1StringEncoding:
- isLower8BitEqual = YES;
- break;
- case NSASCIIStringEncoding:
- case NSUTF8StringEncoding:
- isLower7BitEqual = YES;
- break;
- }
-
- /* scan whether this is a non-8-bit- string ... */
- for (i = 0; i < length; i++) {
- //NSMutableString *s;
-
- #if !HAS_UNICODE_STRING
- /* allow Euro char code (8364) */
- if (chars[i] == 8364) {
- convertCount++;
- continue;
- }
- #endif
- if (isLower8BitEqual && (chars[i] < 256))
- /* valid 8-bit character in default encoding */
- continue;
- if (isLower7BitEqual && (chars[i] < 128))
- /* valid 7-bit character in default encoding */
- continue;
-
- #if HAS_UNICODE_STRING
- s = [[NSMutableUnicodeString alloc]
- initWithCharacters:chars
- length:length];
- if (flag) {
- lfFree(chars);
- chars = NULL;
- }
- #endif
- return [self notImplemented:_cmd];
- }
-
- buffer = MallocAtomic(length + (convertCount*3) + 1);
-
- for (i = 0, j = 0; i < length; i++, j++) {
- #if !HAS_UNICODE_STRING
- if (chars[i] == 8364) {
- buffer[j++] = 'E';
- buffer[j++] = 'U';
- buffer[j] = 'R';
- }
- #endif
- buffer[j] = chars[i];
- }
-
- buffer[j] = '\0';
- self = [self initWithCString:(char *)buffer length:j];
- if (buffer) lfFree(buffer);
- return self;
- }
- - (id)initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length
- freeWhenDone:(BOOL)flag
- {
- unsigned char *buffer;
- unsigned int i, j;
- BOOL isLower8BitEqual = NO;
- BOOL isLower7BitEqual = NO;
- unsigned int convertCount = 0;
-
- switch ([NSStringClass defaultCStringEncoding]) {
- case NSISOLatin1StringEncoding:
- isLower8BitEqual = YES;
- break;
- case NSASCIIStringEncoding:
- case NSUTF8StringEncoding:
- case NSISOLatin9StringEncoding:
- isLower7BitEqual = YES;
- break;
- }
-
- /* scan whether this is a non-8-bit- string ... */
- for (i = 0; i < length; i++) {
- //NSMutableString *s;
-
- #if !HAS_UNICODE_STRING
- /* allow Euro char code (8364) */
- if (chars[i] == 8364) {
- convertCount++;
- continue;
- }
- #endif
- if (isLower8BitEqual && (chars[i] < 256))
- /* valid 8-bit character in default encoding */
- continue;
- if (isLower7BitEqual && (chars[i] < 128))
- /* valid 7-bit character in default encoding */
- continue;
-
- #if HAS_UNICODE_STRING
- s = [[NSMutableUTF16String alloc]
- initWithCharacters:chars
- length:length];
- if (flag) {
- lfFree(chars);
- chars = NULL;
- }
- #endif
- return [self notImplemented:_cmd];
- }
-
- buffer = MallocAtomic(length + (convertCount*3) + 1);
-
- for (i = 0, j = 0; i < length; i++, j++) {
- #if !HAS_UNICODE_STRING
- if (chars[i] == 8364) {
- buffer[j++] = 'E';
- buffer[j++] = 'U';
- buffer[j] = 'R';
- }
- #endif
- buffer[j] = chars[i];
- }
-
- buffer[j] = '\0';
- if (flag) {
- lfFree(chars);
- chars = NULL;
- }
- self = [self initWithCString:(char *)buffer length:j];
- if (buffer) lfFree(buffer);
- return self;
- }
- - (id)initWithCString:(const char*)byteString
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- return [self initWithString:
- AUTORELEASE([[NSStringClass alloc]
- initWithCStringNoCopy:(char*)byteString
- freeWhenDone:NO])];
- }
- - (id)initWithCString:(const char*)byteString length:(unsigned int)length
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- return [self initWithString:
- AUTORELEASE([[NSStringClass alloc]
- initWithCStringNoCopy:(char*)byteString
- length:length freeWhenDone:NO])];
- }
- - (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- return [self initWithString:
- AUTORELEASE([[NSStringClass alloc]
- initWithCStringNoCopy:byteString
- freeWhenDone:flag])];
- }
- - (id)initWithCStringNoCopy:(char*)byteString length:(unsigned int)length
- freeWhenDone:(BOOL)flag
- {
- if (NSStringClass == Nil)
- NSStringClass = [NSString class];
- return [self initWithString:
- AUTORELEASE([[NSStringClass alloc]
- initWithCStringNoCopy:byteString
- length:length freeWhenDone:flag])];
- }
- - (id)initWithString:(NSString*)aString
- {
- [self subclassResponsibility:_cmd];
- return nil;
- }
- - (id)initWithFormat:(NSString*)format, ...
- {
- id str;
- va_list va;
-
- va_start(va, format);
- str = [self initWithFormat:format arguments:va];
- va_end(va);
- return str;
- }
- - (id)initWithFormat:(NSString*)format arguments:(va_list)argList
- {
- return [self initWithString:Avsprintf(format, argList)];
- }
- - (id)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;
- }
- - (id)initWithFormat:(NSString *)format
- locale:(NSDictionary*)dictionary arguments:(va_list)argList
- {
- return [self initWithFormat:format arguments:argList];
- }
- - (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
- {
- /* NSMutableString */
- return NSInitStringWithData(self, data, encoding);
- }
- - (id)initWithContentsOfFile:(NSString *)path
- {
- // UNICODE
- // ENCODINGS
- [self notImplemented:_cmd];
- return nil;
- }
- @end /* NSMutableString(NSStringInitialization) */
- /****************************
- * Allocate concrete strings
- ****************************/
- /*
- * Classes used for allocation of NSString concrete instances
- */
- @implementation NSTemporaryString
- static BOOL isMultithreaded = NO;
- static NSTemporaryString *temporaryStringsPool = nil;
- static…