Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,9 +1,56 @@ Legend: * Changes of existing features or bugfixes. + New features. +ObjFW 0.5.3 -> ObjFW 0.5.4, 30.08.2011 + * The blocks runtime is now working correctly. + * Documentation fixes. + * -framework works with objfw-compile now. + + Support for QNX. + * Various small fixes. + +ObjFW 0.5.2 -> ObjFW 0.5.3, 01.07.2011 + * Lots of bugfixes, see Mercurial log for details. (hg log -b 0.5) + +ObjFW 0.5.1 -> ObjFW 0.5.2, 25.04.2011 + * Fix double-retain in OFList. + * Don't ignore the timeout in OFStreamObserver when using select(). + * Do -[OFURL copy] in a try block to prevent a leak when an exception occurs. + * Fix too big buffer in -[OFMutableString _applyTable:withSize:]. + * Call madvise() on the correct length variable so it covers the whole string. + * Fix a warning when sizeof(size_t) < sizeof(long long). + * Skip possible BOMs when appending strings. + +ObjFW 0.5 -> ObjFW 0.5.1, 21.04.2011 + * Work around a wrong warning produced by Apple GCC 4.0.1 which would cause + the build to fail due to -Werror. + * Call objc_thread_{add,remove} when using the GNU runtime to make sure the + runtime knows about our thread. + * Detach a thread before restarting if it was never joined. + * Release the old return value when restarting a thread. + +ObjFW 0.4-alpha1 -> 0.5, 09.04.2011 + + %@ is now allowed in format strings. + + Added of_log for easy logging. + * Exceptions have one header per exception now. + * Lots of exception improvements. + * Huge improvements in XML handling. + * Improvements in socket handling, including improved API. + * OFStreamObserver is now thread-safe and stops the current observe call when + the set of streams to observe is modified. + + New class OFURL. + + New class OFHTTPRequest. + + New class OFCondition. + * Improvements in objfw-compile. + + Blocks can be used together with Cocoa now. + + When linking ObjFW and Cocoa, OFAutoreleasePools are used by both now. + + Support for Base64. + + Use a real Xcode project instead of just calling make. + + Add Haiku to the list of supported platforms. + * Lots of small bugfixes and countless small changes. Read the commits! + ObjFW 0.3.1 -> 0.4-alpha1, 03.01.2011 * ObjFW is now available under the terms of the QPL, GPLv2 and GPLv3. + Support for blocks was added, including a blocks runtime. + Added support for the new GNU runtime, introduced in GCC 4.6. * Objects returned from collections are no longer retained and autoreleased. Index: Info.plist ================================================================== --- Info.plist +++ Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType FMWK CFBundleSignature OBJFW CFBundleVersion - 0.4-dev + 0.5.4 CFBundleShortVersionString - 0.4-dev + 0.5.4 Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -190,11 +190,11 @@ 4B55A100133ABEA900B58A93 /* OFThreadJoinFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */; }; 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A102133ABEA900B58A93 /* OFThreadStartFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */; }; 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A104133ABEA900B58A93 /* OFThreadStillRunningException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FE133ABEA900B58A93 /* OFThreadStillRunningException.m */; }; - 4B55A109133AC05100B58A93 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A106133AC05100B58A93 /* common.h */; }; + 4B55A109133AC05100B58A93 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A106133AC05100B58A93 /* common.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A10A133AC05100B58A93 /* OFOpenFileFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A107133AC05100B58A93 /* OFOpenFileFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A10B133AC05100B58A93 /* OFOpenFileFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A108133AC05100B58A93 /* OFOpenFileFailedException.m */; }; 4B55A112133AC24600B58A93 /* OFReadFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10C133AC24500B58A93 /* OFReadFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A113133AC24600B58A93 /* OFReadFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */; }; 4B55A114133AC24600B58A93 /* OFReadOrWriteFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -253,12 +253,10 @@ 4BF33B0E133807A20059CEF7 /* OFXMLElementBuilderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67C1235358D0076B512 /* OFXMLElementBuilderTests.m */; }; 4BF33B0F133807A20059CEF7 /* OFXMLElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67D1235358D0076B512 /* OFXMLElementTests.m */; }; 4BF33B10133807A20059CEF7 /* OFXMLParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67E1235358D0076B512 /* OFXMLParserTests.m */; }; 4BF33B11133807A20059CEF7 /* PropertiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF67F1235358D0076B512 /* PropertiesTests.m */; }; 4BF33B12133807A20059CEF7 /* TestsAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6811235358D0076B512 /* TestsAppDelegate.m */; }; - 4BF33B4413380CD40059CEF7 /* testfile.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BF33B4213380CD40059CEF7 /* testfile.bin */; }; - 4BF33B4513380CD40059CEF7 /* testfile.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4BF33B4313380CD40059CEF7 /* testfile.txt */; }; 4BF33B4713380CE20059CEF7 /* testfile.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BF33B4313380CD40059CEF7 /* testfile.txt */; }; 4BF33B4813380D2D0059CEF7 /* testfile.bin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BF33B4213380CD40059CEF7 /* testfile.bin */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1022,12 +1020,12 @@ 4B17FFB1133A3664003E6DCD /* OFUnsupportedProtocolException.h in Headers */, 4B55A0FF133ABEA900B58A93 /* OFThreadJoinFailedException.h in Headers */, 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */, 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */, 4B55A116133AC24600B58A93 /* OFWriteFailedException.h in Headers */, - 4BDF37B51338055600F9A81A /* config.h in Headers */, 4B55A109133AC05100B58A93 /* common.h in Headers */, + 4BDF37B51338055600F9A81A /* config.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ @@ -1122,12 +1120,10 @@ /* Begin PBXResourcesBuildPhase section */ 4B3D23741337FBC800DD29B8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4BF33B4413380CD40059CEF7 /* testfile.bin in Resources */, - 4BF33B4513380CD40059CEF7 /* testfile.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ Index: PLATFORMS ================================================================== --- PLATFORMS +++ PLATFORMS @@ -22,21 +22,23 @@ +--------------------------+--------------+----------------------+---------+ | MirBSD 10uAB - 10uAD | x86 | GCC 4.4.2 | old GNU | | MirBSD 10uAD | x86 | LLVM/Clang r90573 | old GNU | +--------------------------+--------------+----------------------+---------+ | NetBSD 4.0 | x86 | GCC 4.1.2 prerelease | old GNU | - | NetBSD 5.1 RC4 | x86_64 | GCC 4.1.3 prerelease | old GNU | - | NetBSD 5.1 RC4 | x86_64 | GCC 4.6 | GNU | - | NetBSD 5.1 RC4 | x86_64 | LLVM/Clang r117892 | old GNU | + | NetBSD 5.1 | x86_64 | GCC 4.1.3 prerelease | old GNU | + | NetBSD 5.1 | x86_64 | GCC 4.6 | GNU | + | NetBSD 5.1 | x86_64 | LLVM/Clang r134860 | old GNU | +--------------------------+--------------+----------------------+---------+ | OpenBSD 4.6 - 4.7 | x86_64 | GCC 4.2.1 - 4.2.4 | old GNU | +--------------------------+--------------+----------------------+---------+ | OpenSolaris 2009.06 | x86 | | old GNU | | OpenSolaris 2009.06 | x86_64 | | old GNU | +--------------------------+--------------+----------------------+---------+ - | Windows XP - 7 / Cygwin | x86 | | old GMU | + | QNX 6.5.0 | x86 | GCC 4.6.1 | GNU | + +--------------------------+--------------+----------------------+---------+ + | Windows XP - 7 / Cygwin | x86 | | old GNU | | Windows XP - 7 / MinGW32 | x86 | | old GNU | | Windows 7 / MinGW64 | x86_64 | | old GNU | +--------------------------+--------------+----------------------+---------+ Basically, it should run on any POSIX system to which GCC 4 or a recent Clang version has been ported. If not, please send an e-mail with a bug report. Index: README ================================================================== --- README +++ README @@ -22,16 +22,16 @@ BUILDING AS A MAC OS X FRAMEWORK It is also possible to build ObjFW as a Mac OS X framework. To do so, - just execute xcodebuild in the root directory of ObjFW or open the - .xcodeproj in Xcode and choose Build -> Build from the menu. Copy the + just execute xcodebuild -target ObjFW in the root directory of ObjFW or open + the .xcodeproj in Xcode and choose Build -> Build from the menu. Copy the resulting ObjFW.framework to /Library/Frameworks and you are done. -USING THE MAC OS X FRAMWORK IN XCODE +USING THE MAC OS X FRAMEWORK IN XCODE To use the Mac OS X framework in Xcode, you need to add the .framework to your project and add the following flags to "Other C Flags": -fconstant-string-class=OFConstantString -fno-constant-cfstrings Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(ObjFW, 0.4-dev, js@webkeks.org) +AC_INIT(ObjFW, 0.5.4, js@webkeks.org) AC_CONFIG_SRCDIR(src) AS_IF([test x"$host" = x"psp"], [ OBJCFLAGS="-G0 $OBJCFLAGS" LIBS="$LIBS -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc" @@ -27,11 +27,12 @@ AX_CHECK_COMPILER_FLAGS(-fno-common, [OBJCFLAGS="$OBJCFLAGS -fno-common"]) AX_CHECK_COMPILER_FLAGS(-fno-constant-cfstrings, [ NO_CONST_CFSTRINGS="-fno-constant-cfstrings" OBJCFLAGS="$OBJCFLAGS -fno-constant-cfstrings" ]) -AX_CHECK_COMPILER_FLAGS(-Wshorten-64-to-32, [OBJCFLAGS="$OBJCFLAGS -pipe"]) +AX_CHECK_COMPILER_FLAGS(-Wshorten-64-to-32, + [OBJCFLAGS="$OBJCFLAGS -Wshorten-64-to-32"]) AC_SUBST(NO_CONST_CFSTRINGS) AC_MSG_CHECKING(whether Objective C compiler supports fast enumeration) AC_TRY_COMPILE([ @protocol OFFastEnumeration @@ -96,11 +97,11 @@ AC_MSG_CHECKING(whether Objective C compiler supports blocks) old_OBJCFLAGS="$OBJCFLAGS" OBJCFLAGS="$OBJCFLAGS -fblocks" AC_TRY_COMPILE([], [ int (^foo)(int bar); - foo = ^(int bar) { return 0; } + foo = ^ (int bar) { return 0; } ], [ AC_DEFINE(OF_HAVE_BLOCKS, 1, [Compiler support for blocks]) AC_SUBST(BLOCKS_FLAGS, "-fblocks") AC_SUBST(OFBLOCKTESTS_M, "OFBlockTests.m") AC_MSG_RESULT(yes) @@ -111,10 +112,11 @@ AC_CHECK_HEADERS([objfw-rt.h objc/objc.h]) test x"$ac_cv_header_objfw_rt_h" = x"yes" && objc_runtime="ObjFW-RT" +AC_MSG_CHECKING(which Objective C runtime we use) AS_IF([test x"$ac_cv_header_objc_objc_h" = x"yes"], [ AC_EGREP_CPP(yes, [ #import #ifdef __GNU_LIBOBJC__ yes @@ -133,41 +135,60 @@ ], [ objc_runtime="Apple" ]) ]) ]) +AC_MSG_RESULT($objc_runtime) -AC_MSG_CHECKING(which Objective C runtime we use) case $objc_runtime in ObjFW-RT) AC_DEFINE(OF_OBJFW_RUNTIME, 1, [Whether we use the ObjFW runtime]) AC_SUBST(GNU_RUNTIME, "-fgnu-runtime") OBJCFLAGS="$OBJCFLAGS -fgnu-runtime" - LIBS="-lobjfw-rt $LIBS" + + AC_CHECK_LIB(objfw-rt, objc_msg_lookup, [ + LIBS="-lobjfw-rt $LIBS" + ], [ + AC_MSG_ERROR([libobjfw-rt not found!]) + ]) ;; Apple) AC_DEFINE(OF_APPLE_RUNTIME, 1, [Whether we use the Apple ObjC runtime]) - LIBS="-lobjc $LIBS" + + AC_CHECK_LIB(objc, objc_msgSend, [ + LIBS="-lobjc $LIBS" + ], [ + AC_MSG_ERROR([libobjc not found!]) + ]) ;; GNU) AC_DEFINE(OF_GNU_RUNTIME, 1, [Whether we use the GNU ObjC runtime]) - LIBS="-lobjc $LIBS" + + AC_CHECK_LIB(objc, objc_msg_lookup, [ + LIBS="-lobjc $LIBS" + ], [ + AC_MSG_ERROR([libobjc not found!]) + ]) ;; "old GNU") AC_DEFINE(OF_OLD_GNU_RUNTIME, 1, [Whether we use the old GNU ObjC runtime]) - LIBS="-lobjc $LIBS" + + AC_CHECK_LIB(objc, objc_msg_lookup, [ + LIBS="-lobjc $LIBS" + ], [ + AC_MSG_ERROR([libobjc not found!]) + ]) ;; *) AC_MSG_RESULT(none) AC_MSG_ERROR(No ObjC runtime found! Please install ObjFW-RT!) ;; esac -AC_MSG_RESULT($objc_runtime) AC_CHECK_FUNC(objc_getProperty,, [ AC_DEFINE(NEED_OBJC_PROPERTIES_INIT, 1, [Whether objc_properties_init needs to be called]) AC_SUBST(OBJC_PROPERTIES_M, "objc_properties.m") @@ -450,11 +471,20 @@ ;; esac AS_IF([test x"$have_threadsafe_getaddrinfo" = x"unknown"], [ AC_EGREP_CPP(yes, [ - #include + #ifndef _WIN32 + # include + # include + # include + #else + # define _WIN32_WINNT 0x0501 + # include + # include + #endif + #ifdef h_errno yes #end ], [ have_threadsafe_getaddrinfo="yes" @@ -483,12 +513,11 @@ AC_SUBST(FOUNDATION_COMPAT_M, "foundation-compat.m") ]) ]) AS_IF([test x"$GOBJC" = x"yes"], [ - OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wcast-align -Wpointer-arith" - OBJCFLAGS="$OBJCFLAGS -Werror" + OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror" AC_MSG_CHECKING(whether gcc has bug objc/27438) AC_TRY_COMPILE([ @interface OFConstantString { @@ -499,11 +528,11 @@ @end void *_OFConstantStringClassReference; ], [ OFConstantString *test = @""; - test++; /* Get rid of unused variable warning */ + (void)test; /* Get rid of unused variable warning */ ], [ AC_MSG_RESULT(no) ], [ AC_MSG_RESULT([yes, adding -Wno-unused-variable]) OBJCFLAGS="$OBJCFLAGS -Wno-unused-variable" @@ -510,28 +539,53 @@ AC_SUBST(NO_WARN_UNUSED, "-Wno-unused-variable") ]) AC_MSG_CHECKING(whether we need -Wno-strict-aliasing due to gcc bugs) AC_TRY_COMPILE([ - @interface OFObject + @interface Foo { - Class isa; + struct objc_class *isa; } @end static struct { struct objc_class *isa; } object; ], [ - OFObject *test = (OFObject*)&object; - test++; /* Get rid of unused variable warning */ + Foo *test = (Foo*)&object; + (void)test; /* Get rid of unused variable warning */ ], [ AC_MSG_RESULT(no) ], [ AC_MSG_RESULT(yes) OBJCFLAGS="$OBJCFLAGS -Wno-strict-aliasing" ]) + + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Wcast-align" + AC_MSG_CHECKING(whether -Wcast-align is buggy) + AC_TRY_COMPILE([ + @interface Foo + { + struct objc_class *isa; + } + @end + + @implementation Foo + - (void)foo + { + struct objc_class *c = isa; + (void)c; + } + @end + ], [ + ], [ + AC_MSG_RESULT(no) + ], [ + AC_MSG_RESULT(yes) + OBJCFLAGS="$old_OBJCFLAGS" + ]) ]) AS_IF([test x"$cross_compiling" = x"yes"], [ AC_SUBST(BIN_PREFIX, "$host-") Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,8 +1,8 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ -OBJFW_LIB_MAJOR = 3 +OBJFW_LIB_MAJOR = 4 OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} ASPRINTF_M = @ASPRINTF_M@ ATOMIC_H = @ATOMIC_H@ Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -17,25 +17,26 @@ #include "config.h" #define OF_APPLICATION_M #include +#include #import "OFApplication.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFAutoreleasePool.h" #import "OFNotImplementedException.h" -#include +#import "macros.h" -#ifdef __MACH__ +#if defined(__MACH__) && !defined(OF_IOS) # include -#else - extern char **environ; +#elif !defined(OF_IOS) +extern char **environ; #endif static OFApplication *app = nil; static void @@ -101,22 +102,24 @@ { self = [super init]; @try { OFAutoreleasePool *pool; - char **env; +#if defined(__MACH__) && !defined(OF_IOS) + char **env = *_NSGetEnviron(); +#elif !defined(OF_IOS) + char **env = environ; +#else + char *env; +#endif environment = [[OFMutableDictionary alloc] init]; atexit(atexit_handler); -#ifdef __MACH__ - env = *_NSGetEnviron(); -#else - env = environ; -#endif pool = [[OFAutoreleasePool alloc] init]; +#ifndef OF_IOS for (; *env != NULL; env++) { OFString *key; OFString *value; char *sep; @@ -132,10 +135,38 @@ [environment setObject: value forKey: key]; [pool releaseObjects]; } +#else + /* + * iOS does not provide environ and Apple does not allow using + * _NSGetEnviron on iOS. Therefore, we just get a few common + * variables from the environment which applications might + * expect. + */ + if ((env = getenv("HOME")) != NULL) + [environment + setObject: [OFString stringWithCString: env] + forKey: @"HOME"]; + if ((env = getenv("PATH")) != NULL) + [environment + setObject: [OFString stringWithCString: env] + forKey: @"PATH"]; + if ((env = getenv("SHELL")) != NULL) + [environment + setObject: [OFString stringWithCString: env] + forKey: @"SHELL"]; + if ((env = getenv("TMPDIR")) != NULL) + [environment + setObject: [OFString stringWithCString: env] + forKey: @"TMPDIR"]; + if ((env = getenv("USER")) != NULL) + [environment + setObject: [OFString stringWithCString: env] + forKey: @"USER"]; +#endif [pool release]; /* * Class swizzle the environment to be immutable, as we don't * need to change it anymore and expose it only as Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -113,10 +113,12 @@ @try { id obj; [array addItem: &first]; + [first retain]; + while ((obj = va_arg(args, id)) != nil) { [array addItem: &obj]; [obj retain]; } } @catch (id e) { @@ -394,13 +396,17 @@ return hash; } - (OFString*)description { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFAutoreleasePool *pool; OFMutableString *ret; + if ([array count] == 0) + return @"()"; + + pool = [[OFAutoreleasePool alloc] init]; ret = [[self componentsJoinedByString: @",\n"] mutableCopy]; @try { [ret prependString: @"(\n"]; [ret replaceOccurrencesOfString: @"\n" @@ -563,11 +569,11 @@ @end @implementation OFArrayEnumerator - initWithArray: (OFArray*)array_ dataArray: (OFDataArray*)dataArray_ - mutationsPointer: (unsigned long*)mutationsPtr_; + mutationsPointer: (unsigned long*)mutationsPtr_ { self = [super init]; array = [array_ retain]; dataArray = [dataArray_ retain]; Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -223,10 +223,12 @@ if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE) block->descriptor->dispose_helper(block); free(block); + + return; } assert(of_spinlock_unlock(&spinlocks[hash])); #endif } @@ -233,10 +235,16 @@ void _Block_object_assign(void *dst_, const void *src_, const int flags_) { int flags = flags_ & (OF_BLOCK_FIELD_IS_BLOCK | OF_BLOCK_FIELD_IS_OBJECT | OF_BLOCK_FIELD_IS_BYREF); + + if (src_ == NULL) + return; + + if (flags_ & OF_BLOCK_BYREF_CALLER) + return; switch (flags) { case OF_BLOCK_FIELD_IS_BLOCK: *(of_block_literal_t**)dst_ = _Block_copy(src_); break; @@ -245,20 +253,20 @@ break; case OF_BLOCK_FIELD_IS_BYREF:; of_block_byref_t *src = (of_block_byref_t*)src_; of_block_byref_t **dst = (of_block_byref_t**)dst_; - if ((src->flags & ~OF_BLOCK_HAS_COPY_DISPOSE) == 0) { + if ((src->flags & OF_BLOCK_REFCOUNT_MASK) == 0) { if ((*dst = malloc(src->size)) == NULL) { alloc_failed_exception.isa = [OFAllocFailedException class]; @throw (OFAllocFailedException*) &alloc_failed_exception; } if (src->forwarding == src) - src->forwarding = *dst; + (*dst)->forwarding = *dst; memcpy(*dst, src, src->size); if (src->size >= sizeof(of_block_byref_t)) src->byref_keep(*dst, src); @@ -273,10 +281,16 @@ void _Block_object_dispose(const void *obj_, const int flags_) { const int flags = flags_ & (OF_BLOCK_FIELD_IS_BLOCK | OF_BLOCK_FIELD_IS_OBJECT | OF_BLOCK_FIELD_IS_BYREF); + + if (obj_ == NULL) + return; + + if (flags_ & OF_BLOCK_BYREF_CALLER) + return; switch (flags) { case OF_BLOCK_FIELD_IS_BLOCK: _Block_release(obj_); break; @@ -284,11 +298,11 @@ [(id)obj_ release]; break; case OF_BLOCK_FIELD_IS_BYREF:; of_block_byref_t *obj = (of_block_byref_t*)obj_; - if ((--obj->flags & ~OF_BLOCK_HAS_COPY_DISPOSE) == 0) { + if ((--obj->flags & OF_BLOCK_REFCOUNT_MASK) == 0) { if (obj->size >= sizeof(of_block_byref_t)) obj->byref_dispose(obj); free(obj); } @@ -422,11 +436,12 @@ return OF_RETAIN_COUNT_MAX; } - (void)release { - Block_release(self); + if (isa == (Class)&_NSConcreteMallocBlock) + Block_release(self); } - (void)dealloc { @throw [OFNotImplementedException newWithClass: isa Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -52,11 +52,11 @@ @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - initWithCString: (const char*)str - encoding: (of_string_encoding_t)encoding; + encoding: (of_string_encoding_t)encoding { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -30,10 +30,12 @@ #endif #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" + +#import "macros.h" #if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \ defined(OF_THREADS) static OFMutex *mutex; #endif @@ -245,10 +247,35 @@ if (((OFDate*)obj)->sec != sec || ((OFDate*)obj)->usec != usec) return NO; return YES; } + +- (uint32_t)hash +{ + uint32_t hash; + + OF_HASH_INIT(hash); + + OF_HASH_ADD(hash, (sec >> 56) & 0xFF); + OF_HASH_ADD(hash, (sec >> 48) & 0xFF); + OF_HASH_ADD(hash, (sec >> 40) & 0xFF); + OF_HASH_ADD(hash, (sec >> 32) & 0xFF); + OF_HASH_ADD(hash, (sec >> 24) & 0xFF); + OF_HASH_ADD(hash, (sec >> 16) & 0xFF); + OF_HASH_ADD(hash, (sec >> 8) & 0xFF); + OF_HASH_ADD(hash, sec & 0xFF); + + OF_HASH_ADD(hash, (usec >> 24) & 0xFF); + OF_HASH_ADD(hash, (usec >> 16) & 0xFF); + OF_HASH_ADD(hash, (usec >> 8) & 0xFF); + OF_HASH_ADD(hash, usec & 0xFF); + + OF_HASH_FINALIZE(hash); + + return hash; +} - copy { return [self retain]; } Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -34,11 +34,11 @@ #define BUCKET struct of_dictionary_bucket #define DELETED &of_dictionary_deleted_bucket @implementation OFDictionary -+ dictionary; ++ dictionary { return [[[self alloc] init] autorelease]; } + dictionaryWithDictionary: (OFDictionary*)dict @@ -146,10 +146,14 @@ self = [super init]; @try { uint32_t i; BUCKET *b; + + if (key == nil || obj == nil) + @throw [OFInvalidArgumentException newWithClass: isa + selector: _cmd]; data = [self allocMemoryForNItems: 2 withSize: sizeof(BUCKET*)]; size = 2; @@ -453,10 +457,11 @@ [obj release]; @throw e; } data[j]->object = obj; + count--; } } @catch (id e) { [self release]; @throw e; } @@ -703,23 +708,33 @@ return hash; } - (OFString*)description { - OFMutableString *ret = [OFMutableString stringWithString: @"{\n"]; - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init], *pool2; - OFEnumerator *enumerator = [self keyEnumerator]; - id key; + OFMutableString *ret; + OFAutoreleasePool *pool, *pool2; + OFEnumerator *keyEnumerator; + OFEnumerator *objectEnumerator; + id key, object; size_t i; + if (count == 0) + return @"{}"; + + ret = [OFMutableString stringWithString: @"{\n"]; + pool = [[OFAutoreleasePool alloc] init]; + keyEnumerator = [self keyEnumerator]; + objectEnumerator = [self objectEnumerator]; + i = 0; pool2 = [[OFAutoreleasePool alloc] init]; - while ((key = [enumerator nextObject]) != nil) { + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { [ret appendString: [key description]]; [ret appendString: @" = "]; - [ret appendString: [[self objectForKey: key] description]]; + [ret appendString: [object description]]; if (++i < count) [ret appendString: @";\n"]; [pool2 releaseObjects]; Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -14,13 +14,17 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #include +#include #include #include + #include #include #include #include Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -21,10 +21,11 @@ #import "OFHTTPRequest.h" #import "OFString.h" #import "OFURL.h" #import "OFTCPSocket.h" #import "OFDictionary.h" +#import "OFDataArray.h" #import "OFAutoreleasePool.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidServerReplyException.h" #import "OFOutOfRangeException.h" @@ -165,11 +166,11 @@ OFMutableDictionary *s_headers; OFDataArray *data; OFEnumerator *enumerator; OFString *key; int status; - const char *t; + const char *t = NULL; [sock connectToHost: [URL host] onPort: [URL port]]; /* Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -50,16 +50,16 @@ [iter->object release]; [super dealloc]; } -- (of_list_object_t*)firstListObject; +- (of_list_object_t*)firstListObject { return firstListObject; } -- (of_list_object_t*)lastListObject; +- (of_list_object_t*)lastListObject { return lastListObject; } - (of_list_object_t*)appendObject: (id)obj @@ -79,12 +79,10 @@ firstListObject = o; count++; mutations++; - [obj retain]; - return o; } - (of_list_object_t*)prependObject: (id)obj { @@ -103,12 +101,10 @@ lastListObject = o; count++; mutations++; - [obj retain]; - return o; } - (of_list_object_t*)insertObject: (id)obj beforeListObject: (of_list_object_t*)listobj @@ -129,12 +125,10 @@ firstListObject = o; count++; mutations++; - [obj retain]; - return o; } - (of_list_object_t*)insertObject: (id)obj afterListObject: (of_list_object_t*)listobj @@ -155,12 +149,10 @@ lastListObject = o; count++; mutations++; - [obj retain]; - return o; } - (void)removeListObject: (of_list_object_t*)listobj { @@ -257,12 +249,10 @@ if (prev != NULL) prev->next = o; new->count++; - [o->object retain]; - prev = o; } } @catch (id e) { [new release]; @throw e; @@ -294,14 +284,18 @@ return hash; } - (OFString*)description { - OFMutableString *ret = [OFMutableString stringWithString: @"[\n"]; + OFMutableString *ret; OFAutoreleasePool *pool; of_list_object_t *iter; + if (count == 0) + return @"[]"; + + ret = [OFMutableString stringWithString: @"[\n"]; pool = [[OFAutoreleasePool alloc] init]; for (iter = firstListObject; iter != NULL; iter = iter->next) { [ret appendString: [iter->object description]]; @@ -356,11 +350,11 @@ } @end @implementation OFListEnumerator - initWithList: (OFList*)list_ - mutationsPointer: (unsigned long*)mutationsPtr_; + mutationsPointer: (unsigned long*)mutationsPtr_ { self = [super init]; list = [list_ retain]; current = [list firstListObject]; Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -63,15 +63,14 @@ return; } ulen = [self length]; - ustr = [self allocMemoryForNItems: [self length] - withSize: ulen]; + ustr = [self allocMemoryForNItems: ulen + withSize: sizeof(of_unichar_t)]; - i = 0; - j = 0; + i = j = 0; nlen = 0; while (i < length) { clen = of_string_utf8_to_unicode(string + i, length - i, &c); @@ -136,10 +135,15 @@ size_t len; [self freeMemory: string]; len = strlen(str); + + if (len >= 3 && !memcmp(str, "\xEF\xBB\xBF", 3)) { + str += 3; + len -= 3; + } switch (of_string_check_utf8(str, len)) { case 0: isUTF8 = NO; break; @@ -162,10 +166,15 @@ - (void)appendCString: (const char*)str { size_t strlength; strlength = strlen(str); + + if (strlength >= 3 && !memcmp(str, "\xEF\xBB\xBF", 3)) { + str += 3; + strlength -= 3; + } switch (of_string_check_utf8(str, strlength)) { case 1: isUTF8 = YES; break; @@ -180,10 +189,15 @@ } - (void)appendCString: (const char*)str withLength: (size_t)len { + if (len >= 3 && !memcmp(str, "\xEF\xBB\xBF", 3)) { + str += 3; + len -= 3; + } + switch (of_string_check_utf8(str, len)) { case 1: isUTF8 = YES; break; case -1: @@ -266,21 +280,21 @@ - (void)reverse { size_t i, j, len = length / 2; - madvise(string, len, MADV_SEQUENTIAL); + madvise(string, 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]; } if (!isUTF8) { - madvise(string, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); return; } for (i = 0; i < length; i++) { /* ASCII */ @@ -287,17 +301,17 @@ if (OF_LIKELY(!(string[i] & 0x80))) continue; /* A start byte can't happen first as we reversed everything */ if (OF_UNLIKELY(string[i] & 0x40)) { - madvise(string, len, MADV_NORMAL); + madvise(string, 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, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Next byte is the start byte */ if (OF_LIKELY(string[i + 1] & 0x40)) { @@ -309,11 +323,11 @@ continue; } /* Second next byte must not be ASCII */ if (OF_UNLIKELY(length < i + 2 || !(string[i + 2] & 0x80))) { - madvise(string, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Second next byte is the start byte */ if (OF_LIKELY(string[i + 2] & 0x40)) { @@ -325,11 +339,11 @@ continue; } /* Third next byte must not be ASCII */ if (OF_UNLIKELY(length < i + 3 || !(string[i + 3] & 0x80))) { - madvise(string, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } /* Third next byte is the start byte */ if (OF_LIKELY(string[i + 3] & 0x40)) { @@ -344,15 +358,15 @@ i += 3; continue; } /* UTF-8 does not allow more than 4 bytes per character */ - madvise(string, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); @throw [OFInvalidEncodingException newWithClass: isa]; } - madvise(string, len, MADV_NORMAL); + madvise(string, length, MADV_NORMAL); } - (void)upper { [self _applyTable: of_unicode_upper_table Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -12,11 +12,11 @@ * 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 +#include #import "OFObject.h" /** * \brief The type of a number. Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -14,14 +14,18 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #include #include #include + #include + #include #import "OFObject.h" #import "OFAutoreleasePool.h" @@ -39,10 +43,11 @@ #if defined(OF_OBJFW_RUNTIME) # import #elif defined(OF_OLD_GNU_RUNTIME) # import # import +# import #else # import #endif #ifdef _WIN32 @@ -249,11 +254,11 @@ size_t i; for (c = self; c != Nil; c = class_get_super_class(c)) for (pl = c->protocols; pl != NULL; pl = pl->next) for (i = 0; i < pl->count; i++) - if ([pl->list[i] conformsToProtocol: protocol]) + if ([pl->list[i] conformsTo: protocol]) return YES; return NO; #else Class c; @@ -362,11 +367,11 @@ method_getTypeEncoding(method)); #endif } + (IMP)replaceClassMethod: (SEL)selector - withMethodFromClass: (Class)class; + withMethodFromClass: (Class)class { IMP newimp; if (![class isSubclassOfClass: self]) @throw [OFInvalidArgumentException newWithClass: self @@ -420,11 +425,11 @@ method_getTypeEncoding(method)); #endif } + (IMP)replaceInstanceMethod: (SEL)selector - withMethodFromClass: (Class)class; + withMethodFromClass: (Class)class { IMP newimp; if (![class isSubclassOfClass: self]) @throw [OFInvalidArgumentException newWithClass: self @@ -678,11 +683,11 @@ return [self resizeMemory: ptr toSize: nitems * size]; } -- (void)freeMemory: (void*)ptr; +- (void)freeMemory: (void*)ptr { void **iter, *last, **memchunks; size_t i, memchunks_size; if (ptr == NULL) Index: src/OFSeekableStream.h ================================================================== --- src/OFSeekableStream.h +++ src/OFSeekableStream.h @@ -12,14 +12,11 @@ * 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. */ -/* Required to prevent a name conflict in glibc when using -fblocks */ -#undef __USE_XOPEN - -#include +#include #import "OFStream.h" /** * \brief A stream that supports seeking. Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -14,16 +14,19 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #include #include #include #include #include + #include #ifndef _WIN32 # include #endif Index: src/OFStreamObserver.m ================================================================== --- src/OFStreamObserver.m +++ src/OFStreamObserver.m @@ -15,10 +15,11 @@ */ #include "config.h" #define OF_STREAM_OBSERVER_M +#define __NO_EXT_QNX #include #include @@ -39,10 +40,12 @@ #endif #import "OFAutoreleasePool.h" #import "OFInitializationFailedException.h" #import "OFOutOfRangeException.h" + +#import "macros.h" #ifdef _WIN32 # define close(sock) closesocket(sock) #endif @@ -153,18 +156,16 @@ [super dealloc]; } - (id )delegate { - return [[(id)delegate retain] autorelease]; + OF_GETTER(delegate, YES) } - (void)setDelegate: (id )delegate_ { - [(id)delegate_ retain]; - [(id)delegate release]; - delegate = delegate_; + OF_SETTER(delegate, delegate_, YES, NO) } #ifdef OF_HAVE_POLL - (void)_addStream: (OFStream*)stream withEvents: (short)events @@ -487,10 +488,13 @@ readfds_ = readfds; writefds_ = writefds; exceptfds_ = exceptfds; # endif + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + if (select(nfds, &readfds_, &writefds_, &exceptfds_, (timeout != -1 ? &tv : NULL)) < 1) return NO; if (FD_ISSET(cancelFd[0], &readfds_)) { Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -14,12 +14,16 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #include + #include + #include #ifndef _WIN32 # include # include Index: src/OFString+XMLEscaping.m ================================================================== --- src/OFString+XMLEscaping.m +++ src/OFString+XMLEscaping.m @@ -65,10 +65,14 @@ break; case '&': append = "&"; append_len = 5; break; + case '\r': + append = " "; + append_len = 5; + break; default: append = NULL; append_len = 0; } Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -415,11 +415,11 @@ /** * Splits an OFString into an OFArray of OFStrings. * * \param delimiter The delimiter for splitting - * \return An autoreleased OFArray with the splitted string + * \return An autoreleased OFArray with the split string */ - (OFArray*)componentsSeparatedByString: (OFString*)delimiter; /** * \return The components of the path Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -33,10 +33,11 @@ #import "OFString.h" #import "OFArray.h" #import "OFFile.h" #import "OFURL.h" #import "OFHTTPRequest.h" +#import "OFDataArray.h" #import "OFAutoreleasePool.h" #import "OFHTTPRequestFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" @@ -97,11 +98,11 @@ madvise((void*)str, len, MADV_NORMAL); return -1; } /* We have at minimum a 2 byte character -> check next byte */ - if (OF_UNLIKELY(len < i + 1 || (str[i + 1] & 0xC0) != 0x80)) { + if (OF_UNLIKELY(len <= i + 1 || (str[i + 1] & 0xC0) != 0x80)) { madvise((void*)str, len, MADV_NORMAL); return -1; } /* Check if we have at minimum a 3 byte character */ @@ -109,11 +110,11 @@ i++; continue; } /* We have at minimum a 3 byte char -> check second next byte */ - if (OF_UNLIKELY(len < i + 2 || (str[i + 2] & 0xC0) != 0x80)) { + if (OF_UNLIKELY(len <= i + 2 || (str[i + 2] & 0xC0) != 0x80)) { madvise((void*)str, len, MADV_NORMAL); return -1; } /* Check if we have a 4 byte character */ @@ -121,11 +122,11 @@ i += 2; continue; } /* We have a 4 byte character -> check third next byte */ - if (OF_UNLIKELY(len < i + 3 || (str[i + 3] & 0xC0) != 0x80)) { + if (OF_UNLIKELY(len <= i + 3 || (str[i + 3] & 0xC0) != 0x80)) { madvise((void*)str, len, MADV_NORMAL); return -1; } /* @@ -664,17 +665,20 @@ if (stat([path cString], &s) == -1) @throw [OFOpenFileFailedException newWithClass: isa path: path mode: @"rb"]; + if (s.st_size > SIZE_MAX) + @throw [OFOutOfRangeException newWithClass: isa]; + file = [[OFFile alloc] initWithPath: path mode: @"rb"]; @try { - tmp = [self allocMemoryWithSize: s.st_size]; + tmp = [self allocMemoryWithSize: (size_t)s.st_size]; - [file readExactlyNBytes: s.st_size + [file readExactlyNBytes: (size_t)s.st_size intoBuffer: tmp]; } @finally { [file release]; } } @catch (id e) { @@ -682,11 +686,11 @@ @throw e; } self = [self initWithCString: tmp encoding: encoding - length: s.st_size]; + length: (size_t)s.st_size]; [self freeMemory: tmp]; return self; } @@ -1208,11 +1212,11 @@ return [OFString stringWithCString: string + i length: path_len - i]; } -- (OFString*)stringByDeletingLastPathComponent; +- (OFString*)stringByDeletingLastPathComponent { size_t i, path_len = length; if (path_len == 0) return @""; @@ -1415,11 +1419,11 @@ while (i < length) { of_unichar_t c; size_t clen; - clen = of_string_utf8_to_unicode(string + i, length - 1, &c); + clen = of_string_utf8_to_unicode(string + i, length - i, &c); if (clen == 0 || c > 0x10FFFF) { free(ret); @throw [OFInvalidEncodingException newWithClass: isa]; } Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -34,13 +34,13 @@ * To connect to a server, create a socket and connect it. * To create a server, create a socket, bind it and listen on it. */ @interface OFTCPSocket: OFStreamSocket { - BOOL isListening; - struct sockaddr *sockAddr; - socklen_t sockAddrLen; + BOOL isListening; + struct sockaddr_storage *sockAddr; + socklen_t sockAddrLen; } /** * Connect the OFTCPSocket to the specified destination. * Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -14,13 +14,16 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #include #include #include + #include #include #ifndef _WIN32 @@ -346,11 +349,11 @@ } - (OFTCPSocket*)accept { OFTCPSocket *newsock; - struct sockaddr *addr; + struct sockaddr_storage *addr; socklen_t addrlen; int s; newsock = [[[isa alloc] init] autorelease]; addrlen = sizeof(struct sockaddr); @@ -360,11 +363,12 @@ } @catch (id e) { [newsock release]; @throw e; } - if ((s = accept(sock, addr, &addrlen)) == INVALID_SOCKET) { + if ((s = accept(sock, (struct sockaddr*)addr, + &addrlen)) == INVALID_SOCKET) { [newsock release]; @throw [OFAcceptFailedException newWithClass: isa socket: self]; } @@ -392,12 +396,12 @@ #ifdef HAVE_THREADSAFE_GETADDRINFO char *host = [self allocMemoryWithSize: NI_MAXHOST]; @try { - if (getnameinfo(sockAddr, sockAddrLen, host, NI_MAXHOST, NULL, - 0, NI_NUMERICHOST)) + if (getnameinfo((struct sockaddr*)sockAddr, sockAddrLen, host, + NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) @throw [OFAddressTranslationFailedException newWithClass: isa]; return [OFString stringWithCString: host]; } @finally { Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -86,11 +86,11 @@ * \return A new, autoreleased thread */ + thread; /** - * \param obj An object that is passed to the main method as a copy or nil + * \param obj An object which is passed for use in the main method or nil * \return A new, autoreleased thread */ + threadWithObject: (id)obj; /** @@ -159,11 +159,11 @@ * \param obj The object which the terminated thread will return */ + (void)terminateWithObject: (id)obj; /** - * \param obj An object that is passed to the main method as a copy or nil + * \param obj An object which is passed for use in the main method or nil * \return An initialized OFThread. */ - initWithObject: (id)obj; /** Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -14,16 +14,22 @@ * file. */ #include "config.h" +#define __NO_EXT_QNX + #ifndef _WIN32 # include # include #else # include #endif + +#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME) +# import +#endif #import "OFThread.h" #import "OFList.h" #import "OFDate.h" #import "OFAutoreleasePool.h" @@ -49,10 +55,14 @@ static of_tlskey_t thread_self; static id call_main(id obj) { +#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME) + objc_thread_add(); +#endif + if (!of_tlskey_set(thread_self, obj)) @throw [OFInitializationFailedException newWithClass: [obj class]]; /* @@ -67,10 +77,14 @@ [OFTLSKey callAllDestructors]; [OFAutoreleasePool releaseAll]; [obj release]; + +#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME) + objc_thread_remove(); +#endif return 0; } @implementation OFThread @@ -206,10 +220,14 @@ [OFTLSKey callAllDestructors]; [OFAutoreleasePool releaseAll]; [thread release]; + +#if defined(OF_GNU_RUNTIME) || defined(OF_OLD_GNU_RUNTIME) + objc_thread_remove(); +#endif of_thread_exit(); } - initWithObject: (id)obj @@ -241,10 +259,15 @@ - (void)start { if (running == OF_THREAD_RUNNING) @throw [OFThreadStillRunningException newWithClass: isa thread: self]; + + if (running == OF_THREAD_WAITING_FOR_JOIN) { + of_thread_detach(thread); + [retval release]; + } [self retain]; if (!of_thread_new(&thread, call_main, self)) { [self release]; @@ -270,10 +293,17 @@ { if (running == OF_THREAD_RUNNING) @throw [OFThreadStillRunningException newWithClass: isa thread: self]; + /* + * We should not be running anymore, but call detach in order to free + * the resources. + */ + if (running == OF_THREAD_WAITING_FOR_JOIN) + of_thread_detach(thread); + [object release]; [retval release]; [super dealloc]; } Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -159,11 +159,11 @@ tmp2++; host = [[OFString alloc] initWithCString: str_c]; pool = [[OFAutoreleasePool alloc] init]; - port_str = [[OFString alloc] initWithCString: tmp2]; + port_str = [OFString stringWithCString: tmp2]; if ([port_str decimalValue] > 65535) @throw [OFInvalidFormatException newWithClass: isa]; @@ -316,21 +316,22 @@ return NO; if (![url->host isEqual: host]) return NO; if (url->port != port) return NO; - if (![url->user isEqual: user]) + if (url->user != user && ![url->user isEqual: user]) return NO; - if (![url->password isEqual: password]) + if (url->password != password && ![url->password isEqual: password]) return NO; if (![url->path isEqual: path]) return NO; - if (![url->parameters isEqual: parameters]) + if (url->parameters != parameters && + ![url->parameters isEqual: parameters]) return NO; - if (![url->query isEqual: query]) + if (url->query != query && ![url->query isEqual: query]) return NO; - if (![url->fragment isEqual: fragment]) + if (url->fragment != fragment && ![url->fragment isEqual: fragment]) return NO; return YES; } @@ -360,19 +361,24 @@ - copy { OFURL *new = [[OFURL alloc] init]; - new->scheme = [scheme copy]; - new->host = [host copy]; - new->port = port; - new->user = [user copy]; - new->password = [password copy]; - new->path = [path copy]; - new->parameters = [parameters copy]; - new->query = [query copy]; - new->fragment = [fragment copy]; + @try { + new->scheme = [scheme copy]; + new->host = [host copy]; + new->port = port; + new->user = [user copy]; + new->password = [password copy]; + new->path = [path copy]; + new->parameters = [parameters copy]; + new->query = [query copy]; + new->fragment = [fragment copy]; + } @catch (id e) { + [new release]; + @throw e; + } return new; } - (OFString*)scheme Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -17,10 +17,12 @@ #include "config.h" #import "OFXMLAttribute.h" #import "OFString.h" #import "OFAutoreleasePool.h" + +#import "macros.h" @implementation OFXMLAttribute + attributeWithName: (OFString*)name namespace: (OFString*)ns stringValue: (OFString*)value @@ -69,6 +71,60 @@ - (OFString*)stringValue { return [[stringValue copy] autorelease]; } + +- (BOOL)isEqual: (id)object +{ + OFXMLAttribute *other; + + if (![object isKindOfClass: [OFXMLAttribute class]]) + return NO; + + other = object; + + if (![other->name isEqual: name]) + return NO; + if (other->ns != ns && ![other->ns isEqual: ns]) + return NO; + if (![other->stringValue isEqual: stringValue]) + return NO; + + return YES; +} + +- (uint32_t)hash +{ + uint32_t hash, tmp; + + OF_HASH_INIT(hash); + + tmp = [name hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [name hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [ns hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [stringValue hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + OF_HASH_FINALIZE(hash); + + return hash; +} @end Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -13,17 +13,17 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" +#import "OFXMLAttribute.h" @class OFString; @class OFArray; @class OFMutableString; @class OFMutableArray; @class OFMutableDictionary; -@class OFXMLAttribute; /** * \brief A class which stores an XML element. */ @interface OFXMLElement: OFObject @@ -325,11 +325,11 @@ */ - (void)bindPrefix: (OFString*)prefix forNamespace: (OFString*)ns; /** - * Sets the default namespace for the element. + * Sets the default namespace for the element to be used if there is no parent. * * \param ns The default namespace for the element */ - (void)setDefaultNamespace: (OFString*)ns; Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -30,10 +30,12 @@ #import "OFInvalidArgumentException.h" #import "OFMalformedXMLException.h" #import "OFNotImplementedException.h" #import "OFUnboundNamespaceException.h" + +#import "macros.h" @interface OFXMLElement_OFXMLElementBuilderDelegate: OFObject { @public OFXMLElement *element; @@ -42,11 +44,18 @@ @implementation OFXMLElement_OFXMLElementBuilderDelegate - (void)elementBuilder: (OFXMLElementBuilder*)builder didBuildElement: (OFXMLElement*)elem { - element = [elem retain]; + /* + * Make sure we don't take whitespaces before or after the root element + * into account. + */ + if ([elem name] != nil) { + assert(element == nil); + element = [elem retain]; + } } - (void)dealloc { [element release]; @@ -212,11 +221,13 @@ { OFAutoreleasePool *pool; OFXMLParser *parser; OFXMLElementBuilder *builder; OFXMLElement_OFXMLElementBuilderDelegate *delegate; + Class c; + c = isa; [self release]; pool = [[OFAutoreleasePool alloc] init]; parser = [OFXMLParser parser]; @@ -228,11 +239,11 @@ [builder setDelegate: delegate]; [parser parseString: str]; if (![parser finishedParsing]) - @throw [OFMalformedXMLException newWithClass: isa + @throw [OFMalformedXMLException newWithClass: c parser: parser]; self = [delegate->element retain]; @try { @@ -324,18 +335,18 @@ ret->isa = [OFString class]; return ret; } - (OFString*)_XMLStringWithParent: (OFXMLElement*)parent + namespaces: (OFDictionary*)all_namespaces { OFAutoreleasePool *pool, *pool2; char *str_c; size_t len, i, j, attrs_count; OFString *prefix, *parent_prefix; OFXMLAttribute **attrs_carray; OFString *ret, *tmp; - OFMutableDictionary *all_namespaces; OFString *def_ns; if (characters != nil) return [characters stringByXMLEscaping]; @@ -358,43 +369,49 @@ str->isa = [OFString class]; return str; } pool = [[OFAutoreleasePool alloc] init]; - def_ns = (defaultNamespace != nil - ? defaultNamespace - : (parent != nil ? parent->defaultNamespace : (OFString*)nil)); - if (parent != nil && parent->namespaces != nil) { + parent_prefix = [all_namespaces objectForKey: + (parent != nil && parent->ns != nil ? parent->ns : (OFString*)@"")]; + + if (all_namespaces != nil) { OFEnumerator *key_enum = [namespaces keyEnumerator]; OFEnumerator *obj_enum = [namespaces objectEnumerator]; + OFMutableDictionary *mutable; id key, obj; - all_namespaces = [[parent->namespaces mutableCopy] autorelease]; + mutable = [[all_namespaces mutableCopy] autorelease]; while ((key = [key_enum nextObject]) != nil && (obj = [obj_enum nextObject]) != nil) - [all_namespaces setObject: obj - forKey: key]; + [mutable setObject: obj + forKey: key]; + + all_namespaces = mutable; } else all_namespaces = namespaces; prefix = [all_namespaces objectForKey: (ns != nil ? ns : (OFString*)@"")]; - parent_prefix = [all_namespaces objectForKey: - (parent != nil && parent->ns != nil ? parent->ns : (OFString*)@"")]; + + if (parent != nil && parent->ns != nil && parent_prefix == nil) + def_ns = parent->ns; + else if (parent != nil && parent->defaultNamespace != nil) + def_ns = parent->defaultNamespace; + else + def_ns = defaultNamespace; i = 0; len = [name cStringLength] + 3; str_c = [self allocMemoryWithSize: len]; /* Start of tag */ str_c[i++] = '<'; - if (prefix != nil && ![ns isEqual: def_ns] && - (![ns isEqual: (parent != nil ? parent->ns : (OFString*)nil)] || - parent_prefix != nil)) { + if (prefix != nil && ![ns isEqual: def_ns]) { len += [prefix cStringLength] + 1; @try { str_c = [self resizeMemory: str_c toSize: len]; } @catch (id e) { @@ -410,13 +427,12 @@ memcpy(str_c + i, [name cString], [name cStringLength]); i += [name cStringLength]; /* xmlns if necessary */ - if (ns != nil && prefix == nil && ![ns isEqual: def_ns] && - (![ns isEqual: (parent != nil ? parent->ns : (OFString*)nil)] || - parent_prefix != nil)) { + if (prefix == nil && ((ns != nil && ![ns isEqual: def_ns]) || + (ns == nil && def_ns != nil))) { len += [ns cStringLength] + 9; @try { str_c = [self resizeMemory: str_c toSize: len]; @@ -428,12 +444,10 @@ memcpy(str_c + i, " xmlns='", 8); i += 8; memcpy(str_c + i, [ns cString], [ns cStringLength]); i += [ns cStringLength]; str_c[i++] = '\''; - - def_ns = ns; } /* Attributes */ attrs_carray = [attributes cArray]; attrs_count = [attributes count]; @@ -494,11 +508,12 @@ for (j = 0; j < children_count; j++) append(tmp, @selector( appendCStringWithoutUTF8Checking:), [[children_carray[j] - _XMLStringWithParent: self] cString]); + _XMLStringWithParent: self + namespaces: all_namespaces] cString]); len += [tmp cStringLength] + [name cStringLength] + 2; @try { str_c = [self resizeMemory: str_c toSize: len]; @@ -546,11 +561,12 @@ return ret; } - (OFString*)XMLString { - return [self _XMLStringWithParent: nil]; + return [self _XMLStringWithParent: nil + namespaces: nil]; } - (OFString*)description { return [self XMLString]; @@ -748,15 +764,116 @@ [ret addObject: children_c[i]]; } return ret; } + +- (BOOL)isEqual: (id)object +{ + OFXMLElement *other; + + if (![object isKindOfClass: [OFXMLElement class]]) + return NO; + + other = object; + + if (other->name != name && ![other->name isEqual: name]) + return NO; + if (other->ns != ns && ![other->ns isEqual: ns]) + return NO; + if (other->defaultNamespace != defaultNamespace && + ![other->defaultNamespace isEqual: defaultNamespace]) + return NO; + if (other->attributes != attributes && + ![other->attributes isEqual: attributes]) + return NO; + if (other->namespaces != namespaces && + ![other->namespaces isEqual: namespaces]) + return NO; + if (other->children != children && ![other->children isEqual: children]) + return NO; + if (other->characters != characters && + ![other->characters isEqual: characters]) + return NO; + if (other->cdata != cdata && ![other->cdata isEqual: cdata]) + return NO; + if (other->comment != comment && ![other->comment isEqual: comment]) + return NO; + + return YES; +} + +- (uint32_t)hash +{ + uint32_t hash, tmp; + + OF_HASH_INIT(hash); + + tmp = [name hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [ns hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [defaultNamespace hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [attributes hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [namespaces hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [children hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [characters hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [cdata hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + tmp = [comment hash]; + OF_HASH_ADD(hash, (tmp >> 24) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 16) & 0xFF); + OF_HASH_ADD(hash, (tmp >> 8) & 0xFF); + OF_HASH_ADD(hash, tmp & 0xFF); + + OF_HASH_FINALIZE(hash); + + return hash; +} - (void)dealloc { [name release]; [ns release]; + [defaultNamespace release]; [attributes release]; [namespaces release]; [children release]; [characters release]; [cdata release]; Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -177,10 +177,11 @@ of_xml_parser_string_block_t CDATAHandler; of_xml_parser_string_block_t commentHandler; of_xml_parser_unknown_entity_block_t unknownEntityHandler; #endif size_t level; + BOOL acceptProlog; size_t lineNumber; BOOL lastCarriageReturn; BOOL finishedParsing; } Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -17,11 +17,12 @@ #include "config.h" #define OF_XML_PARSER_M #include -#include + +#include #import "OFXMLParser.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" @@ -49,11 +50,11 @@ [cache replaceOccurrencesOfString: @"\r" withString: @"\n"]; return [cache stringByXMLUnescapingWithDelegate: delegate]; } -static OF_INLINE OFString* +static OFString* namespace_for_prefix(OFString *prefix, OFArray *namespaces) { OFDictionary **carray = [namespaces cArray]; ssize_t i; @@ -155,10 +156,11 @@ dict = [OFMutableDictionary dictionaryWithKeysAndObjects: @"xml", @"http://www.w3.org/XML/1998/namespace", @"xmlns", @"http://www.w3.org/2000/xmlns/", nil]; [namespaces addObject: dict]; + acceptProlog = YES; lineNumber = 1; [pool release]; } @catch (id e) { [self release]; @@ -265,11 +267,11 @@ } } /* * The following methods handle the different states of the parser. They are - * lookup up in +[initialize] and put in a lookup table to speed things up. + * looked up in +[initialize] and put in a lookup table to speed things up. * One dispatch for every character would be way too slow! */ /* Not in a tag */ - (void)_parseOutsideTagWithBuffer: (const char*)buf @@ -276,12 +278,13 @@ i: (size_t*)i last: (size_t*)last { size_t len; - if (finishedParsing && buf[*i] != ' ' && buf[*i] != '\t' && - buf[*i] != '\n' && buf[*i] != '\r' && buf[*i] != '<') + if ((finishedParsing || [previous count] < 1) && buf[*i] != ' ' && + buf[*i] != '\t' && buf[*i] != '\n' && buf[*i] != '\r' && + buf[*i] != '<') @throw [OFMalformedXMLException newWithClass: isa parser: self]; if (buf[*i] != '<') return; @@ -317,11 +320,11 @@ /* Tag was just opened */ - (void)_parseTagOpenedWithBuffer: (const char*)buf i: (size_t*)i last: (size_t*)last { - if (finishedParsing && buf[*i] != '!') + if (finishedParsing && buf[*i] != '!' && buf[*i] != '?') @throw [OFMalformedXMLException newWithClass: isa parser: self]; switch (buf[*i]) { case '?': @@ -330,23 +333,108 @@ level = 0; break; case '/': *last = *i + 1; state = OF_XMLPARSER_IN_CLOSE_TAG_NAME; + acceptProlog = NO; break; case '!': *last = *i + 1; state = OF_XMLPARSER_IN_EXCLAMATIONMARK; + acceptProlog = NO; break; default: state = OF_XMLPARSER_IN_TAG_NAME; + acceptProlog = NO; (*i)--; break; } } -/* Inside prolog */ +/* */ +- (BOOL)_parseXMLProcessingInstructions: (OFString*)pi +{ + const char *pi_c; + size_t i, last, pi_len; + int xstate = 0; + OFString *attr = nil; + OFString *val = nil; + char xdelim = 0; + + if (!acceptProlog) + return NO; + + acceptProlog = NO; + + pi = [pi substringFromIndex: 3 + toIndex: [pi length]]; + pi = [pi stringByDeletingLeadingAndTrailingWhitespaces]; + + pi_c = [pi cString]; + pi_len = [pi cStringLength]; + + for (i = last = 0; i < pi_len; i++) { + switch (xstate) { + case 0: + if (pi_c[i] == ' ' || pi_c[i] == '\t' || + pi_c[i] == '\r' || pi_c[i] == '\n') + continue; + + last = i; + xstate = 1; + i--; + + break; + case 1: + if (pi_c[i] != '=') + continue; + + attr = [OFString stringWithCString: pi_c + last + length: i - last]; + last = i + 1; + xstate = 2; + + break; + case 2: + if (pi_c[i] != '\'' && pi_c[i] != '"') + return NO; + + xdelim = pi_c[i]; + last = i + 1; + xstate = 3; + + break; + case 3: + if (pi_c[i] != xdelim) + continue; + + val = [OFString stringWithCString: pi_c + last + length: i - last]; + + if ([attr isEqual: @"version"]) + if (![val hasPrefix: @"1."]) + return NO; + + if ([attr isEqual: @"encoding"]) + if ([val caseInsensitiveCompare: @"utf-8"] != + OF_ORDERED_SAME) + return NO; + + last = i + 1; + xstate = 0; + + break; + } + } + + if (xstate != 0) + return NO; + + return YES; +} + +/* Inside processing instructions */ - (void)_parseInProcessingInstructionsWithBuffer: (const char*)buf i: (size_t*)i last: (size_t*)last { if (buf[*i] == '?') @@ -368,10 +456,18 @@ * Class swizzle the string to be immutable. We pass it as * OFString*, so it can't be modified anyway. But not swizzling * it would create a real copy each time -[copy] is called. */ pi->isa = [OFString class]; + + if ([pi isEqual: @"xml"] || [pi hasPrefix: @"xml "] || + [pi hasPrefix: @"xml\t"] || [pi hasPrefix: @"xml\r"] || + [pi hasPrefix: @"xml\n"]) + if (![self _parseXMLProcessingInstructions: pi]) + @throw [OFMalformedXMLException + newWithClass: isa + parser: self]; [delegate parser: self foundProcessingInstructions: pi]; [pool release]; @@ -446,10 +542,13 @@ #endif [delegate parser: self didEndElement: name withPrefix: prefix namespace: ns]; + + if ([previous count] == 0) + finishedParsing = YES; } else [previous addObject: [[cache copy] autorelease]]; [pool release]; @@ -601,10 +700,13 @@ #endif [delegate parser: self didEndElement: name withPrefix: prefix namespace: ns]; + + if ([previous count] == 0) + finishedParsing = YES; [namespaces removeNObjects: 1]; } else if (prefix != nil) { OFString *str = [OFString stringWithFormat: @"%@:%@", prefix, name]; Index: src/base64.m ================================================================== --- src/base64.m +++ src/base64.m @@ -102,10 +102,13 @@ const uint8_t *buf = (const uint8_t*)str; size_t i; if ((len & 3) != 0) return NO; + + if ([data itemSize] != 1) + return NO; for (i = 0; i < len; i += 4) { uint32_t sb = 0; uint8_t cnt = 3; char db[3]; Index: src/exceptions/OFAcceptFailedException.m ================================================================== --- src/exceptions/OFAcceptFailedException.m +++ src/exceptions/OFAcceptFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFAcceptFailedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" #import "common.h" Index: src/exceptions/OFAddressTranslationFailedException.m ================================================================== --- src/exceptions/OFAddressTranslationFailedException.m +++ src/exceptions/OFAddressTranslationFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFAddressTranslationFailedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "common.h" @implementation OFAddressTranslationFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFAlreadyConnectedException.m ================================================================== --- src/exceptions/OFAlreadyConnectedException.m +++ src/exceptions/OFAlreadyConnectedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFAlreadyConnectedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" @implementation OFAlreadyConnectedException + newWithClass: (Class)class_ Index: src/exceptions/OFBindFailedException.m ================================================================== --- src/exceptions/OFBindFailedException.m +++ src/exceptions/OFBindFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFBindFailedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" #import "common.h" Index: src/exceptions/OFConditionBroadcastFailedException.m ================================================================== --- src/exceptions/OFConditionBroadcastFailedException.m +++ src/exceptions/OFConditionBroadcastFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFConditionBroadcastFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFConditionBroadcastFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFConditionSignalFailedException.m ================================================================== --- src/exceptions/OFConditionSignalFailedException.m +++ src/exceptions/OFConditionSignalFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFConditionSignalFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFConditionSignalFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFConditionStillWaitingException.m ================================================================== --- src/exceptions/OFConditionStillWaitingException.m +++ src/exceptions/OFConditionStillWaitingException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFConditionStillWaitingException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFConditionStillWaitingException + newWithClass: (Class)class_ Index: src/exceptions/OFConditionWaitFailedException.m ================================================================== --- src/exceptions/OFConditionWaitFailedException.m +++ src/exceptions/OFConditionWaitFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFConditionWaitFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFConditionWaitFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFConnectionFailedException.m ================================================================== --- src/exceptions/OFConnectionFailedException.m +++ src/exceptions/OFConnectionFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFConnectionFailedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" #import "common.h" @@ -75,12 +76,12 @@ { if (description != nil) return description; description = [[OFString alloc] initWithFormat: - @"A connection to %@ on port %" @PRIu16 @"could not be established " - @"in class %@! " ERRFMT, host, port, inClass, ERRPARAM]; + @"A connection to %@ on port %" @PRIu16 @" could not be " + @"established in class %@! " ERRFMT, host, port, inClass, ERRPARAM]; return description; } - (OFTCPSocket*)socket Index: src/exceptions/OFCopyFileFailedException.m ================================================================== --- src/exceptions/OFCopyFileFailedException.m +++ src/exceptions/OFCopyFileFailedException.m @@ -87,10 +87,10 @@ - (OFString*)sourcePath { return sourcePath; } -- (OFString*)destinationPath; +- (OFString*)destinationPath { return destinationPath; } @end Index: src/exceptions/OFHashAlreadyCalculatedException.m ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.m +++ src/exceptions/OFHashAlreadyCalculatedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFHashAlreadyCalculatedException.h" #import "OFString.h" +#import "OFHash.h" #import "OFNotImplementedException.h" @implementation OFHashAlreadyCalculatedException + newWithClass: (Class)class_ Index: src/exceptions/OFListenFailedException.m ================================================================== --- src/exceptions/OFListenFailedException.m +++ src/exceptions/OFListenFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFListenFailedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" #import "common.h" Index: src/exceptions/OFMalformedXMLException.m ================================================================== --- src/exceptions/OFMalformedXMLException.m +++ src/exceptions/OFMalformedXMLException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMalformedXMLException.h" #import "OFString.h" +#import "OFXMLParser.h" #import "OFNotImplementedException.h" @implementation OFMalformedXMLException + newWithClass: (Class)class_ Index: src/exceptions/OFMutexLockFailedException.m ================================================================== --- src/exceptions/OFMutexLockFailedException.m +++ src/exceptions/OFMutexLockFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMutexLockFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFMutexLockFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFMutexStillLockedException.m ================================================================== --- src/exceptions/OFMutexStillLockedException.m +++ src/exceptions/OFMutexStillLockedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMutexStillLockedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFMutexStillLockedException + newWithClass: (Class)class_ Index: src/exceptions/OFMutexUnlockFailedException.m ================================================================== --- src/exceptions/OFMutexUnlockFailedException.m +++ src/exceptions/OFMutexUnlockFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMutexUnlockFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFMutexUnlockFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFNotConnectedException.m ================================================================== --- src/exceptions/OFNotConnectedException.m +++ src/exceptions/OFNotConnectedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFNotConnectedException.h" #import "OFString.h" +#import "OFTCPSocket.h" #import "OFNotImplementedException.h" @implementation OFNotConnectedException + newWithClass: (Class)class_ Index: src/exceptions/OFRenameFileFailedException.m ================================================================== --- src/exceptions/OFRenameFileFailedException.m +++ src/exceptions/OFRenameFileFailedException.m @@ -87,10 +87,10 @@ - (OFString*)sourcePath { return sourcePath; } -- (OFString*)destinationPath; +- (OFString*)destinationPath { return destinationPath; } @end Index: src/exceptions/OFSeekFailedException.h ================================================================== --- src/exceptions/OFSeekFailedException.h +++ src/exceptions/OFSeekFailedException.h @@ -16,12 +16,10 @@ #ifndef _WIN32 # include #endif -#include - #import "OFException.h" @class OFSeekableStream; /** Index: src/exceptions/OFSeekFailedException.m ================================================================== --- src/exceptions/OFSeekFailedException.m +++ src/exceptions/OFSeekFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFSeekFailedException.h" #import "OFString.h" +#import "OFSeekableStream.h" #import "OFNotImplementedException.h" #import "common.h" Index: src/exceptions/OFSetOptionFailedException.m ================================================================== --- src/exceptions/OFSetOptionFailedException.m +++ src/exceptions/OFSetOptionFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFSetOptionFailedException.h" #import "OFString.h" +#import "OFStream.h" #import "OFNotImplementedException.h" @implementation OFSetOptionFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFThreadJoinFailedException.m ================================================================== --- src/exceptions/OFThreadJoinFailedException.m +++ src/exceptions/OFThreadJoinFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFThreadJoinFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFThreadJoinFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFThreadStartFailedException.m ================================================================== --- src/exceptions/OFThreadStartFailedException.m +++ src/exceptions/OFThreadStartFailedException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFThreadStartFailedException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFThreadStartFailedException + newWithClass: (Class)class_ Index: src/exceptions/OFThreadStillRunningException.m ================================================================== --- src/exceptions/OFThreadStillRunningException.m +++ src/exceptions/OFThreadStillRunningException.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFThreadStillRunningException.h" #import "OFString.h" +#import "OFThread.h" #import "OFNotImplementedException.h" @implementation OFThreadStillRunningException + newWithClass: (Class)class_ Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -69,11 +69,11 @@ # define OF_PATH_DELIM '/' #else # define OF_PATH_DELIM '\\' #endif -#define OF_IVAR_OFFSET(ivar) ((char*)&ivar - (char*)self) +#define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self) #define OF_GETTER(ivar, atomic) \ return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic); #define OF_SETTER(ivar, value, atomic, copy) \ objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy); @@ -180,12 +180,12 @@ "xchgl %%eax, %%edx" : "=A"(i) : "0"(i) ); #else - i = (uint64_t)of_bswap32_nonconst(i & 0xFFFFFFFF) << 32 | - of_bswap32_nonconst(i >> 32); + i = (uint64_t)of_bswap32_nonconst((uint32_t)(i & 0xFFFFFFFF)) << 32 | + of_bswap32_nonconst((uint32_t)(i >> 32)); #endif return i; } #ifdef __GNUC__ @@ -226,10 +226,18 @@ # define of_bswap32_if_le(i) of_bswap32(i) # define of_bswap64_if_le(i) of_bswap64(i) # define of_bswap32_vec_if_be(buf, len) #endif +/* + * We define it here and not in objfw-defs.h, as it would be theoretically + * possible to build a universal binary for Mac OS X and iOS. + */ +#if defined(__MACH__) && defined(__arm__) +# define OF_IOS +#endif + #define OF_ROL(val, bits) \ (((val) << ((bits) % (sizeof(val) * 8))) | \ (val) >> (sizeof(val) * 8 - ((bits) % (sizeof(val) * 8)))) #define OF_HASH_INIT(hash) hash = 0 Index: src/objc_properties.m ================================================================== --- src/objc_properties.m +++ src/objc_properties.m @@ -21,11 +21,11 @@ #import "OFObject.h" #ifdef OF_THREADS # import "threading.h" # define NUM_SPINLOCKS 8 /* needs to be a power of 2 */ -# define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1) +# define SPINLOCK_HASH(p) ((unsigned)((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1)) static of_spinlock_t spinlocks[NUM_SPINLOCKS]; #endif BOOL objc_properties_init() Index: src/objc_sync.m ================================================================== --- src/objc_sync.m +++ src/objc_sync.m @@ -17,10 +17,12 @@ #include "config.h" #include #include #include + +#include #ifdef OF_OBJFW_RUNTIME # import #else # import Index: src/of_asprintf.m ================================================================== --- src/of_asprintf.m +++ src/of_asprintf.m @@ -21,13 +21,17 @@ #include #include #include #include +#include + #import "OFString.h" #import "OFAutoreleasePool.h" #import "asprintf.h" + +#import "macros.h" #define MAX_SUBFMT_LEN 64 struct context { const char *fmt; @@ -167,12 +171,17 @@ } break; case 'l': /* and also ll */ if (ctx->fmt_len > ctx->i + 1 && ctx->fmt[ctx->i + 1] == 'l') { +#ifndef _WIN32 if (!append_subfmt(ctx, ctx->fmt + ctx->i, 2)) return false; +#else + if (!append_subfmt(ctx, "I64", 3)) + return false; +#endif ctx->i++; ctx->len_mod = LENGTH_MODIFIER_LL; } else { if (!append_subfmt(ctx, ctx->fmt + ctx->i, 1)) @@ -181,12 +190,17 @@ ctx->len_mod = LENGTH_MODIFIER_L; } break; case 'j': +#ifndef _WIN32 if (!append_subfmt(ctx, ctx->fmt + ctx->i, 1)) return false; +#else + if (!append_subfmt(ctx, "I64", 3)) + return false; +#endif ctx->len_mod = LENGTH_MODIFIER_J; break; case 'z': @@ -208,10 +222,33 @@ return false; ctx->len_mod = LENGTH_MODIFIER_CAPITAL_L; break; +#ifdef _WIN32 + case 'I': /* win32 strangeness (I64 instead of ll or j) */ + if (ctx->fmt_len > ctx->i + 2 && ctx->fmt[ctx->i + 1] == '6' && + ctx->fmt[ctx->i + 2] == '4') { + if (!append_subfmt(ctx, ctx->fmt + ctx->i, 3)) + return false; + + ctx->i += 2; + ctx->len_mod = LENGTH_MODIFIER_LL; + } else + ctx->i--; + + break; +#endif +#ifdef OF_IOS + case 'q': /* iOS uses this for PRI?64 */ + if (!append_subfmt(ctx, ctx->fmt + ctx->i, 1)) + return false; + + ctx->len_mod = LENGTH_MODIFIER_LL; + + break; +#endif default: ctx->i--; break; } Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -88,10 +88,21 @@ CloseHandle(thread); return YES; #endif } + +static OF_INLINE BOOL +of_thread_detach(of_thread_t thread) +{ +#if defined(OF_HAVE_PTHREADS) + return !pthread_detach(thread); +#elif defined(_WIN32) + /* FIXME */ + return YES; +#endif +} static OF_INLINE void of_thread_exit() { #if defined(OF_HAVE_PTHREADS) Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -20,14 +20,14 @@ #import "OFString.h" #import "OFAutoreleasePool.h" #if defined(OF_OBJFW_RUNTIME) # include +#elif defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) +# include #elif defined(OF_OLD_GNU_RUNTIME) # include -#elif defined(OF_APPLE_RUNTIME) -# include #endif #if defined(OF_OLD_GNU_RUNTIME) || defined(OF_OBJFW_RUNTIME) # define objc_getClass objc_get_class #endif @@ -59,14 +59,15 @@ TEST(@"Class of a malloc block", (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock")) TEST(@"Copying a stack block", - (m = [s copy]) && [m class] == objc_getClass("OFMallocBlock") && + (m = [[s copy] autorelease]) && + [m class] == objc_getClass("OFMallocBlock") && [m isKindOfClass: [OFBlock class]]) - TEST(@"Copying a global block", (id)g == [g copy]) + TEST(@"Copying a global block", (id)g == [[g copy] autorelease]) TEST(@"Copying a malloc block", (id)m == [m copy] && [m retainCount] == 2) TEST(@"Autorelease a stack block", R([s autorelease])) Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -135,12 +135,12 @@ @"file://testfile.txt"] encoding: OF_STRING_ENCODING_ISO_8859_1]) && [s[1] isEqual: @"testäöü"]) TEST(@"-[appendCStringWithLength:]", - R([s[0] appendCString: "foobarqux" + 3 - withLength: 3]) && [s[0] isEqual: @"foobar"]) + R([s[0] appendCString: "foo\xEF\xBB\xBF" "barqux" + 3 + withLength: 6]) && [s[0] isEqual: @"foobar"]) EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1", OFInvalidEncodingException, [OFString stringWithCString: "\xE0\x80"]) EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2", @@ -402,24 +402,43 @@ EXPECT_EXCEPTION(@"Detect OoR in " @"-[deleteCharactersFromIndex:toIndex:] #1", OFOutOfRangeException, { s[0] = [OFMutableString stringWithString: @"𝄞öö"]; - [s[0] substringFromIndex: 2 - toIndex: 4]; + [s[0] deleteCharactersFromIndex: 2 + toIndex: 4]; }) EXPECT_EXCEPTION(@"Detect OoR in " @"-[deleteCharactersFromIndex:toIndex:] #2", OFOutOfRangeException, - [s[0] substringFromIndex: 4 - toIndex: 4]) + [s[0] deleteCharactersFromIndex: 4 + toIndex: 4]) EXPECT_EXCEPTION(@"Detect s > e in " @"-[deleteCharactersFromIndex:toIndex:]", OFInvalidArgumentException, - [s[0] substringFromIndex: 2 - toIndex: 0]) + [s[0] deleteCharactersFromIndex: 2 + toIndex: 0]) + + EXPECT_EXCEPTION(@"OoR " + @"-[replaceCharactersFromIndex:toIndex:withString:] #1", + OFOutOfRangeException, [s[0] replaceCharactersFromIndex: 2 + toIndex: 4 + withString: @""]) + + EXPECT_EXCEPTION(@"OoR " + @"-[replaceCharactersFromIndex:toIndex:withString:] #2", + OFOutOfRangeException, + [s[0] replaceCharactersFromIndex: 4 + toIndex: 4 + withString: @""]) + + EXPECT_EXCEPTION(@"s>e in " + @"-[replaceCharactersFromIndex:toIndex:withString:]", + OFInvalidArgumentException, [s[0] replaceCharactersFromIndex: 2 + toIndex: 0 + withString: @""]) TEST(@"-[replaceOccurrencesOfString:withString:]", (s[0] = [OFMutableString stringWithString: @"asd fo asd fofo asd"]) && R([s[0] replaceOccurrencesOfString: @"fo" Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -73,11 +73,12 @@ TEST(@"-[fragment]", [[u1 fragment] isEqual: @"f"] && [u4 fragment] == nil) TEST(@"-[copy]", R(u4 = [[u1 copy] autorelease])) - TEST(@"-[isEqual:]", [u1 isEqual: u4] && ![u2 isEqual: u3]) + TEST(@"-[isEqual:]", [u1 isEqual: u4] && ![u2 isEqual: u3] && + [[OFURL URLWithString: @"http://bar/"] isEqual: u3]) TEST(@"-[hash:]", [u1 hash] == [u4 hash] && [u2 hash] != [u3 hash]) EXPECT_EXCEPTION(@"Detection of invalid format", OFInvalidFormatException, [OFURL URLWithString: @"http"]) Index: tests/OFXMLElementTests.m ================================================================== --- tests/OFXMLElementTests.m +++ tests/OFXMLElementTests.m @@ -117,17 +117,24 @@ [[elem[2] XMLString] isEqual: @""]) TEST(@"+[elementWithXMLString:] and -[stringValue]", [[[OFXMLElement elementWithXMLString: - @"foobazqux"] stringValue] + @"\r\nfoo" + @"bazqux"] stringValue] isEqual: @"foobarbazqux"]) TEST(@"-[elementsForName:namespace:]", (a = [elem[2] elementsForName: @"bar" namespace: @"urn:objfw:test"]) && [a count] == 1 && [[[a firstObject] XMLString] isEqual: @""]) + TEST(@"-[isEqual:]", + [[OFXMLElement elementWithXMLString: @""] isEqual: + [OFXMLElement elementWithXMLString: @""]] && + [[OFXMLElement elementWithXMLString: @""] isEqual: + [OFXMLElement elementWithXMLString: @""]]) + [pool drain]; } @end Index: tests/OFXMLParserTests.m ================================================================== --- tests/OFXMLParserTests.m +++ tests/OFXMLParserTests.m @@ -374,8 +374,23 @@ OFMalformedXMLException, [parser parseString: @"a"]) EXPECT_EXCEPTION(@"Detection of junk after the document #2", OFMalformedXMLException, [parser parseString: @""]) + + parser = [OFXMLParser parser]; + EXPECT_EXCEPTION(@"Detection of invalid XML processing instructions #2", + OFMalformedXMLException, + [parser parseString: @""]) + + parser = [OFXMLParser parser]; + EXPECT_EXCEPTION(@"Detection of invalid XML processing instructions #3", + OFMalformedXMLException, + [parser parseString: @""]) + [pool drain]; } @end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -40,11 +40,11 @@ \ @try { \ code; \ } @catch (exception *e) { \ caught = YES; \ - [e dealloc]; \ + [e release]; \ } \ \ if (caught) \ [self outputSuccess: test \ inModule: module]; \ Index: utils/objfw-compile ================================================================== --- utils/objfw-compile +++ utils/objfw-compile @@ -109,10 +109,13 @@ ;; -framework) shift LIBS="$LIBS -framework $1" ;; + -f*) + OBJCFLAGS="$OBJCFLAGS $1" + ;; -g*) OBJCFLAGS="$OBJCFLAGS $1" ;; -I) shift Index: utils/objfw-config.in ================================================================== --- utils/objfw-config.in +++ utils/objfw-config.in @@ -35,11 +35,11 @@ LIBS="-L${libdir} -lobjfw @LIBS@" PLUGIN_CFLAGS="@PLUGIN_CFLAGS@" PLUGIN_LDFLAGS="@PLUGIN_LDFLAGS@" PLUGIN_SUFFIX="@PLUGIN_SUFFIX@" PROG_SUFFIX="@EXEEXT@" -VERSION="0.4-dev" +VERSION="0.5.4" show_help() { cat <<__EOF__ objfw-config: Available arguments are: