/* * Copyright (c) 2008, 2009, 2010, 2011, 2012 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #define OF_CONSTANT_STRING_M #include <stdlib.h> #include <string.h> #import "OFConstantString.h" #import "OFString_UTF8.h" #import "OFInitializationFailedException.h" #import "OFInvalidEncodingException.h" #import "OFNotImplementedException.h" #import "OFOutOfMemoryException.h" #if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__) # import <objc/runtime.h> struct { struct class *isa, *super_class; const char *name; long version, info, instance_size; struct ivar_list *ivars; struct method_list **methodLists; struct cache *cache; struct protocol_list *protocols; const char *ivar_layout; struct class_ext *ext; } _OFConstantStringClassReference; #endif @interface OFString_const: OFString_UTF8 @end @implementation OFString_const + alloc { @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; } - (void)addMemoryToPool: (void*)ptr { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)allocMemoryWithSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)allocMemoryForNItems: (size_t)nitems withSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)resizeMemory: (void*)ptr toSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)resizeMemory: (void*)ptr toNItems: (size_t)nitems withSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void)freeMemory: (void*)ptr { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - retain { return self; } - autorelease { return self; } - (unsigned int)retainCount { return OF_RETAIN_COUNT_MAX; } - (void)release { } - (void)dealloc { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; [super dealloc]; /* Get rid of a stupid warning */ } @end @implementation OFConstantString + (void)load { #if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__) /* * objc_setFutureClass suddenly stopped working as OFConstantString * became more complex. So the only solution is to make * _OFConstantStringClassRerence the actual class, but there is no * objc_initializeClassPair in 10.5. However, objc_allocateClassPair * does not register the new class with the subclass in the ObjC1 * runtime like the ObjC2 runtime does, so this workaround should be * fine. */ Class class; if ((class = objc_allocateClassPair(self, "OFConstantString_hack", 0)) == NULL) @throw [OFInitializationFailedException exceptionWithClass: self]; memcpy(&_OFConstantStringClassReference, class, sizeof(_OFConstantStringClassReference)); free(class); objc_registerClassPair((Class)&_OFConstantStringClassReference); #endif } - (void)finishInitialization { struct of_string_utf8_ivars *ivars; if ((ivars = malloc(sizeof(*ivars))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: isa requestedSize: sizeof(*ivars)]; memset(ivars, 0, sizeof(*ivars)); ivars->cString = cString; ivars->cStringLength = cStringLength; switch (of_string_check_utf8(ivars->cString, ivars->cStringLength, &ivars->length)) { case 1: ivars->UTF8 = YES; break; case -1: free(ivars); @throw [OFInvalidEncodingException exceptionWithClass: isa]; } cString = (char*)ivars; isa = [OFString_const class]; } + alloc { @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; } - (void)addMemoryToPool: (void*)ptr { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)allocMemoryWithSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)allocMemoryForNItems: (size_t)nitems withSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)resizeMemory: (void*)ptr toSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)resizeMemory: (void*)ptr toNItems: (size_t)nitems withSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void)freeMemory: (void*)ptr { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - retain { return self; } - autorelease { return self; } - (unsigned int)retainCount { return OF_RETAIN_COUNT_MAX; } - (void)release { } - (void)dealloc { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; [super dealloc]; /* Get rid of a stupid warning */ } /* * In all following methods, the constant string is converted to an * OFString_UTF8 and the message sent again. */ /* From protocol OFCopying */ - copy { [self finishInitialization]; return [self copy]; } /* From protocol OFMutableCopying */ - mutableCopy { [self finishInitialization]; return [self mutableCopy]; } /* From protocol OFComparing */ - (of_comparison_result_t)compare: (id)object { [self finishInitialization]; return [self compare: object]; } /* From OFObject, but reimplemented in OFString */ - (BOOL)isEqual: (id)object { [self finishInitialization]; return [self isEqual: object]; } - (uint32_t)hash { [self finishInitialization]; return [self hash]; } - (OFString*)description { [self finishInitialization]; return [self description]; } /* From OFString */ - (const char*)UTF8String { [self finishInitialization]; return [self UTF8String]; } - (const char*)cStringWithEncoding: (of_string_encoding_t)encoding { [self finishInitialization]; return [self cStringWithEncoding: encoding]; } - (size_t)length { [self finishInitialization]; return [self length]; } - (size_t)UTF8StringLength { [self finishInitialization]; return [self UTF8StringLength]; } - (size_t)cStringLengthWithEncoding: (of_string_encoding_t)encoding { [self finishInitialization]; return [self cStringLengthWithEncoding: encoding]; } - (of_comparison_result_t)caseInsensitiveCompare: (OFString*)otherString { [self finishInitialization]; return [self caseInsensitiveCompare: otherString]; } - (of_unichar_t)characterAtIndex: (size_t)index { [self finishInitialization]; return [self characterAtIndex: index]; } - (void)getCharacters: (of_unichar_t*)buffer inRange: (of_range_t)range { [self finishInitialization]; return [self getCharacters: buffer inRange: range]; } - (size_t)indexOfFirstOccurrenceOfString: (OFString*)string { [self finishInitialization]; return [self indexOfFirstOccurrenceOfString: string]; } - (size_t)indexOfLastOccurrenceOfString: (OFString*)string { [self finishInitialization]; return [self indexOfLastOccurrenceOfString: string]; } - (BOOL)containsString: (OFString*)string { [self finishInitialization]; return [self containsString: string]; } - (OFString*)substringWithRange: (of_range_t)range { [self finishInitialization]; return [self substringWithRange: range]; } - (OFString*)stringByAppendingString: (OFString*)string { [self finishInitialization]; return [self stringByAppendingString: string]; } - (OFString*)stringByPrependingString: (OFString*)string { [self finishInitialization]; return [self stringByPrependingString: string]; } - (OFString*)uppercaseString { [self finishInitialization]; return [self uppercaseString]; } - (OFString*)lowercaseString { [self finishInitialization]; return [self lowercaseString]; } - (OFString*)stringByDeletingLeadingWhitespaces { [self finishInitialization]; return [self stringByDeletingLeadingWhitespaces]; } - (OFString*)stringByDeletingTrailingWhitespaces { [self finishInitialization]; return [self stringByDeletingTrailingWhitespaces]; } - (OFString*)stringByDeletingEnclosingWhitespaces { [self finishInitialization]; return [self stringByDeletingEnclosingWhitespaces]; } - (BOOL)hasPrefix: (OFString*)prefix { [self finishInitialization]; return [self hasPrefix: prefix]; } - (BOOL)hasSuffix: (OFString*)suffix { [self finishInitialization]; return [self hasSuffix: suffix]; } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter { [self finishInitialization]; return [self componentsSeparatedByString: delimiter]; } - (OFArray*)pathComponents { [self finishInitialization]; return [self pathComponents]; } - (OFString*)lastPathComponent { [self finishInitialization]; return [self lastPathComponent]; } - (OFString*)stringByDeletingLastPathComponent { [self finishInitialization]; return [self stringByDeletingLastPathComponent]; } - (intmax_t)decimalValue { [self finishInitialization]; return [self decimalValue]; } - (uintmax_t)hexadecimalValue { [self finishInitialization]; return [self hexadecimalValue]; } - (float)floatValue { [self finishInitialization]; return [self floatValue]; } - (double)doubleValue { [self finishInitialization]; return [self doubleValue]; } - (const of_unichar_t*)unicodeString { [self finishInitialization]; return [self unicodeString]; } - (const uint16_t*)UTF16String { [self finishInitialization]; return [self UTF16String]; } - (void)writeToFile: (OFString*)path { [self finishInitialization]; return [self writeToFile: path]; } #ifdef OF_HAVE_BLOCKS - (void)enumerateLinesUsingBlock: (of_string_line_enumeration_block_t)block { [self finishInitialization]; return [self enumerateLinesUsingBlock: block]; } #endif @end