Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -392,18 +392,18 @@ @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - (void*)allocMemoryForNItems: (size_t)nitems - withSize: (size_t)size + withSize: (size_t)size { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - (void*)resizeMemory: (void*)ptr - toSize: (size_t)size + toSize: (size_t)size { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } Index: src/OFConstantString.h ================================================================== --- src/OFConstantString.h +++ src/OFConstantString.h @@ -28,6 +28,13 @@ /** * \brief A class for storing constant strings using the \@"" literal. */ @interface OFConstantString: OFString +/** + * \brief Completes initialization of the OFConstantString + * + * This method completes the initialization, as the constant strings created by + * the compiler are not fully initialized. + */ +- (void)completeInitialization; @end Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -13,14 +13,19 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include +#include #import "OFConstantString.h" +#import "OFInvalidEncodingException.h" #import "OFNotImplementedException.h" +#import "OFOutOfMemoryException.h" #ifdef OF_APPLE_RUNTIME # import void *_OFConstantStringClassReference; @@ -33,74 +38,245 @@ objc_setFutureClass((Class)&_OFConstantStringClassReference, "OFConstantString"); } #endif +- (void)completeInitialization +{ + struct of_string_ivars *ivars; + + if (initialized == SIZE_MAX) + return; + + if ((ivars = malloc(sizeof(*ivars))) == NULL) + @throw [OFOutOfMemoryException newWithClass: isa + requestedSize: sizeof(*ivars)]; + memset(ivars, 0, sizeof(*ivars)); + + ivars->string = (char*)s; + ivars->length = initialized; + + switch (of_string_check_utf8(ivars->string, ivars->length)) { + case 1: + ivars->isUTF8 = YES; + break; + case -1: + free(ivars); + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + s = ivars; + initialized = SIZE_MAX; +} + +/* + * The following methods are not available since it's a constant string, which + * can't be allocated or initialized at runtime. + */ + alloc { @throw [OFNotImplementedException newWithClass: self selector: _cmd]; } - init { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } - initWithCString: (const char*)str { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } - initWithCString: (const char*)str encoding: (of_string_encoding_t)encoding { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } - initWithCString: (const char*)str encoding: (of_string_encoding_t)encoding length: (size_t)len { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } - initWithCString: (const char*)str - length: (size_t)len + length: (size_t)len +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithString: (OFString*)string +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUnicodeString: (of_unichar_t*)string +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUnicodeString: (of_unichar_t*)string + byteOrder: (of_endianess_t)byteOrder +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUnicodeString: (of_unichar_t*)string + length: (size_t)length +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUnicodeString: (of_unichar_t*)string + byteOrder: (of_endianess_t)byteOrder + length: (size_t)length +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUTF16String: (uint16_t*)string + byteOrder: (of_endianess_t)byteOrder +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUTF16String: (uint16_t*)string + length: (size_t)length +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithUTF16String: (uint16_t*)string + byteOrder: (of_endianess_t)byteOrder + length: (size_t)length { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } -- initWithFormat: (OFString*)fmt, ... +- initWithFormat: (OFConstantString*)format, ... { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } -- initWithFormat: (OFString*)fmt +- initWithFormat: (OFConstantString*)format arguments: (va_list)args { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithPath: (OFString*)firstComponent, ... +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithPath: (OFString*)firstComponent + arguments: (va_list)arguments +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithContentsOfFile: (OFString*)path +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithContentsOfFile: (OFString*)path + encoding: (of_string_encoding_t)encoding +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithContentsOfURL: (OFURL*)URL +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithContentsOfURL: (OFURL*)URL + encoding: (of_string_encoding_t)encoding +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } -- initWithString: (OFString*)str +/* From protocol OFSerializing */ +- initWithSerialization: (OFXMLElement*)element { - @throw [OFNotImplementedException newWithClass: isa + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c selector: _cmd]; } -- (BOOL)isUTF8 -{ - return YES; -} - +/* + * The following methods are not available because constant strings are + * preallocated by the compiler and thus don't have a memory pool. + */ - (void)addMemoryToPool: (void*)ptr { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } @@ -110,11 +286,11 @@ @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - (void*)allocMemoryForNItems: (size_t)nitems - withSize: (size_t)size + withSize: (size_t)size { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } @@ -137,10 +313,14 @@ { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } +/* + * The following methods are unnecessary because constant strings are + * singletons. + */ - retain { return self; } @@ -162,6 +342,308 @@ { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; [super dealloc]; /* Get rid of a stupid warning */ } + +/* + * In all following methods, it is checked whether the constant string has been + * initialized. If not, it will be initialized. Finally, the implementation of + * the superclass will be called. + */ + +/* From protocol OFCopying */ +- copy +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super copy]; +} + +/* From protocol OFMutableCopying */ +- mutableCopy +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super mutableCopy]; +} + +/* From protocol OFComparing */ +- (of_comparison_result_t)compare: (id)object +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super compare: object]; +} + +/* From protocol OFSerialization */ +- (OFXMLElement*)XMLElementBySerializing +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super XMLElementBySerializing]; +} + +/* From OFObject, but reimplemented in OFString */ +- (BOOL)isEqual: (id)object +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super isEqual: object]; +} + +- (uint32_t)hash +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super hash]; +} + +- (OFString*)description +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super description]; +} + +/* From OFString */ +- (const char*)cString +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super cString]; +} + +- (size_t)length +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super length]; +} + +- (size_t)cStringLength +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super cStringLength]; +} + +- (of_comparison_result_t)caseInsensitiveCompare: (OFString*)otherString +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super caseInsensitiveCompare: otherString]; +} + +- (of_unichar_t)characterAtIndex: (size_t)index +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super characterAtIndex: index]; +} + +- (size_t)indexOfFirstOccurrenceOfString: (OFString*)string +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super indexOfFirstOccurrenceOfString: string]; +} + +- (size_t)indexOfLastOccurrenceOfString: (OFString*)string +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super indexOfLastOccurrenceOfString: string]; +} + +- (BOOL)containsString: (OFString*)string +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super containsString: string]; +} + +- (OFString*)substringFromIndex: (size_t)start + toIndex: (size_t)end +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super substringFromIndex: start + toIndex: end]; +} + +- (OFString*)substringWithRange: (of_range_t)range +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super substringWithRange: range]; +} + +- (OFString*)stringByAppendingString: (OFString*)string +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByAppendingString: string]; +} + +- (OFString*)stringByPrependingString: (OFString*)string +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByPrependingString: string]; +} + +- (OFString*)uppercaseString +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super uppercaseString]; +} + +- (OFString*)lowercaseString +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super lowercaseString]; +} + +- (OFString*)stringByDeletingLeadingWhitespaces +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByDeletingLeadingWhitespaces]; +} + +- (OFString*)stringByDeletingTrailingWhitespaces +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByDeletingTrailingWhitespaces]; +} + +- (OFString*)stringByDeletingLeadingAndTrailingWhitespaces +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByDeletingLeadingAndTrailingWhitespaces]; +} + +- (BOOL)hasPrefix: (OFString*)prefix +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super hasPrefix: prefix]; +} + +- (BOOL)hasSuffix: (OFString*)suffix +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super hasSuffix: suffix]; +} + +- (OFArray*)componentsSeparatedByString: (OFString*)delimiter +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super componentsSeparatedByString: delimiter]; +} + +- (OFArray*)pathComponents +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super pathComponents]; +} + +- (OFString*)lastPathComponent +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super lastPathComponent]; +} + +- (OFString*)stringByDeletingLastPathComponent +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super stringByDeletingLastPathComponent]; +} + +- (intmax_t)decimalValue +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super decimalValue]; +} + +- (uintmax_t)hexadecimalValue +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super hexadecimalValue]; +} + +- (float)floatValue +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super floatValue]; +} + +- (double)doubleValue +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super doubleValue]; +} + +- (of_unichar_t*)unicodeString +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super unicodeString]; +} + +- (void)writeToFile: (OFString*)path +{ + if (initialized != SIZE_MAX) + [self completeInitialization]; + + return [super writeToFile: path]; +} @end Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -413,11 +413,11 @@ } - (OFEnumerator*)objectEnumerator { return [[[OFListEnumerator alloc] - initWithList: self + initWithList: self mutationsPointer: &mutations] autorelease]; } @end @implementation OFListEnumerator Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -50,17 +50,17 @@ of_unichar_t *unicodeString; size_t unicodeLen, newLength, cLen; size_t i, j, d; char *newString; - if (!isUTF8) { + if (!s->isUTF8) { assert(tableSize >= 1); - uint8_t *p = (uint8_t*)string + length; + uint8_t *p = (uint8_t*)s->string + s->length; uint8_t t; - while (--p >= (uint8_t*)string) + while (--p >= (uint8_t*)s->string) if ((t = table[0][*p]) != 0) *p = t; return; } @@ -70,12 +70,13 @@ withSize: sizeof(of_unichar_t)]; i = j = 0; newLength = 0; - while (i < length) { - cLen = of_string_utf8_to_unicode(string + i, length - i, &c); + while (i < s->length) { + cLen = of_string_utf8_to_unicode(s->string + i, s->length - i, + &c); if (cLen == 0 || c > 0x10FFFF) { [self freeMemory: unicodeString]; @throw [OFInvalidEncodingException newWithClass: isa]; } @@ -125,138 +126,138 @@ assert(j == newLength); newString[j] = 0; [self freeMemory: unicodeString]; - [self freeMemory: string]; - string = newString; - length = newLength; -} - -- (void)setToCString: (const char*)string_ -{ - size_t length_; - - [self freeMemory: string]; - - length_ = strlen(string_); - - if (length_ >= 3 && !memcmp(string_, "\xEF\xBB\xBF", 3)) { - string_ += 3; - length_ -= 3; - } - - switch (of_string_check_utf8(string_, length_)) { - case 0: - isUTF8 = NO; - break; - case 1: - isUTF8 = YES; - break; - case -1: - string = NULL; - length = 0; - isUTF8 = NO; - - @throw [OFInvalidEncodingException newWithClass: isa]; - } - - length = length_; - string = [self allocMemoryWithSize: length + 1]; - memcpy(string, string_, length + 1); -} - -- (void)appendCString: (const char*)string_ -{ - size_t length_ = strlen(string_); - - if (length_ >= 3 && !memcmp(string_, "\xEF\xBB\xBF", 3)) { - string_ += 3; - length_ -= 3; - } - - switch (of_string_check_utf8(string_, length_)) { - case 1: - isUTF8 = YES; - break; - case -1: - @throw [OFInvalidEncodingException newWithClass: isa]; - } - - string = [self resizeMemory: string - toSize: length + length_ + 1]; - memcpy(string + length, string_, length_ + 1); - length += length_; -} - -- (void)appendCString: (const char*)string_ - withLength: (size_t)length_ -{ - if (length_ >= 3 && !memcmp(string_, "\xEF\xBB\xBF", 3)) { - string_ += 3; - length_ -= 3; - } - - switch (of_string_check_utf8(string_, length_)) { - case 1: - isUTF8 = YES; - break; - case -1: - @throw [OFInvalidEncodingException newWithClass: isa]; - } - - string = [self resizeMemory: string - toSize: length + length_ + 1]; - memcpy(string + length, string_, length_); - length += length_; - string[length] = 0; -} - -- (void)appendCString: (const char*)string_ - withEncoding: (of_string_encoding_t)encoding - length: (size_t)length_ -{ - if (encoding == OF_STRING_ENCODING_UTF_8) - [self appendCString: string_ - withLength: length_]; - else { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - [self appendString: [OFString stringWithCString: string_ - encoding: encoding - length: length_]]; - [pool release]; - } -} - -- (void)appendCStringWithoutUTF8Checking: (const char*)string_ -{ - size_t len; - - len = strlen(string_); - string = [self resizeMemory: string - toSize: length + len + 1]; - memcpy(string + length, string_, len + 1); - length += len; -} - -- (void)appendCStringWithoutUTF8Checking: (const char*)string_ - length: (size_t)length_ -{ - string = [self resizeMemory: string - toSize: length + length_ + 1]; - memcpy(string + length, string_, length_); - length += length_; - string[length] = 0; -} - -- (void)appendString: (OFString*)string_ -{ - if (string_ == nil) - @throw [OFInvalidArgumentException newWithClass: isa - selector: _cmd]; - - [self appendCString: [string_ cString]]; + [self freeMemory: s->string]; + s->string = newString; + s->length = newLength; +} + +- (void)setToCString: (const char*)string +{ + size_t length; + + [self freeMemory: s->string]; + + length = strlen(string); + + if (length >= 3 && !memcmp(string, "\xEF\xBB\xBF", 3)) { + string += 3; + length -= 3; + } + + switch (of_string_check_utf8(string, length)) { + case 0: + s->isUTF8 = NO; + break; + case 1: + s->isUTF8 = YES; + break; + case -1: + s->string = NULL; + s->length = 0; + s->isUTF8 = NO; + + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + s->length = length; + s->string = [self allocMemoryWithSize: length + 1]; + memcpy(s->string, string, length + 1); +} + +- (void)appendCString: (const char*)string +{ + size_t length = strlen(string); + + if (length >= 3 && !memcmp(string, "\xEF\xBB\xBF", 3)) { + string += 3; + length -= 3; + } + + switch (of_string_check_utf8(string, length)) { + case 1: + s->isUTF8 = YES; + break; + case -1: + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + s->string = [self resizeMemory: s->string + toSize: s->length + length + 1]; + memcpy(s->string + s->length, string, length + 1); + s->length += length; +} + +- (void)appendCString: (const char*)string + withLength: (size_t)length +{ + if (length >= 3 && !memcmp(string, "\xEF\xBB\xBF", 3)) { + string += 3; + length -= 3; + } + + switch (of_string_check_utf8(string, length)) { + case 1: + s->isUTF8 = YES; + break; + case -1: + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + s->string = [self resizeMemory: s->string + toSize: s->length + length + 1]; + memcpy(s->string + s->length, string, length); + s->length += length; + s->string[s->length] = 0; +} + +- (void)appendCString: (const char*)string + withEncoding: (of_string_encoding_t)encoding + length: (size_t)length +{ + if (encoding == OF_STRING_ENCODING_UTF_8) + [self appendCString: string + withLength: length]; + else { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + [self appendString: [OFString stringWithCString: string + encoding: encoding + length: length]]; + [pool release]; + } +} + +- (void)appendCStringWithoutUTF8Checking: (const char*)string +{ + size_t length; + + length = strlen(string); + s->string = [self resizeMemory: s->string + toSize: s->length + length + 1]; + memcpy(s->string + s->length, string, length + 1); + s->length += length; +} + +- (void)appendCStringWithoutUTF8Checking: (const char*)string + length: (size_t)length +{ + s->string = [self resizeMemory: s->string + toSize: s->length + length + 1]; + memcpy(s->string + s->length, string, length); + s->length += length; + s->string[s->length] = 0; +} + +- (void)appendString: (OFString*)string +{ + if (string == nil) + @throw [OFInvalidArgumentException newWithClass: isa + selector: _cmd]; + + [self appendCString: [string cString]]; } - (void)appendFormat: (OFConstantString*)format, ... { va_list arguments; @@ -269,120 +270,123 @@ - (void)appendFormat: (OFConstantString*)format withArguments: (va_list)arguments { char *t; - int len; + int length; if (format == nil) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; - if ((len = of_vasprintf(&t, [format cString], arguments)) == -1) + if ((length = of_vasprintf(&t, [format cString], arguments)) == -1) @throw [OFInvalidFormatException newWithClass: isa]; @try { [self appendCString: t - withLength: len]; + withLength: length]; } @finally { free(t); } } -- (void)prependString: (OFString*)string_ +- (void)prependString: (OFString*)string { - return [self insertString: string_ + return [self insertString: string atIndex: 0]; } - (void)reverse { - size_t i, j, len = length / 2; + size_t i, j, length = s->length / 2; - madvise(string, length, MADV_SEQUENTIAL); + madvise(s->string, s->length, MADV_SEQUENTIAL); /* We reverse all bytes and restore UTF-8 later, if necessary */ - for (i = 0, j = length - 1; i < len; i++, j--) { - string[i] ^= string[j]; - string[j] ^= string[i]; - string[i] ^= string[j]; + for (i = 0, j = s->length - 1; i < length; i++, j--) { + s->string[i] ^= s->string[j]; + s->string[j] ^= s->string[i]; + s->string[i] ^= s->string[j]; } - if (!isUTF8) { - madvise(string, length, MADV_NORMAL); + if (!s->isUTF8) { + madvise(s->string, s->length, MADV_NORMAL); return; } - for (i = 0; i < length; i++) { + for (i = 0; i < s->length; i++) { /* ASCII */ - if (OF_LIKELY(!(string[i] & 0x80))) + if (OF_LIKELY(!(s->string[i] & 0x80))) continue; /* A start byte can't happen first as we reversed everything */ - if (OF_UNLIKELY(string[i] & 0x40)) { - madvise(string, length, MADV_NORMAL); + if (OF_UNLIKELY(s->string[i] & 0x40)) { + madvise(s->string, s->length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Next byte must not be ASCII */ - if (OF_UNLIKELY(length < i + 1 || !(string[i + 1] & 0x80))) { - madvise(string, length, MADV_NORMAL); + if (OF_UNLIKELY(s->length < i + 1 || + !(s->string[i + 1] & 0x80))) { + madvise(s->string, s->length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Next byte is the start byte */ - if (OF_LIKELY(string[i + 1] & 0x40)) { - string[i] ^= string[i + 1]; - string[i + 1] ^= string[i]; - string[i] ^= string[i + 1]; + if (OF_LIKELY(s->string[i + 1] & 0x40)) { + s->string[i] ^= s->string[i + 1]; + s->string[i + 1] ^= s->string[i]; + s->string[i] ^= s->string[i + 1]; i++; continue; } /* Second next byte must not be ASCII */ - if (OF_UNLIKELY(length < i + 2 || !(string[i + 2] & 0x80))) { - madvise(string, length, MADV_NORMAL); + if (OF_UNLIKELY(s->length < i + 2 || + !(s->string[i + 2] & 0x80))) { + madvise(s->string, s->length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Second next byte is the start byte */ - if (OF_LIKELY(string[i + 2] & 0x40)) { - string[i] ^= string[i + 2]; - string[i + 2] ^= string[i]; - string[i] ^= string[i + 2]; + if (OF_LIKELY(s->string[i + 2] & 0x40)) { + s->string[i] ^= s->string[i + 2]; + s->string[i + 2] ^= s->string[i]; + s->string[i] ^= s->string[i + 2]; i += 2; continue; } /* Third next byte must not be ASCII */ - if (OF_UNLIKELY(length < i + 3 || !(string[i + 3] & 0x80))) { - madvise(string, length, MADV_NORMAL); + if (OF_UNLIKELY(s->length < i + 3 || + !(s->string[i + 3] & 0x80))) { + madvise(s->string, s->length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Third next byte is the start byte */ - if (OF_LIKELY(string[i + 3] & 0x40)) { - string[i] ^= string[i + 3]; - string[i + 3] ^= string[i]; - string[i] ^= string[i + 3]; - - string[i + 1] ^= string[i + 2]; - string[i + 2] ^= string[i + 1]; - string[i + 1] ^= string[i + 2]; + if (OF_LIKELY(s->string[i + 3] & 0x40)) { + s->string[i] ^= s->string[i + 3]; + s->string[i + 3] ^= s->string[i]; + s->string[i] ^= s->string[i + 3]; + + s->string[i + 1] ^= s->string[i + 2]; + s->string[i + 2] ^= s->string[i + 1]; + s->string[i + 1] ^= s->string[i + 2]; i += 3; continue; } /* UTF-8 does not allow more than 4 bytes per character */ - madvise(string, length, MADV_NORMAL); + madvise(s->string, s->length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } - madvise(string, length, MADV_NORMAL); + madvise(s->string, s->length, MADV_NORMAL); } - (void)upper { [self _applyTable: of_unicode_upper_table @@ -393,55 +397,57 @@ { [self _applyTable: of_unicode_lower_table withSize: OF_UNICODE_LOWER_TABLE_SIZE]; } -- (void)insertString: (OFString*)string_ +- (void)insertString: (OFString*)string atIndex: (size_t)index { size_t newLength; - if (isUTF8) - index = of_string_index_to_position(string, index, length); + if (s->isUTF8) + index = of_string_index_to_position(s->string, index, + s->length); - if (index > length) + if (index > s->length) @throw [OFOutOfRangeException newWithClass: isa]; - newLength = length + [string_ cStringLength]; - string = [self resizeMemory: string - toSize: newLength + 1]; - - memmove(string + index + [string_ cStringLength], string + index, - length - index); - memcpy(string + index, [string_ cString], [string_ cStringLength]); - string[newLength] = '\0'; - - length = newLength; + newLength = s->length + [string cStringLength]; + s->string = [self resizeMemory: s->string + toSize: newLength + 1]; + + memmove(s->string + index + [string cStringLength], s->string + index, + s->length - index); + memcpy(s->string + index, [string cString], [string cStringLength]); + s->string[newLength] = '\0'; + + s->length = newLength; } - (void)deleteCharactersFromIndex: (size_t)start toIndex: (size_t)end { - if (isUTF8) { - start = of_string_index_to_position(string, start, length); - end = of_string_index_to_position(string, end, length); + if (s->isUTF8) { + start = of_string_index_to_position(s->string, start, + s->length); + end = of_string_index_to_position(s->string, end, s->length); } if (start > end) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; - if (end > length) + if (end > s->length) @throw [OFOutOfRangeException newWithClass: isa]; - memmove(string + start, string + end, length - end); - length -= end - start; - string[length] = 0; + memmove(s->string + start, s->string + end, s->length - end); + s->length -= end - start; + s->string[s->length] = 0; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't really care, as we only made it smaller */ [e release]; } } @@ -456,33 +462,34 @@ toIndex: (size_t)end withString: (OFString*)replacement { size_t newLength; - if (isUTF8) { - start = of_string_index_to_position(string, start, length); - end = of_string_index_to_position(string, end, length); + if (s->isUTF8) { + start = of_string_index_to_position(s->string, start, + s->length); + end = of_string_index_to_position(s->string, end, s->length); } if (start > end) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; - if (end > length) + if (end > s->length) @throw [OFOutOfRangeException newWithClass: isa]; - newLength = length - (end - start) + [replacement cStringLength]; - string = [self resizeMemory: string - toSize: newLength + 1]; + newLength = s->length - (end - start) + [replacement cStringLength]; + s->string = [self resizeMemory: s->string + toSize: newLength + 1]; - memmove(string + end, string + start + [replacement cStringLength], - length - end); - memcpy(string + start, [replacement cString], + memmove(s->string + end, s->string + start + + [replacement cStringLength], s->length - end); + memcpy(s->string + start, [replacement cString], [replacement cStringLength]); - string[newLength] = '\0'; + s->string[newLength] = '\0'; - length = newLength; + s->length = newLength; } - (void)replaceCharactersInRange: (of_range_t)range withString: (OFString*)replacement { @@ -489,28 +496,28 @@ [self replaceCharactersFromIndex: range.start toIndex: range.start + range.length withString: replacement]; } -- (void)replaceOccurrencesOfString: (OFString*)string_ +- (void)replaceOccurrencesOfString: (OFString*)string withString: (OFString*)replacement { - const char *cString = [string_ cString]; + const char *cString = [string cString]; const char *replacementCString = [replacement cString]; - size_t stringLen = [string_ cStringLength]; + size_t stringLen = [string cStringLength]; size_t replacementLen = [replacement cStringLength]; size_t i, last, newLength; char *newString; - if (stringLen > length) + if (stringLen > s->length) return; newString = NULL; newLength = 0; - for (i = 0, last = 0; i <= length - stringLen; i++) { - if (memcmp(string + i, cString, stringLen)) + for (i = 0, last = 0; i <= s->length - stringLen; i++) { + if (memcmp(s->string + i, cString, stringLen)) continue; @try { newString = [self resizeMemory: newString toSize: newLength + i - last + @@ -517,50 +524,51 @@ replacementLen + 1]; } @catch (id e) { [self freeMemory: newString]; @throw e; } - memcpy(newString + newLength, string + last, i - last); + memcpy(newString + newLength, s->string + last, i - last); memcpy(newString + newLength + i - last, replacementCString, replacementLen); newLength += i - last + replacementLen; i += stringLen - 1; last = i + 1; } @try { newString = [self resizeMemory: newString - toSize: newLength + length - last + 1]; + toSize: newLength + s->length - last + + 1]; } @catch (id e) { [self freeMemory: newString]; @throw e; } - memcpy(newString + newLength, string + last, length - last); - newLength += length - last; + memcpy(newString + newLength, s->string + last, s->length - last); + newLength += s->length - last; newString[newLength] = 0; - [self freeMemory: string]; - string = newString; - length = newLength; + [self freeMemory: s->string]; + s->string = newString; + s->length = newLength; } - (void)deleteLeadingWhitespaces { size_t i; - for (i = 0; i < length; i++) - if (string[i] != ' ' && string[i] != '\t' && - string[i] != '\n' && string[i] != '\r') + for (i = 0; i < s->length; i++) + if (s->string[i] != ' ' && s->string[i] != '\t' && + s->string[i] != '\n' && s->string[i] != '\r') break; - length -= i; - memmove(string, string + i, length); - string[length] = '\0'; + s->length -= i; + memmove(s->string, s->string + i, s->length); + s->string[s->length] = '\0'; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't really care, as we only made it smaller */ [e release]; } } @@ -569,23 +577,23 @@ { size_t d; char *p; d = 0; - for (p = string + length - 1; p >= string; p--) { + for (p = s->string + s->length - 1; p >= s->string; p--) { if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') break; *p = '\0'; d++; } - length -= d; + s->length -= d; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't really care, as we only made it smaller */ [e release]; } } @@ -594,32 +602,32 @@ { size_t d, i; char *p; d = 0; - for (p = string + length - 1; p >= string; p--) { + for (p = s->string + s->length - 1; p >= s->string; p--) { if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') break; *p = '\0'; d++; } - length -= d; + s->length -= d; - for (i = 0; i < length; i++) - if (string[i] != ' ' && string[i] != '\t' && - string[i] != '\n' && string[i] != '\r') + for (i = 0; i < s->length; i++) + if (s->string[i] != ' ' && s->string[i] != '\t' && + s->string[i] != '\n' && s->string[i] != '\r') break; - length -= i; - memmove(string, string + i, length); - string[length] = '\0'; + s->length -= i; + memmove(s->string, s->string + i, s->length); + s->string[s->length] = '\0'; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't really care, as we only made it smaller */ [e release]; } } Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -890,11 +890,11 @@ @throw [OFNotImplementedException newWithClass: self selector: _cmd]; } + (void*)allocMemoryForNItems: (size_t)nItems - withSize: (size_t)size + withSize: (size_t)size { @throw [OFNotImplementedException newWithClass: self selector: _cmd]; } Index: src/OFString+Hashing.m ================================================================== --- src/OFString+Hashing.m +++ src/OFString+Hashing.m @@ -30,12 +30,12 @@ OFMD5Hash *hash = [OFMD5Hash MD5Hash]; uint8_t *digest; char ret[OF_MD5_DIGEST_SIZE * 2]; size_t i; - [hash updateWithBuffer: string - length: length]; + [hash updateWithBuffer: [self cString] + length: [self cStringLength]]; digest = [hash digest]; for (i = 0; i < OF_MD5_DIGEST_SIZE; i++) { uint8_t high, low; @@ -58,12 +58,12 @@ OFMD5Hash *hash = [OFSHA1Hash SHA1Hash]; uint8_t *digest; char ret[OF_SHA1_DIGEST_SIZE * 2]; size_t i; - [hash updateWithBuffer: string - length: length]; + [hash updateWithBuffer: [self cString] + length: [self cStringLength]]; digest = [hash digest]; for (i = 0; i < OF_SHA1_DIGEST_SIZE; i++) { uint8_t high, low; Index: src/OFString+URLEncoding.m ================================================================== --- src/OFString+URLEncoding.m +++ src/OFString+URLEncoding.m @@ -29,33 +29,34 @@ int _OFString_URLEncoding_reference; @implementation OFString (URLEncoding) - (OFString*)stringByURLEncoding { - const char *string_ = string; + const char *string = [self cString]; char *retCString; size_t i; OFString *ret; /* * Worst case: 3 times longer than before. * Oh, and we can't use [self allocWithSize:] here as self might be a * @"" literal. */ - if ((retCString = malloc((length * 3) + 1)) == NULL) - @throw [OFOutOfMemoryException newWithClass: isa - requestedSize: (length * 3) + 1]; - - for (i = 0; *string_ != '\0'; string_++) { - if (isalnum((int)*string_) || *string_ == '-' || - *string_ == '_' || *string_ == '.' || *string_ == '~') - retCString[i++] = *string_; + if ((retCString = malloc(([self cStringLength] * 3) + 1)) == NULL) + @throw [OFOutOfMemoryException + newWithClass: isa + requestedSize: ([self cStringLength] * 3) + 1]; + + for (i = 0; *string != '\0'; string++) { + if (isalnum((int)*string) || *string == '-' || *string == '_' || + *string == '.' || *string == '~') + retCString[i++] = *string; else { uint8_t high, low; - high = *string_ >> 4; - low = *string_ & 0x0F; + high = *string >> 4; + low = *string & 0x0F; retCString[i++] = '%'; retCString[i++] = (high > 9 ? high - 10 + 'A' : high + '0'); retCString[i++] = @@ -74,40 +75,41 @@ } - (OFString*)stringByURLDecoding { OFString *ret; - const char *string_ = string; + const char *string = [self cString]; char *retCString; char byte = 0; int state = 0; size_t i; - if ((retCString = malloc(length + 1)) == NULL) - @throw [OFOutOfMemoryException newWithClass: isa - requestedSize: length + 1]; + if ((retCString = malloc([self cStringLength] + 1)) == NULL) + @throw [OFOutOfMemoryException + newWithClass: isa + requestedSize: [self cStringLength] + 1]; - for (i = 0; *string_; string_++) { + for (i = 0; *string; string++) { switch (state) { case 0: - if (*string_ == '%') + if (*string == '%') state = 1; - else if (*string_ == '+') + else if (*string == '+') retCString[i++] = ' '; else - retCString[i++] = *string_; + retCString[i++] = *string; break; case 1: case 2:; uint8_t shift = (state == 1 ? 4 : 0); - if (*string_ >= '0' && *string_ <= '9') - byte += (*string_ - '0') << shift; - else if (*string_ >= 'A' && *string_ <= 'F') - byte += (*string_ - 'A' + 10) << shift; - else if (*string_ >= 'a' && *string_ <= 'f') - byte += (*string_ - 'a' + 10) << shift; + if (*string >= '0' && *string <= '9') + byte += (*string - '0') << shift; + else if (*string >= 'A' && *string <= 'F') + byte += (*string - 'A' + 10) << shift; + else if (*string >= 'a' && *string <= 'f') + byte += (*string - 'a' + 10) << shift; else { free(retCString); @throw [OFInvalidEncodingException newWithClass: isa]; } Index: src/OFString+XMLEscaping.m ================================================================== --- src/OFString+XMLEscaping.m +++ src/OFString+XMLEscaping.m @@ -28,15 +28,18 @@ @implementation OFString (XMLEscaping) - (OFString*)stringByXMLEscaping { char *retCString; - const char *append; - size_t retLength, appendLen; + const char *string, *append; + size_t length, retLength, appendLen; size_t i, j; OFString *ret; + string = [self cString]; + length = [self cStringLength]; + j = 0; retLength = length; /* * We can't use allocMemoryWithSize: here as it might be a @"" literal Index: src/OFString+XMLUnescaping.m ================================================================== --- src/OFString+XMLUnescaping.m +++ src/OFString+XMLUnescaping.m @@ -82,28 +82,39 @@ } - (OFString*)stringByXMLUnescapingWithDelegate: (id )delegate { - size_t i, last; + const char *string; + size_t i, last, length; BOOL inEntity; OFMutableString *ret; + string = [self cString]; + length = [self cStringLength]; + + ret = [OFMutableString string]; + + /* + * This is safe as we already called -[cString] on self and thus can be + * sure the string is correctly initialized, even if it is a constant + * string. + */ + ((OFString*)ret)->s->isUTF8 = s->isUTF8; + last = 0; inEntity = NO; - ret = [OFMutableString string]; - ((OFString*)ret)->isUTF8 = [self isUTF8]; for (i = 0; i < length; i++) { if (!inEntity && string[i] == '&') { [ret appendCStringWithoutUTF8Checking: string + last length: i - last]; last = i + 1; inEntity = YES; } else if (inEntity && string[i] == ';') { - char *entity = string + last; + const char *entity = string + last; size_t entityLength = i - last; if (entityLength == 2 && !memcmp(entity, "lt", 2)) [ret appendCStringWithoutUTF8Checking: "<" length: 1]; @@ -178,28 +189,39 @@ #ifdef OF_HAVE_BLOCKS - (OFString*)stringByXMLUnescapingWithBlock: (of_string_xml_unescaping_block_t)block { - size_t i, last; + const char *string; + size_t i, last, length; BOOL inEntity; OFMutableString *ret; + string = [self cString]; + length = [self cStringLength]; + + ret = [OFMutableString string]; + + /* + * This is safe as we already called -[cString] on self and thus can be + * sure the string is correctly initialized, even if it is a constant + * string. + */ + ((OFString*)ret)->s->isUTF8 = s->isUTF8; + last = 0; inEntity = NO; - ret = [OFMutableString string]; - ((OFString*)ret)->isUTF8 = [self isUTF8]; for (i = 0; i < length; i++) { if (!inEntity && string[i] == '&') { [ret appendCStringWithoutUTF8Checking: string + last length: i - last]; last = i + 1; inEntity = YES; } else if (inEntity && string[i] == ';') { - char *entity = string + last; + const char *entity = string + last; size_t entityLength = i - last; if (entityLength == 2 && !memcmp(entity, "lt", 2)) [ret appendCStringWithoutUTF8Checking: "<" length: 1]; Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -53,17 +53,39 @@ @class OFArray; @class OFURL; /** * \brief A class for handling strings. + * + * Warning: If you add methods to OFString using a category, you are not + * allowed to access the ivars directly, as these might be still uninitialized + * for a constant string and get initialized on the first message! Therefore, + * you should use the corresponding methods to get the ivars, which ensures the + * constant string is initialized. */ @interface OFString: OFObject { - char *string; - size_t length; - BOOL isUTF8; + /* + * The ivars have to be like this because OFConstantString bases on + * OFString. + * + * The compiler generates an instance with a const char* and a size_t + * for each constant string. We change the const char* to point to our + * struct on the first call to a constant string so we can have more + * than those two ivars. + */ + struct of_string_ivars { + char *string; + size_t length; + BOOL isUTF8; + } *restrict s; + /* + * Unused in OFString, however, OFConstantString sets this to SIZE_MAX + * once it allocated and initialized the struct. + */ + size_t initialized; } /** * \return A new autoreleased OFString */ @@ -507,14 +529,10 @@ /** * \return The length of the string which cString would return */ - (size_t)cStringLength; -/// \cond internal -- (BOOL)isUTF8; -/// \endcond - /** * Compares the OFString to another OFString without caring about the case. * * \param otherString A string to compare with * \return An of_comparison_result_t Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -417,97 +417,103 @@ - init { self = [super init]; @try { - string = [self allocMemoryWithSize: 1]; - string[0] = '\0'; + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); + + s->string = [self allocMemoryWithSize: 1]; + s->string[0] = '\0'; } @catch (id e) { [self release]; @throw e; } return self; } -- initWithCString: (const char*)string_ +- initWithCString: (const char*)string { - return [self initWithCString: string_ + return [self initWithCString: string encoding: OF_STRING_ENCODING_UTF_8 - length: strlen(string_)]; + length: strlen(string)]; } -- initWithCString: (const char*)string_ +- initWithCString: (const char*)string encoding: (of_string_encoding_t)encoding { - return [self initWithCString: string_ + return [self initWithCString: string encoding: encoding - length: strlen(string_)]; + length: strlen(string)]; } -- initWithCString: (const char*)string_ +- initWithCString: (const char*)string encoding: (of_string_encoding_t)encoding - length: (size_t)length_ + length: (size_t)length { self = [super init]; @try { size_t i, j; const uint16_t *table; if (encoding == OF_STRING_ENCODING_UTF_8 && - length_ >= 3 && !memcmp(string_, "\xEF\xBB\xBF", 3)) { - string_ += 3; - length_ -= 3; + length >= 3 && !memcmp(string, "\xEF\xBB\xBF", 3)) { + string += 3; + length -= 3; } - string = [self allocMemoryWithSize: length_ + 1]; - length = length_; + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); + + s->string = [self allocMemoryWithSize: length + 1]; + s->length = length; if (encoding == OF_STRING_ENCODING_UTF_8) { - switch (of_string_check_utf8(string_, length)) { + switch (of_string_check_utf8(string, length)) { case 1: - isUTF8 = YES; + s->isUTF8 = YES; break; case -1: @throw [OFInvalidEncodingException newWithClass: isa]; } - memcpy(string, string_, length); - string[length] = 0; + memcpy(s->string, string, length); + s->string[length] = 0; return self; } if (encoding == OF_STRING_ENCODING_ISO_8859_1) { - for (i = j = 0; i < length_; i++) { - char buf[4]; + for (i = j = 0; i < length; i++) { + char buffer[4]; size_t bytes; - if (!(string_[i] & 0x80)) { - string[j++] = string_[i]; + if (!(string[i] & 0x80)) { + s->string[j++] = string[i]; continue; } - isUTF8 = YES; + s->isUTF8 = YES; bytes = of_string_unicode_to_utf8( - (uint8_t)string_[i], buf); + (uint8_t)string[i], buffer); if (bytes == 0) @throw [OFInvalidEncodingException newWithClass: isa]; - length += bytes - 1; - string = [self resizeMemory: string - toSize: length + 1]; + s->length += bytes - 1; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; - memcpy(string + j, buf, bytes); + memcpy(s->string + j, buffer, bytes); j += bytes; } - string[length] = 0; + s->string[s->length] = 0; return self; } switch (encoding) { @@ -519,85 +525,89 @@ break; default: @throw [OFInvalidEncodingException newWithClass: isa]; } - for (i = j = 0; i < length_; i++) { - char buf[4]; + for (i = j = 0; i < length; i++) { + char buffer[4]; of_unichar_t character; size_t characterBytes; - if (!(string_[i] & 0x80)) { - string[j++] = string_[i]; + if (!(string[i] & 0x80)) { + s->string[j++] = string[i]; continue; } - character = table[(uint8_t)string_[i]]; + character = table[(uint8_t)string[i]]; if (character == 0xFFFD) @throw [OFInvalidEncodingException newWithClass: isa]; - isUTF8 = YES; + s->isUTF8 = YES; characterBytes = of_string_unicode_to_utf8(character, - buf); + buffer); if (characterBytes == 0) @throw [OFInvalidEncodingException newWithClass: isa]; - length += characterBytes - 1; - string = [self resizeMemory: string - toSize: length + 1]; + s->length += characterBytes - 1; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; - memcpy(string + j, buf, characterBytes); + memcpy(s->string + j, buffer, characterBytes); j += characterBytes; } - string[length] = 0; + s->string[s->length] = 0; } @catch (id e) { [self release]; @throw e; } return self; } -- initWithCString: (const char*)string_ - length: (size_t)length_ +- initWithCString: (const char*)string + length: (size_t)length { - return [self initWithCString: string_ + return [self initWithCString: string encoding: OF_STRING_ENCODING_UTF_8 - length: length_]; + length: length]; } -- initWithString: (OFString*)string_ +- initWithString: (OFString*)string { self = [super init]; @try { - /* We have no -[dealloc], so this is ok */ - string = (char*)[string_ cString]; - length = [string_ cStringLength]; + const char *cString; - switch (of_string_check_utf8(string, length)) { + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); + + cString = [string cString]; + s->length = [string cStringLength]; + + switch (of_string_check_utf8(cString, s->length)) { case 1: - isUTF8 = YES; + s->isUTF8 = YES; break; case -1:; @throw [OFInvalidEncodingException newWithClass: isa]; } - if ((string = strdup(string)) == NULL) + if ((s->string = strdup(cString)) == NULL) @throw [OFOutOfMemoryException newWithClass: isa - requestedSize: length + 1]; + requestedSize: s->length + 1]; @try { - [self addMemoryToPool: string]; + [self addMemoryToPool: s->string]; } @catch (id e) { - free(string); + free(s->string); @throw e; } } @catch (id e) { [self release]; @throw e; @@ -604,101 +614,104 @@ } return self; } -- initWithUnicodeString: (of_unichar_t*)string_ +- initWithUnicodeString: (of_unichar_t*)string { - return [self initWithUnicodeString: string_ + return [self initWithUnicodeString: string byteOrder: OF_ENDIANESS_NATIVE - length: of_unicode_string_length(string_)]; + length: of_unicode_string_length(string)]; } -- initWithUnicodeString: (of_unichar_t*)string_ +- initWithUnicodeString: (of_unichar_t*)string byteOrder: (of_endianess_t)byteOrder { - return [self initWithUnicodeString: string_ + return [self initWithUnicodeString: string byteOrder: byteOrder - length: of_unicode_string_length(string_)]; + length: of_unicode_string_length(string)]; } -- initWithUnicodeString: (of_unichar_t*)string_ - length: (size_t)length_ +- initWithUnicodeString: (of_unichar_t*)string + length: (size_t)length { - return [self initWithUnicodeString: string_ + return [self initWithUnicodeString: string byteOrder: OF_ENDIANESS_NATIVE - length: length_]; + length: length]; } -- initWithUnicodeString: (of_unichar_t*)string_ +- initWithUnicodeString: (of_unichar_t*)string byteOrder: (of_endianess_t)byteOrder - length: (size_t)length_ + length: (size_t)length { self = [super init]; @try { - char buffer[4]; size_t i, j = 0; BOOL swap = NO; - if (length_ > 0 && *string_ == 0xFEFF) { - string_++; - length_--; - } else if (length_ > 0 && *string_ == 0xFFFE0000) { + if (length > 0 && *string == 0xFEFF) { + string++; + length--; + } else if (length > 0 && *string == 0xFFFE0000) { swap = YES; - string_++; - length_--; + string++; + length--; } else if (byteOrder != OF_ENDIANESS_NATIVE) swap = YES; - length = length_; - string = [self allocMemoryWithSize: (length * 4) + 1]; + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); - for (i = 0; i < length_; i++) { + s->length = length; + s->string = [self allocMemoryWithSize: (length * 4) + 1]; + + for (i = 0; i < length; i++) { + char buffer[4]; size_t characterLen = of_string_unicode_to_utf8( - (swap ? of_bswap32(string_[i]) : string_[i]), + (swap ? of_bswap32(string[i]) : string[i]), buffer); switch (characterLen) { case 1: - string[j++] = buffer[0]; + s->string[j++] = buffer[0]; break; case 2: - isUTF8 = YES; - length++; + s->isUTF8 = YES; + s->length++; - memcpy(string + j, buffer, 2); + memcpy(s->string + j, buffer, 2); j += 2; break; case 3: - isUTF8 = YES; - length += 2; + s->isUTF8 = YES; + s->length += 2; - memcpy(string + j, buffer, 3); + memcpy(s->string + j, buffer, 3); j += 3; break; case 4: - isUTF8 = YES; - length += 3; + s->isUTF8 = YES; + s->length += 3; - memcpy(string + j, buffer, 4); + memcpy(s->string + j, buffer, 4); j += 4; break; default: @throw [OFInvalidEncodingException newWithClass: isa]; } } - string[j] = '\0'; + s->string[j] = '\0'; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't care, as we only tried to make it smaller */ [e release]; } } @catch (id e) { @@ -707,60 +720,63 @@ } return self; } -- initWithUTF16String: (uint16_t*)string_ +- initWithUTF16String: (uint16_t*)string { - return [self initWithUTF16String: string_ + return [self initWithUTF16String: string byteOrder: OF_ENDIANESS_NATIVE - length: of_utf16_string_length(string_)]; + length: of_utf16_string_length(string)]; } -- initWithUTF16String: (uint16_t*)string_ +- initWithUTF16String: (uint16_t*)string byteOrder: (of_endianess_t)byteOrder { - return [self initWithUTF16String: string_ + return [self initWithUTF16String: string byteOrder: byteOrder - length: of_utf16_string_length(string_)]; + length: of_utf16_string_length(string)]; } -- initWithUTF16String: (uint16_t*)string_ - length: (size_t)length_ +- initWithUTF16String: (uint16_t*)string + length: (size_t)length { - return [self initWithUTF16String: string_ + return [self initWithUTF16String: string byteOrder: OF_ENDIANESS_NATIVE - length: length_]; + length: length]; } -- initWithUTF16String: (uint16_t*)string_ +- initWithUTF16String: (uint16_t*)string byteOrder: (of_endianess_t)byteOrder - length: (size_t)length_ + length: (size_t)length { self = [super init]; @try { - char buffer[4]; size_t i, j = 0; BOOL swap = NO; - if (length_ > 0 && *string_ == 0xFEFF) { - string_++; - length_--; - } else if (length_ > 0 && *string_ == 0xFFFE) { + if (length > 0 && *string == 0xFEFF) { + string++; + length--; + } else if (length > 0 && *string == 0xFFFE) { swap = YES; - string_++; - length_--; + string++; + length--; } else if (byteOrder != OF_ENDIANESS_NATIVE) swap = YES; - length = length_; - string = [self allocMemoryWithSize: (length * 4) + 1]; + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); - for (i = 0; i < length_; i++) { + s->length = length; + s->string = [self allocMemoryWithSize: (length * 4) + 1]; + + for (i = 0; i < length; i++) { + char buffer[4]; of_unichar_t character = - (swap ? of_bswap16(string_[i]) : string_[i]); + (swap ? of_bswap16(string[i]) : string[i]); size_t characterLen; /* Missing high surrogate */ if ((character & 0xFC00) == 0xDC00) @throw [OFInvalidEncodingException @@ -767,17 +783,17 @@ newWithClass: isa]; if ((character & 0xFC00) == 0xD800) { uint16_t nextCharacter; - if (length_ <= i + 1) + if (length <= i + 1) @throw [OFInvalidEncodingException newWithClass: isa]; nextCharacter = (swap - ? of_bswap16(string_[i + 1]) - : string_[i + 1]); + ? of_bswap16(string[i + 1]) + : string[i + 1]); character = (((character & 0x3FF) << 10) | (nextCharacter & 0x3FF)) + 0x10000; i++; } @@ -785,47 +801,47 @@ characterLen = of_string_unicode_to_utf8( character, buffer); switch (characterLen) { case 1: - string[j++] = buffer[0]; + s->string[j++] = buffer[0]; break; case 2: - isUTF8 = YES; - length++; + s->isUTF8 = YES; + s->length++; - memcpy(string + j, buffer, 2); + memcpy(s->string + j, buffer, 2); j += 2; break; case 3: - isUTF8 = YES; - length += 2; + s->isUTF8 = YES; + s->length += 2; - memcpy(string + j, buffer, 3); + memcpy(s->string + j, buffer, 3); j += 3; break; case 4: - isUTF8 = YES; - length += 3; + s->isUTF8 = YES; + s->length += 3; - memcpy(string + j, buffer, 4); + memcpy(s->string + j, buffer, 4); j += 4; break; default: @throw [OFInvalidEncodingException newWithClass: isa]; } } - string[j] = '\0'; + s->string[j] = '\0'; @try { - string = [self resizeMemory: string - toSize: length + 1]; + s->string = [self resizeMemory: s->string + toSize: s->length + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't care, as we only tried to make it smaller */ [e release]; } } @catch (id e) { @@ -853,35 +869,38 @@ arguments: (va_list)arguments { self = [super init]; @try { - int len; + int length; if (format == nil) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; - if ((len = of_vasprintf(&string, [format cString], + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); + + if ((length = of_vasprintf(&s->string, [format cString], arguments)) == -1) @throw [OFInvalidFormatException newWithClass: isa]; + s->length = length; + @try { - length = len; - - switch (of_string_check_utf8(string, length)) { + switch (of_string_check_utf8(s->string, length)) { case 1: - isUTF8 = YES; + s->isUTF8 = YES; break; case -1: @throw [OFInvalidEncodingException newWithClass: isa]; } - [self addMemoryToPool: string]; + [self addMemoryToPool: s->string]; } @catch (id e) { - free(string); + free(s->string); } } @catch (id e) { [self release]; @throw e; } @@ -907,55 +926,58 @@ { self = [super init]; @try { OFString *component; - size_t i, length_; + size_t i, length; va_list argumentsCopy; - length = [firstComponent cStringLength]; + s = [self allocMemoryWithSize: sizeof(*s)]; + memset(s, 0, sizeof(*s)); + + s->length = [firstComponent cStringLength]; switch (of_string_check_utf8([firstComponent cString], - length)) { + s->length)) { case 1: - isUTF8 = YES; + s->isUTF8 = YES; break; case -1: @throw [OFInvalidEncodingException newWithClass: isa]; } /* Calculate length */ va_copy(argumentsCopy, arguments); while ((component = va_arg(argumentsCopy, OFString*)) != nil) { - length_ = [component cStringLength]; - length += 1 + length_; + length = [component cStringLength]; + s->length += 1 + length; switch (of_string_check_utf8([component cString], - length_)) { + length)) { case 1: - isUTF8 = YES; + s->isUTF8 = YES; break; case -1: @throw [OFInvalidEncodingException newWithClass: isa]; } } - string = [self allocMemoryWithSize: length + 1]; + s->string = [self allocMemoryWithSize: s->length + 1]; - length_ = [firstComponent cStringLength]; - memcpy(string, [firstComponent cString], length_); - i = length_; + length = [firstComponent cStringLength]; + memcpy(s->string, [firstComponent cString], length); + i = length; while ((component = va_arg(arguments, OFString*)) != nil) { - length_ = [component cStringLength]; - string[i] = OF_PATH_DELIM; - memcpy(string + i + 1, [component cString], length_); - i += 1 + length_; + length = [component cStringLength]; + s->string[i] = OF_PATH_DELIM; + memcpy(s->string + i + 1, [component cString], length); + i += 1 + length; } - string[i] = '\0'; + s->string[i] = '\0'; } @catch (id e) { [self release]; @throw e; } @@ -970,32 +992,30 @@ - initWithContentsOfFile: (OFString*)path encoding: (of_string_encoding_t)encoding { char *tmp; - struct stat s; - - self = [super init]; + struct stat st; @try { OFFile *file; - if (stat([path cString], &s) == -1) + if (stat([path cString], &st) == -1) @throw [OFOpenFileFailedException newWithClass: isa path: path mode: @"rb"]; - if (s.st_size > SIZE_MAX) + if (st.st_size > SIZE_MAX) @throw [OFOutOfRangeException newWithClass: isa]; file = [[OFFile alloc] initWithPath: path mode: @"rb"]; @try { - tmp = [self allocMemoryWithSize: (size_t)s.st_size]; + tmp = [self allocMemoryWithSize: (size_t)st.st_size]; - [file readExactlyNBytes: (size_t)s.st_size + [file readExactlyNBytes: (size_t)st.st_size intoBuffer: tmp]; } @finally { [file release]; } } @catch (id e) { @@ -1003,11 +1023,11 @@ @throw e; } self = [self initWithCString: tmp encoding: encoding - length: (size_t)s.st_size]; + length: (size_t)st.st_size]; [self freeMemory: tmp]; return self; } @@ -1097,43 +1117,34 @@ return self; } - (const char*)cString { - return string; + return s->string; } - (size_t)length { /* FIXME: Maybe cache this in an ivar? */ - if (![self isUTF8]) - return length; + if (!s->isUTF8) + return s->length; - return of_string_position_to_index(string, length); + return of_string_position_to_index(s->string, s->length); } - (size_t)cStringLength { - return length; -} - -- (BOOL)isUTF8 -{ - return isUTF8; + return s->length; } - (BOOL)isEqual: (id)object { - OFString *otherString; - if (![object isKindOfClass: [OFString class]]) return NO; - otherString = object; - - if (strcmp(string, [otherString cString])) + if (strcmp(s->string, [object cString])) return NO; return YES; } @@ -1157,16 +1168,16 @@ @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; otherString = object; otherLen = [otherString cStringLength]; - minLen = (length > otherLen ? otherLen : length); + minLen = (s->length > otherLen ? otherLen : s->length); - if ((cmp = memcmp(string, [otherString cString], minLen)) == 0) { - if (length > otherLen) + if ((cmp = memcmp(s->string, [otherString cString], minLen)) == 0) { + if (s->length > otherLen) return OF_ORDERED_DESCENDING; - if (length < otherLen) + if (s->length < otherLen) return OF_ORDERED_ASCENDING; return OF_ORDERED_SAME; } if (cmp > 0) @@ -1186,17 +1197,17 @@ selector: _cmd]; otherCString = [otherString cString]; otherLen = [otherString cStringLength]; - if (![self isUTF8]) { - minLen = (length > otherLen ? otherLen : length); + if (!s->isUTF8) { + minLen = (s->length > otherLen ? otherLen : s->length); - if ((cmp = memcasecmp(string, otherCString, minLen)) == 0) { - if (length > otherLen) + if ((cmp = memcasecmp(s->string, otherCString, minLen)) == 0) { + if (s->length > otherLen) return OF_ORDERED_DESCENDING; - if (length < otherLen) + if (s->length < otherLen) return OF_ORDERED_ASCENDING; return OF_ORDERED_SAME; } if (cmp > 0) @@ -1205,15 +1216,16 @@ return OF_ORDERED_ASCENDING; } i = j = 0; - while (i < length && j < otherLen) { + while (i < s->length && j < otherLen) { of_unichar_t c1, c2; size_t l1, l2; - l1 = of_string_utf8_to_unicode(string + i, length - i, &c1); + l1 = of_string_utf8_to_unicode(s->string + i, s->length - i, + &c1); l2 = of_string_utf8_to_unicode(otherCString + j, otherLen - j, &c2); if (l1 == 0 || l2 == 0 || c1 > 0x10FFFF || c2 > 0x10FFFF) @throw [OFInvalidEncodingException newWithClass: isa]; @@ -1241,13 +1253,13 @@ i += l1; j += l2; } - if (length - i > otherLen - j) + if (s->length - i > otherLen - j) return OF_ORDERED_DESCENDING; - else if (length - i < otherLen - j) + else if (s->length - i < otherLen - j) return OF_ORDERED_ASCENDING; return OF_ORDERED_SAME; } @@ -1255,12 +1267,12 @@ { uint32_t hash; size_t i; OF_HASH_INIT(hash); - for (i = 0; i < length; i++) - OF_HASH_ADD(hash, string[i]); + for (i = 0; i < s->length; i++) + OF_HASH_ADD(hash, s->string[i]); OF_HASH_FINALIZE(hash); return hash; } @@ -1296,119 +1308,121 @@ - (of_unichar_t)characterAtIndex: (size_t)index { of_unichar_t c; - if (![self isUTF8]) { - if (index >= length) + if (!s->isUTF8) { + if (index >= s->length) @throw [OFOutOfRangeException newWithClass: isa]; - return string[index]; + return s->string[index]; } - index = of_string_index_to_position(string, index, length); + index = of_string_index_to_position(s->string, index, s->length); - if (index >= length) + if (index >= s->length) @throw [OFOutOfRangeException newWithClass: isa]; - if (!of_string_utf8_to_unicode(string + index, length - index, &c)) + if (!of_string_utf8_to_unicode(s->string + index, s->length - index, + &c)) @throw [OFInvalidEncodingException newWithClass: isa]; return c; } -- (size_t)indexOfFirstOccurrenceOfString: (OFString*)string_ +- (size_t)indexOfFirstOccurrenceOfString: (OFString*)string { - const char *cString = [string_ cString]; - size_t stringLen = [string_ cStringLength]; + const char *cString = [string cString]; + size_t stringLen = [string cStringLength]; size_t i; if (stringLen == 0) return 0; - if (stringLen > length) + if (stringLen > s->length) return OF_INVALID_INDEX; - for (i = 0; i <= length - stringLen; i++) - if (!memcmp(string + i, cString, stringLen)) - return of_string_position_to_index(string, i); + for (i = 0; i <= s->length - stringLen; i++) + if (!memcmp(s->string + i, cString, stringLen)) + return of_string_position_to_index(s->string, i); return OF_INVALID_INDEX; } -- (size_t)indexOfLastOccurrenceOfString: (OFString*)string_ +- (size_t)indexOfLastOccurrenceOfString: (OFString*)string { - const char *cString = [string_ cString]; - size_t stringLen = [string_ cStringLength]; + const char *cString = [string cString]; + size_t stringLen = [string cStringLength]; size_t i; if (stringLen == 0) - return of_string_position_to_index(string, length); + return of_string_position_to_index(s->string, s->length); - if (stringLen > length) + if (stringLen > s->length) return OF_INVALID_INDEX; - for (i = length - stringLen;; i--) { - if (!memcmp(string + i, cString, stringLen)) - return of_string_position_to_index(string, i); + for (i = s->length - stringLen;; i--) { + if (!memcmp(s->string + i, cString, stringLen)) + return of_string_position_to_index(s->string, i); /* Did not match and we're at the last char */ if (i == 0) return OF_INVALID_INDEX; } } -- (BOOL)containsString: (OFString*)string_ +- (BOOL)containsString: (OFString*)string { - const char *cString = [string_ cString]; - size_t stringLen = [string_ cStringLength]; + const char *cString = [string cString]; + size_t stringLen = [string cStringLength]; size_t i; if (stringLen == 0) return YES; - if (stringLen > length) + if (stringLen > s->length) return NO; - for (i = 0; i <= length - stringLen; i++) - if (!memcmp(string + i, cString, stringLen)) + for (i = 0; i <= s->length - stringLen; i++) + if (!memcmp(s->string + i, cString, stringLen)) return YES; return NO; } - (OFString*)substringFromIndex: (size_t)start toIndex: (size_t)end { - if ([self isUTF8]) { - start = of_string_index_to_position(string, start, length); - end = of_string_index_to_position(string, end, length); + if (s->isUTF8) { + start = of_string_index_to_position(s->string, start, + s->length); + end = of_string_index_to_position(s->string, end, s->length); } if (start > end) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; - if (end > length) + if (end > s->length) @throw [OFOutOfRangeException newWithClass: isa]; - return [OFString stringWithCString: string + start + return [OFString stringWithCString: s->string + start length: end - start]; } - (OFString*)substringWithRange: (of_range_t)range { return [self substringFromIndex: range.start toIndex: range.start + range.length]; } -- (OFString*)stringByAppendingString: (OFString*)string_ +- (OFString*)stringByAppendingString: (OFString*)string { OFMutableString *new; new = [OFMutableString stringWithString: self]; - [new appendString: string_]; + [new appendString: string]; /* * Class swizzle the string to be immutable. We declared the return type * to be OFString*, so it can't be modified anyway. But not swizzling it * would create a real copy each time -[copy] is called. @@ -1415,15 +1429,15 @@ */ new->isa = [OFString class]; return new; } -- (OFString*)stringByPrependingString: (OFString*)string_ +- (OFString*)stringByPrependingString: (OFString*)string { OFMutableString *new; - new = [OFMutableString stringWithString: string_]; + new = [OFMutableString stringWithString: string]; [new appendString: self]; /* * Class swizzle the string to be immutable. We declared the return type * to be OFString*, so it can't be modified anyway. But not swizzling it @@ -1513,26 +1527,27 @@ return new; } - (BOOL)hasPrefix: (OFString*)prefix { - size_t length_ = [prefix cStringLength]; + size_t length = [prefix cStringLength]; - if (length_ > length) + if (length > s->length) return NO; - return !memcmp(string, [prefix cString], length_); + return !memcmp(s->string, [prefix cString], length); } - (BOOL)hasSuffix: (OFString*)suffix { - size_t length_ = [suffix cStringLength]; + size_t length = [suffix cStringLength]; - if (length_ > length) + if (length > s->length) return NO; - return !memcmp(string + (length - length_), [suffix cString], length_); + return !memcmp(s->string + (s->length - length), [suffix cString], + length); } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter { OFAutoreleasePool *pool; @@ -1542,27 +1557,27 @@ size_t i, last; array = [OFMutableArray array]; pool = [[OFAutoreleasePool alloc] init]; - if (delimLen > length) { + if (delimLen > s->length) { [array addObject: [[self copy] autorelease]]; [pool release]; return array; } - for (i = 0, last = 0; i <= length - delimLen; i++) { - if (memcmp(string + i, delim, delimLen)) + for (i = 0, last = 0; i <= s->length - delimLen; i++) { + if (memcmp(s->string + i, delim, delimLen)) continue; - [array addObject: [OFString stringWithCString: string + last + [array addObject: [OFString stringWithCString: s->string + last length: i - last]]; i += delimLen - 1; last = i + 1; } - [array addObject: [OFString stringWithCString: string + last]]; + [array addObject: [OFString stringWithCString: s->string + last]]; [pool release]; /* * Class swizzle the array to be immutable. We declared the return type @@ -1575,40 +1590,40 @@ - (OFArray*)pathComponents { OFMutableArray *ret; OFAutoreleasePool *pool; - size_t i, last = 0, pathLen = length; + size_t i, last = 0, pathLen = s->length; ret = [OFMutableArray array]; if (pathLen == 0) return ret; pool = [[OFAutoreleasePool alloc] init]; #ifndef _WIN32 - if (string[pathLen - 1] == OF_PATH_DELIM) + if (s->string[pathLen - 1] == OF_PATH_DELIM) #else - if (string[pathLen - 1] == '/' || string[pathLen - 1] == '\\') + if (s->string[pathLen - 1] == '/' || s->string[pathLen - 1] == '\\') #endif pathLen--; for (i = 0; i < pathLen; i++) { #ifndef _WIN32 - if (string[i] == OF_PATH_DELIM) { + if (s->string[i] == OF_PATH_DELIM) { #else - if (string[i] == '/' || string[i] == '\\') { + if (s->string[i] == '/' || s->string[i] == '\\') { #endif [ret addObject: - [OFString stringWithCString: string + last + [OFString stringWithCString: s->string + last length: i - last]]; last = i + 1; } } - [ret addObject: [OFString stringWithCString: string + last + [ret addObject: [OFString stringWithCString: s->string + last length: i - last]]; [pool release]; /* @@ -1620,28 +1635,28 @@ return ret; } - (OFString*)lastPathComponent { - size_t pathLen = length; + size_t pathLen = s->length; ssize_t i; if (pathLen == 0) return @""; #ifndef _WIN32 - if (string[pathLen - 1] == OF_PATH_DELIM) + if (s->string[pathLen - 1] == OF_PATH_DELIM) #else - if (string[pathLen - 1] == '/' || string[pathLen - 1] == '\\') + if (s->string[pathLen - 1] == '/' || s->string[pathLen - 1] == '\\') #endif pathLen--; for (i = pathLen - 1; i >= 0; i--) { #ifndef _WIN32 - if (string[i] == OF_PATH_DELIM) { + if (s->string[i] == OF_PATH_DELIM) { #else - if (string[i] == '/' || string[i] == '\\') { + if (s->string[i] == '/' || s->string[i] == '\\') { #endif i++; break; } } @@ -1651,143 +1666,143 @@ * removed, so return a new string anyway. */ if (i < 0) i = 0; - return [OFString stringWithCString: string + i + return [OFString stringWithCString: s->string + i length: pathLen - i]; } - (OFString*)stringByDeletingLastPathComponent { - size_t i, pathLen = length; + size_t i, pathLen = s->length; if (pathLen == 0) return @""; #ifndef _WIN32 - if (string[pathLen - 1] == OF_PATH_DELIM) + if (s->string[pathLen - 1] == OF_PATH_DELIM) #else - if (string[pathLen - 1] == '/' || string[pathLen - 1] == '\\') + if (s->string[pathLen - 1] == '/' || s->string[pathLen - 1] == '\\') #endif pathLen--; if (pathLen == 0) - return [OFString stringWithCString: string + return [OFString stringWithCString: s->string length: 1]; for (i = pathLen - 1; i >= 1; i--) #ifndef _WIN32 - if (string[i] == OF_PATH_DELIM) + if (s->string[i] == OF_PATH_DELIM) #else - if (string[i] == '/' || string[i] == '\\') + if (s->string[i] == '/' || s->string[i] == '\\') #endif - return [OFString stringWithCString: string + return [OFString stringWithCString: s->string length: i]; #ifndef _WIN32 - if (string[0] == OF_PATH_DELIM) + if (s->string[0] == OF_PATH_DELIM) #else - if (string[i] == '/' || string[i] == '\\') + if (s->string[i] == '/' || s->string[i] == '\\') #endif - return [OFString stringWithCString: string + return [OFString stringWithCString: s->string length: 1]; return @"."; } - (intmax_t)decimalValue { - const char *string_ = string; - size_t length_ = length; + const char *string = s->string; + size_t length = s->length; int i = 0; intmax_t num = 0; BOOL expectWhitespace = NO; - while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' || - *string_ == '\r') { - string_++; - length_--; + while (*string == ' ' || *string == '\t' || *string == '\n' || + *string == '\r') { + string++; + length--; } - if (string_[0] == '-' || string_[0] == '+') + if (string[0] == '-' || string[0] == '+') i++; - for (; i < length_; i++) { + for (; i < length; i++) { if (expectWhitespace) { - if (string_[i] != ' ' && string_[i] != '\t' && - string_[i] != '\n' && string_[i] != '\r') + if (string[i] != ' ' && string[i] != '\t' && + string[i] != '\n' && string[i] != '\r') @throw [OFInvalidFormatException newWithClass: isa]; continue; } - if (string_[i] >= '0' && string_[i] <= '9') { + if (string[i] >= '0' && string[i] <= '9') { if (INTMAX_MAX / 10 < num || - INTMAX_MAX - num * 10 < string_[i] - '0') + INTMAX_MAX - num * 10 < string[i] - '0') @throw [OFOutOfRangeException newWithClass: isa]; - num = (num * 10) + (string_[i] - '0'); - } else if (string_[i] == ' ' || string_[i] == '\t' || - string_[i] == '\n' || string_[i] == '\r') + num = (num * 10) + (string[i] - '0'); + } else if (string[i] == ' ' || string[i] == '\t' || + string[i] == '\n' || string[i] == '\r') expectWhitespace = YES; else @throw [OFInvalidFormatException newWithClass: isa]; } - if (string_[0] == '-') + if (string[0] == '-') num *= -1; return num; } - (uintmax_t)hexadecimalValue { - const char *string_ = string; - size_t length_ = length; + const char *string = s->string; + size_t length = s->length; int i = 0; uintmax_t num = 0; BOOL expectWhitespace = NO, gotNumber = NO; - while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' || - *string_ == '\r') { - string_++; - length_--; + while (*string == ' ' || *string == '\t' || *string == '\n' || + *string == '\r') { + string++; + length--; } - if (length_ == 0) + if (length == 0) return 0; - if (length_ >= 2 && string_[0] == '0' && string_[1] == 'x') + if (length >= 2 && string[0] == '0' && string[1] == 'x') i = 2; - else if (length_ >= 1 && (string_[0] == 'x' || string_[0] == '$')) + else if (length >= 1 && (string[0] == 'x' || string[0] == '$')) i = 1; - for (; i < length_; i++) { + for (; i < length; i++) { uintmax_t newNum; if (expectWhitespace) { - if (string_[i] != ' ' && string_[i] != '\t' && - string_[i] != '\n' && string_[i] != '\r') + if (string[i] != ' ' && string[i] != '\t' && + string[i] != '\n' && string[i] != '\r') @throw [OFInvalidFormatException newWithClass: isa]; continue; } - if (string_[i] >= '0' && string_[i] <= '9') { - newNum = (num << 4) | (string_[i] - '0'); - gotNumber = YES; - } else if (string_[i] >= 'A' && string_[i] <= 'F') { - newNum = (num << 4) | (string_[i] - 'A' + 10); - gotNumber = YES; - } else if (string_[i] >= 'a' && string_[i] <= 'f') { - newNum = (num << 4) | (string_[i] - 'a' + 10); - gotNumber = YES; - } else if (string_[i] == 'h' || string_[i] == ' ' || - string_[i] == '\t' || string_[i] == '\n' || - string_[i] == '\r') { + if (string[i] >= '0' && string[i] <= '9') { + newNum = (num << 4) | (string[i] - '0'); + gotNumber = YES; + } else if (string[i] >= 'A' && string[i] <= 'F') { + newNum = (num << 4) | (string[i] - 'A' + 10); + gotNumber = YES; + } else if (string[i] >= 'a' && string[i] <= 'f') { + newNum = (num << 4) | (string[i] - 'a' + 10); + gotNumber = YES; + } else if (string[i] == 'h' || string[i] == ' ' || + string[i] == '\t' || string[i] == '\n' || + string[i] == '\r') { expectWhitespace = YES; continue; } else @throw [OFInvalidFormatException newWithClass: isa]; @@ -1803,19 +1818,19 @@ return num; } - (float)floatValue { - const char *string_ = string; + const char *string = s->string; char *endPointer = NULL; float value; - while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' || - *string_ == '\r') - string_++; + while (*string == ' ' || *string == '\t' || *string == '\n' || + *string == '\r') + string++; - value = strtof(string_, &endPointer); + value = strtof(string, &endPointer); /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && @@ -1826,19 +1841,19 @@ return value; } - (double)doubleValue { - const char *string_ = string; + const char *string = s->string; char *endPointer = NULL; double value; - while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' || - *string_ == '\r') - string_++; + while (*string == ' ' || *string == '\t' || *string == '\n' || + *string == '\r') + string++; - value = strtod(string_, &endPointer); + value = strtod(string, &endPointer); /* Check if there are any invalid chars left */ if (endPointer != NULL) for (; *endPointer != '\0'; endPointer++) if (*endPointer != ' ' && *endPointer != '\t' && @@ -1861,15 +1876,16 @@ i = 0; j = 0; ret[j++] = 0xFEFF; - while (i < length) { + while (i < s->length) { of_unichar_t c; size_t cLen; - cLen = of_string_utf8_to_unicode(string + i, length - i, &c); + cLen = of_string_utf8_to_unicode(s->string + i, s->length - i, + &c); if (cLen == 0 || c > 0x10FFFF) @throw [OFInvalidEncodingException newWithClass: isa]; ret[j++] = c;