Index: ChangeLog
==================================================================
--- ChangeLog
+++ ChangeLog
@@ -1,9 +1,49 @@
Legend:
* Changes of existing features or bugfixes.
+ New features.
+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.3
CFBundleShortVersionString
- 0.4-dev
+ 0.5.3
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: 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.3, 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,11 +253,11 @@
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;
@@ -257,10 +265,13 @@
if (src->forwarding == src)
src->forwarding = *dst;
memcpy(*dst, src, src->size);
+
+ /* src->forwarding points to us -> that's a reference */
+ (*dst)->flags++;
if (src->size >= sizeof(of_block_byref_t))
src->byref_keep(*dst, src);
} else
*dst = src;
@@ -273,10 +284,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 +301,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);
}
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
@@ -15,10 +15,11 @@
*/
#include "config.h"
#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/OFObject.m
==================================================================
--- src/OFObject.m
+++ src/OFObject.m
@@ -39,10 +39,11 @@
#if defined(OF_OBJFW_RUNTIME)
# import
#elif defined(OF_OLD_GNU_RUNTIME)
# import
# import
+# import
#else
# import
#endif
#ifdef _WIN32
@@ -249,11 +250,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 +363,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 +421,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 +679,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/OFStreamObserver.m
==================================================================
--- src/OFStreamObserver.m
+++ src/OFStreamObserver.m
@@ -40,10 +40,12 @@
#import "OFAutoreleasePool.h"
#import "OFInitializationFailedException.h"
#import "OFOutOfRangeException.h"
+#import "macros.h"
+
#ifdef _WIN32
# define close(sock) closesocket(sock)
#endif
enum {
@@ -153,18 +155,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 +487,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/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/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
@@ -20,10 +20,14 @@
# 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 +53,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 +75,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 +218,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 +257,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 +291,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
@@ -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 {
@@ -358,13 +369,10 @@
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) {
OFEnumerator *key_enum = [namespaces keyEnumerator];
OFEnumerator *obj_enum = [namespaces objectEnumerator];
id key, obj;
@@ -381,20 +389,25 @@
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 +423,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 +440,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];
@@ -748,15 +758,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
@@ -49,11 +49,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 +155,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 +266,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 +277,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 +319,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 +332,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 +455,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 +541,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 +699,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.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
@@ -24,10 +24,12 @@
#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 +169,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 +188,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 +220,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,17 +59,18 @@
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)
+ (id)m == [[m copy] autorelease] && [m retainCount] == 2)
TEST(@"Autorelease a stack block", R([s autorelease]))
TEST(@"Autorelease a global block", R([g 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",
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.3"
show_help() {
cat <<__EOF__
objfw-config: Available arguments are: