Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -166,30 +166,45 @@ * variables from the environment which applications might * expect. */ pool = objc_autoreleasePoolPush(); - if ((env = getenv("HOME")) != NULL) - [environment - setObject: [OFString stringWithUTF8String: env] - forKey: @"HOME"]; - if ((env = getenv("PATH")) != NULL) - [environment - setObject: [OFString stringWithUTF8String: env] - forKey: @"PATH"]; - if ((env = getenv("SHELL")) != NULL) - [environment - setObject: [OFString stringWithUTF8String: env] - forKey: @"SHELL"]; - if ((env = getenv("TMPDIR")) != NULL) - [environment - setObject: [OFString stringWithUTF8String: env] - forKey: @"TMPDIR"]; - if ((env = getenv("USER")) != NULL) - [environment - setObject: [OFString stringWithUTF8String: env] - forKey: @"USER"]; + if ((env = getenv("HOME")) != NULL) { + OFString *home = [[[OFString alloc] + initWithUTF8StringNoCopy: env + freeWhenDone: NO] autorelease]; + [environment setObject: home + forKey: @"HOME"]; + } + if ((env = getenv("PATH")) != NULL) { + OFString *path = [[[OFString alloc] + initWithUTF8StringNoCopy: env + freeWhenDone: NO] autorelease]; + [environment setObject: path + forKey: @"PATH"]; + } + if ((env = getenv("SHELL")) != NULL) { + OFString *shell = [[[OFString alloc] + initWithUTF8StringNoCopy: env + freeWhenDone: NO] autorelease]; + [environment setObject: shell + forKey: @"SHELL"]; + } + if ((env = getenv("TMPDIR")) != NULL) { + OFString *tmpdir = [[[OFString alloc] + initWithUTF8StringNoCopy: env + freeWhenDone: NO] autorelease]; + [environment setObject: tmpdir + forKey: @"TMPDIR"]; + } + if ((env = getenv("USER")) != NULL) { + OFString *user = [[[OFString alloc] + initWithUTF8StringNoCopy: env + freeWhenDone: NO] autorelease]; + [environment setObject: user + forKey: @"USER"]; + } objc_autoreleasePoolPop(pool); #endif [environment makeImmutable]; Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -145,15 +145,14 @@ - (void)finishInitialization { struct of_string_utf8_ivars *ivars; - if ((ivars = malloc(sizeof(*ivars))) == NULL) + if ((ivars = calloc(1, sizeof(*ivars))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: [self class] requestedSize: sizeof(*ivars)]; - memset(ivars, 0, sizeof(*ivars)); ivars->cString = cString; ivars->cStringLength = cStringLength; switch (of_string_check_utf8(ivars->cString, ivars->cStringLength, Index: src/OFMutableString_UTF8.m ================================================================== --- src/OFMutableString_UTF8.m +++ src/OFMutableString_UTF8.m @@ -41,10 +41,16 @@ + (void)initialize { if (self == [OFMutableString_UTF8 class]) [self inheritMethodsFromClass: [OFString_UTF8 class]]; } + +- initWithUTF8StringNoCopy: (const char*)UTF8String + freeWhenDone: (BOOL)freeWhenDone +{ + return [self initWithUTF8String: UTF8String]; +} - (void)_convertWithWordStartTable: (const of_unichar_t *const[])startTable wordMiddleTable: (const of_unichar_t *const[])middleTable wordStartTableSize: (size_t)startTableSize wordMiddleTableSize: (size_t)middleTableSize Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -311,10 +311,24 @@ * \return An initialized OFString */ - initWithUTF8String: (const char*)UTF8String length: (size_t)UTF8StringLength; +/** + * \brief Initializes an already allocated OFString from an UTF-8 encoded C + * string without copying it, if possible. + * + * \note Mutable versions always create a copy! + * + * \param UTF8String A UTF-8 encoded C string to initialize the OFString with + * \param freeWhenDone Whether to free the C string when it is not needed + * anymore + * \return An initialized OFString + */ +- initWithUTF8StringNoCopy: (const char*)UTF8String + freeWhenDone: (BOOL)freeWhenDone; + /** * \brief Initializes an already allocated OFString from a C string with the * specified encoding. * * \param cString A C string to initialize the OFString with Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -294,10 +294,18 @@ return (id)[string _initWithUTF8String: UTF8String length: UTF8StringLength storage: storage]; } + +- initWithUTF8StringNoCopy: (const char*)UTF8String + freeWhenDone: (BOOL)freeWhenDone +{ + return (id)[[OFString_UTF8 alloc] + initWithUTF8StringNoCopy: UTF8String + freeWhenDone: freeWhenDone]; +} - initWithCString: (const char*)cString encoding: (of_string_encoding_t)encoding { if (encoding == OF_STRING_ENCODING_UTF_8) { @@ -675,10 +683,16 @@ { return [self initWithCString: UTF8String encoding: OF_STRING_ENCODING_UTF_8 length: UTF8StringLength]; } + +- initWithUTF8StringNoCopy: (const char*)UTF8String + freeWhenDone: (BOOL)freeWhenDone +{ + return [self initWithUTF8String: UTF8String]; +} - initWithCString: (const char*)cString encoding: (of_string_encoding_t)encoding { return [self initWithCString: cString Index: src/OFString_UTF8.h ================================================================== --- src/OFString_UTF8.h +++ src/OFString_UTF8.h @@ -31,13 +31,14 @@ size_t cStringLength; BOOL UTF8; size_t length; BOOL hashed; uint32_t hash; + char *freeWhenDone; } *restrict s; struct of_string_utf8_ivars s_store; } - _initWithUTF8String: (const char*)UTF8String length: (size_t)UTF8StringLength storage: (char*)storage; @end Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -242,10 +242,49 @@ @throw e; } return self; } + +- initWithUTF8StringNoCopy: (const char*)UTF8String + freeWhenDone: (BOOL)freeWhenDone +{ + self = [super init]; + + @try { + size_t UTF8StringLength = strlen(UTF8String); + + if (freeWhenDone) + s->freeWhenDone = (char*)UTF8String; + + if (UTF8StringLength >= 3 && + !memcmp(UTF8String, "\xEF\xBB\xBF", 3)) { + UTF8String += 3; + UTF8StringLength -= 3; + } + + s = &s_store; + + s->cString = (char*)UTF8String; + s->cStringLength = UTF8StringLength; + + switch (of_string_check_utf8(UTF8String, UTF8StringLength, + &s->length)) { + case 1: + s->UTF8 = YES; + break; + case -1: + @throw [OFInvalidEncodingException + exceptionWithClass: [self class]]; + } + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - initWithString: (OFString*)string { self = [super init]; @@ -569,10 +608,18 @@ @throw e; } return self; } + +- (void)dealloc +{ + if (s != NULL && s->freeWhenDone != NULL) + free(s->freeWhenDone); + + [super dealloc]; +} - (const char*)UTF8String { return s->cString; }