ObjFW  Changes On Branch 0.90

Changes In Branch 0.90 Excluding Merge-Ins

This is equivalent to a diff from 636098dbdd to 3c65e47ed2

2020-05-31
16:17
Close 0.90 branch Closed-Leaf check-in: 3c65e47ed2 user: js tags: 0.90
2018-04-15
14:50
OFLocalization: Fix setting the territory check-in: 5fcee684cb user: js tags: 0.90
2017-07-29
10:50
Set version to 0.90-dev as 0.90 has been branched check-in: 7e614ef5c0 user: js tags: trunk
10:22
Create 0.90 branch check-in: f934699959 user: js tags: 0.90
2017-07-24
20:33
runtime: Don't depend on platform.h in ObjFW-RT.h check-in: 636098dbdd user: js tags: trunk
20:29
OFINIFile: Always use \r\n check-in: 1248c00475 user: js tags: trunk

Modified ChangeLog from [22a812d84f] to [9da9558760].

1
2
3


























































4
5
6
7
8
9
10
Legend:
 * Changes of existing features or bugfixes
 + New features



























































ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015
 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in
   Clang 3.7 (this fixes compilation with Clang 3.7)
 * Blocks: Proper handling when called from a byref handler
 * Fix compilation on Solaris
 * Fix compilation for Wii, PSP and Nintendo DS



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
Legend:
 * Changes of existing features or bugfixes
 + New features

This file only contains the most significant changes.

ObjFW 0.90.1 -> ObjFW 0.90.2, 23.10.2017
 * Fix shadowed variables which caused many bugs (e.g. using the wrong object)
 * Many, many nullability fixes
 * OFTCPSocket: Fix exception not being retained for async connect
 * OFThread: Fix setting the name on the wrong thread
 * OFMutableSet: Fix missing override for -[copy]
 * configure: Fix posix_spawnp check
 * Xcode project: Set the correct version for the bridge
 * Better check for iOS
 * tests: Fix testing the wrong OFKernelEventObserver

ObjFW 0.90 -> ObjFW 0.90.1, 20.08.2017
 * OFData: Fix -[description]
 * OFFileManager: Set errno to 0 before readdir()
 * OFDate: Add -[localMinute]
 * OFTarArchiveEntry: Fix prefix handling for ustar
 * OFZIPArchive: Fix uncompressed + data descriptor
 * OFArray: Fix MessagePack encoding
 * of_asprintf: Don't require set up OFLocalization
 * OFGZIPStream: Add missing documentation
 * Fix a linker warning on OpenBSD/SPARC64
 * Remove the OFFile b modes from MorphOS
   (they were already removed for all other OSes)

ObjFW 0.8.1 -> ObjFW 0.90, 01.08.2017
 + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry
		OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager,
		OFLocalization
 + New platforms: Nintendo 3DS, MorphOS
 + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF
 + New forwarding for: ARM64/ELF
 + New tools: objfw-new (to create boilerplate code)
 + New options: --disable-unicode-tables
 * Required GCC version increased to 4.6
 * OFDataArray was split into OFData and OFMutableData
 * OFURL was split into OFURL and OFMutableURL
 * Most properties are now nonatomic
   (this changes from returned retained + autoreleased to +0 retained)
 * Correct handling of encoding on Win32 console
   (stream is read and written in UTF-8 and translated to UTF-16 on the fly)
 * Runtime is now built as a separate library
 + More encodings for strings
 * Reworked OFOptionsParser API
 * Refactored OFKernelEventObserver
 * Better randomization of HTTP header order
 * Allow overriding all HTTP headers
 * Definition of thread priorities changed
 + Key Value Coding
 + Exceptions in ObjC++
 * OFHash was renamed to OFCryptoHash
 + PBKDF2
 + scrypt
 + Xcode project to build for iOS
 + String decomposition to NFD
 * OFFile modes simplified ('b' removed)

ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015
 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in
   Clang 3.7 (this fixes compilation with Clang 3.7)
 * Blocks: Proper handling when called from a byref handler
 * Fix compilation on Solaris
 * Fix compilation for Wii, PSP and Nintendo DS

Modified Doxyfile from [31e59694ac] to [27902ec17a].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	     OF_HAVE_BLOCKS			\
	     OF_HAVE_FILES			\
	     OF_HAVE_SANDBOX			\
	     OF_HAVE_SOCKETS			\
	     OF_HAVE_THREADS			\
	     OF_NO_RETURN			\
	     OF_NO_RETURN_FUNC			\
	     OF_NULLABLE_PROPERTY		\
	     OF_NULL_RESETTABLE_PROPERTY	\
	     OF_REQUIRES_SUPER			\
	     OF_RETURNS_INNER_POINTER		\
	     OF_RETURNS_NOT_RETAINED		\
	     OF_RETURNS_RETAINED		\
	     OF_ROOT_CLASS			\
	     OF_SENTINEL			\
	     OF_WEAK_UNAVAILABLE		\
	     SIGHUP				\
	     SIGUSR1				\
	     SIGUSR2
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
IGNORE_PREFIX = OF of_







|
|













13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	     OF_HAVE_BLOCKS			\
	     OF_HAVE_FILES			\
	     OF_HAVE_SANDBOX			\
	     OF_HAVE_SOCKETS			\
	     OF_HAVE_THREADS			\
	     OF_NO_RETURN			\
	     OF_NO_RETURN_FUNC			\
	     OF_NULLABLE_PROPERTY(...)=		\
	     OF_NULL_RESETTABLE_PROPERTY(...)=	\
	     OF_REQUIRES_SUPER			\
	     OF_RETURNS_INNER_POINTER		\
	     OF_RETURNS_NOT_RETAINED		\
	     OF_RETURNS_RETAINED		\
	     OF_ROOT_CLASS			\
	     OF_SENTINEL			\
	     OF_WEAK_UNAVAILABLE		\
	     SIGHUP				\
	     SIGUSR1				\
	     SIGUSR2
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
IGNORE_PREFIX = OF of_

Modified ObjFW.xcodeproj/project.pbxproj from [b65ec16d37] to [06460d959d].

3799
3800
3801
3802
3803
3804
3805

3806
3807
3808
3809
3810
3811
3812
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = c11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 2;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_PEDANTIC = YES;

				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				ONLY_ACTIVE_ARCH = YES;
				OTHER_CFLAGS = (
					"-fexceptions",







>







3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = c11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 2;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_PEDANTIC = YES;
				GCC_WARN_SHADOW = YES;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				ONLY_ACTIVE_ARCH = YES;
				OTHER_CFLAGS = (
					"-fexceptions",
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = c11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 2;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_PEDANTIC = YES;

				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				OTHER_CFLAGS = (
					"-fexceptions",
					"-fconstant-string-class=OFConstantString",







>







3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = c11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 2;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_PEDANTIC = YES;
				GCC_WARN_SHADOW = YES;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				OTHER_CFLAGS = (
					"-fexceptions",
					"-fconstant-string-class=OFConstantString",
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				DEFINES_MODULE = YES;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				DYLIB_COMPATIBILITY_VERSION = 7;
				DYLIB_CURRENT_VERSION = 7;
				ENABLE_BITCODE = NO;
				FRAMEWORK_VERSION = A;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (







|
|







3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				DEFINES_MODULE = YES;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				DYLIB_COMPATIBILITY_VERSION = 8;
				DYLIB_CURRENT_VERSION = 8;
				ENABLE_BITCODE = NO;
				FRAMEWORK_VERSION = A;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				DEFINES_MODULE = YES;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				DYLIB_COMPATIBILITY_VERSION = 7;
				DYLIB_CURRENT_VERSION = 7;
				ENABLE_BITCODE = NO;
				FRAMEWORK_VERSION = A;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = OF_BRIDGE_LOCAL_INCLUDES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;







|
|







3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				DEFINES_MODULE = YES;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				DYLIB_COMPATIBILITY_VERSION = 8;
				DYLIB_CURRENT_VERSION = 8;
				ENABLE_BITCODE = NO;
				FRAMEWORK_VERSION = A;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = OF_BRIDGE_LOCAL_INCLUDES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 7;
				DYLIB_CURRENT_VERSION = 7;
				FRAMEWORK_VERSION = A;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",







|
|







3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 8;
				DYLIB_CURRENT_VERSION = 8;
				FRAMEWORK_VERSION = A;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 7;
				DYLIB_CURRENT_VERSION = 7;
				FRAMEWORK_VERSION = A;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = OF_BRIDGE_LOCAL_INCLUDES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;







|
|







3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 8;
				DYLIB_CURRENT_VERSION = 8;
				FRAMEWORK_VERSION = A;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREPROCESSOR_DEFINITIONS = OF_BRIDGE_LOCAL_INCLUDES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;

Modified configure.ac from [12f3d4bae6] to [c8a78845ba].

1
2
3
4
5
6
7
8
AC_INIT(ObjFW, 0.9-dev, js@heap.zone)
BUILDSYS_INIT

AS_IF([test configure.ac -nt configure], [
	AC_MSG_ERROR([configure.ac is newer than configure! Run autoreconf!])
])

AC_CONFIG_SRCDIR(src)
|







1
2
3
4
5
6
7
8
AC_INIT(ObjFW, 0.90.2, js@heap.zone)
BUILDSYS_INIT

AS_IF([test configure.ac -nt configure], [
	AC_MSG_ERROR([configure.ac is newer than configure! Run autoreconf!])
])

AC_CONFIG_SRCDIR(src)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
	*-morphos*)
		AS_IF([test x"$with_ixemul" != x"yes"], [
			OBJCFLAGS="$OBJCFLAGS -noixemul"
			LDFLAGS="$LDFLAGS -noixemul"
			enable_files="yes"	# Required for reading ENV:

			AC_SUBST(NOIXEMUL, -noixemul)
			AC_SUBST(OBJFW_RT_MORPHOS_LIB, objfw-rt.library)
		])

		enable_shared="no"
		enable_threads="no"
		;;
	*-msdosdjgpp*)
		enable_shared="no"







<







21
22
23
24
25
26
27

28
29
30
31
32
33
34
	*-morphos*)
		AS_IF([test x"$with_ixemul" != x"yes"], [
			OBJCFLAGS="$OBJCFLAGS -noixemul"
			LDFLAGS="$LDFLAGS -noixemul"
			enable_files="yes"	# Required for reading ENV:

			AC_SUBST(NOIXEMUL, -noixemul)

		])

		enable_shared="no"
		enable_threads="no"
		;;
	*-msdosdjgpp*)
		enable_shared="no"
173
174
175
176
177
178
179


180
181
182
183
184
185
186
AX_CHECK_COMPILER_FLAGS(-fno-common, [OBJCFLAGS="$OBJCFLAGS -fno-common"])
AX_CHECK_COMPILER_FLAGS(-fno-constant-cfstrings, [
	OBJCFLAGS="$OBJCFLAGS -fno-constant-cfstrings"
	AC_SUBST(NO_CONST_CFSTRINGS, "-fno-constant-cfstrings")
])
AX_CHECK_COMPILER_FLAGS(-Wsign-compare -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wsign-compare"])


AX_CHECK_COMPILER_FLAGS(-Wshorten-64-to-32 -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wshorten-64-to-32"])
AX_CHECK_COMPILER_FLAGS(-Wsemicolon-before-method-body -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wsemicolon-before-method-body"])
AX_CHECK_COMPILER_FLAGS(-Wobjc-missing-property-synthesis -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wobjc-missing-property-synthesis"])
AX_CHECK_COMPILER_FLAGS(-Watomic-properties -Werror, [







>
>







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
AX_CHECK_COMPILER_FLAGS(-fno-common, [OBJCFLAGS="$OBJCFLAGS -fno-common"])
AX_CHECK_COMPILER_FLAGS(-fno-constant-cfstrings, [
	OBJCFLAGS="$OBJCFLAGS -fno-constant-cfstrings"
	AC_SUBST(NO_CONST_CFSTRINGS, "-fno-constant-cfstrings")
])
AX_CHECK_COMPILER_FLAGS(-Wsign-compare -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wsign-compare"])
AX_CHECK_COMPILER_FLAGS(-Wshadow -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wshadow"])
AX_CHECK_COMPILER_FLAGS(-Wshorten-64-to-32 -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wshorten-64-to-32"])
AX_CHECK_COMPILER_FLAGS(-Wsemicolon-before-method-body -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wsemicolon-before-method-body"])
AX_CHECK_COMPILER_FLAGS(-Wobjc-missing-property-synthesis -Werror,
	[OBJCFLAGS="$OBJCFLAGS -Wobjc-missing-property-synthesis"])
AX_CHECK_COMPILER_FLAGS(-Watomic-properties -Werror, [
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
	])
	AS_IF([test x"$enable_static" = x"yes" -o x"$enable_shared" = x"no"], [
		AC_SUBST(ENCODINGS_A, "encodings.a")
		AC_SUBST(ENCODINGS_ENCODINGS_A, "encodings/encodings.a")
	])
])

AC_CHECK_FUNCS(sigaction)

AC_CHECK_FUNCS(arc4random random, break)

AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl")
AC_CHECK_HEADERS_ONCE(dlfcn.h)
case "$host_os" in
	netbsd*)
		dnl dladdr exists on NetBSD, but it is completely broken.







<
<







654
655
656
657
658
659
660


661
662
663
664
665
666
667
	])
	AS_IF([test x"$enable_static" = x"yes" -o x"$enable_shared" = x"no"], [
		AC_SUBST(ENCODINGS_A, "encodings.a")
		AC_SUBST(ENCODINGS_ENCODINGS_A, "encodings/encodings.a")
	])
])



AC_CHECK_FUNCS(arc4random random, break)

AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl")
AC_CHECK_HEADERS_ONCE(dlfcn.h)
case "$host_os" in
	netbsd*)
		dnl dladdr exists on NetBSD, but it is completely broken.
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
		AC_DEFINE(HAVE_EPOLL, 1, [Whether we have epoll])
		AC_SUBST(OFKERNELEVENTOBSERVER_EPOLL_M,
			"OFKernelEventObserver_epoll.m")
		break
	])

	AS_IF([test x"$with_wii" = x"yes"], [

		AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M,
			"OFKernelEventObserver_poll.m")
	], [
		AC_CHECK_HEADERS(poll.h)
		AC_CHECK_FUNC(poll, [
			AC_DEFINE(HAVE_POLL, 1, [Whether we have poll()])
			AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M,







>







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
		AC_DEFINE(HAVE_EPOLL, 1, [Whether we have epoll])
		AC_SUBST(OFKERNELEVENTOBSERVER_EPOLL_M,
			"OFKernelEventObserver_epoll.m")
		break
	])

	AS_IF([test x"$with_wii" = x"yes"], [
		AC_DEFINE(HAVE_POLL, 1, [Whether we have poll()])
		AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M,
			"OFKernelEventObserver_poll.m")
	], [
		AC_CHECK_HEADERS(poll.h)
		AC_CHECK_FUNC(poll, [
			AC_DEFINE(HAVE_POLL, 1, [Whether we have poll()])
			AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M,
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
	*-*-msdosdjgpp*)
		have_processes="no"
		;;
	*)
		AC_HEADER_SYS_WAIT
		AC_CHECK_FUNCS(kill)

		AC_CHECK_FUNC(posix_spawnp, [
			AS_IF([test x"$ac_cv_func_kill" = x"yes"], [
				have_processes="yes"

				AC_CHECK_HEADERS(spawn.h)
			])
		], [
			AC_CHECK_FUNCS([vfork dup2 execvp _exit], [







|







1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
	*-*-msdosdjgpp*)
		have_processes="no"
		;;
	*)
		AC_HEADER_SYS_WAIT
		AC_CHECK_FUNCS(kill)

		AC_CHECK_FUNCS(posix_spawnp, [
			AS_IF([test x"$ac_cv_func_kill" = x"yes"], [
				have_processes="yes"

				AC_CHECK_HEADERS(spawn.h)
			])
		], [
			AC_CHECK_FUNCS([vfork dup2 execvp _exit], [

Modified extra.mk.in from [130d0ab22e] to [f18de84cc5].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
# When changing: Be sure to also change these in the Xcode project!
OBJFW_LIB_MAJOR = 8
OBJFW_LIB_MINOR = 0
OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}

OBJFW_RT_SHARED_LIB = @OBJFW_RT_SHARED_LIB@
OBJFW_RT_STATIC_LIB = @OBJFW_RT_STATIC_LIB@
OBJFW_RT_MORPHOS_LIB = @OBJFW_RT_MORPHOS_LIB@
OBJFW_RT_LIB_MAJOR = 0
OBJFW_RT_LIB_MINOR = 0
OBJFW_RT_LIB_MAJOR_MINOR = ${OBJFW_RT_LIB_MAJOR}.${OBJFW_RT_LIB_MINOR}

OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@
OBJFW_BRIDGE_STATIC_LIB = @OBJFW_BRIDGE_STATIC_LIB@





|




<







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
# When changing: Be sure to also change these in the Xcode project!
OBJFW_LIB_MAJOR = 8
OBJFW_LIB_MINOR = 1
OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}

OBJFW_RT_SHARED_LIB = @OBJFW_RT_SHARED_LIB@
OBJFW_RT_STATIC_LIB = @OBJFW_RT_STATIC_LIB@

OBJFW_RT_LIB_MAJOR = 0
OBJFW_RT_LIB_MINOR = 0
OBJFW_RT_LIB_MAJOR_MINOR = ${OBJFW_RT_LIB_MAJOR}.${OBJFW_RT_LIB_MINOR}

OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@
OBJFW_BRIDGE_STATIC_LIB = @OBJFW_BRIDGE_STATIC_LIB@

Modified src/OFApplication.h from [627b4181f1] to [e7e5df2d5d].

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
{
	OFString *_programName;
	OFArray OF_GENERIC(OFString *) *_arguments;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_environment;
	int *_argc;
	char ***_argv;
@public
	id <OFApplicationDelegate> _delegate;
	void (*_SIGINTHandler)(id, SEL);
#ifndef OF_WINDOWS
	void (*_SIGHUPHandler)(id, SEL);
	void (*_SIGUSR1Handler)(id, SEL);
	void (*_SIGUSR2Handler)(id, SEL);
#endif
}

/*!
 * The name of the program (argv[0]).
 */
@property (readonly, nonatomic) OFString *programName;







|
|

|
|
|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
{
	OFString *_programName;
	OFArray OF_GENERIC(OFString *) *_arguments;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_environment;
	int *_argc;
	char ***_argv;
@public
	id <OFApplicationDelegate> _Nullable _delegate;
	void (*_Nullable _SIGINTHandler)(id, SEL);
#ifndef OF_WINDOWS
	void (*_Nullable _SIGHUPHandler)(id, SEL);
	void (*_Nullable _SIGUSR1Handler)(id, SEL);
	void (*_Nullable _SIGUSR2Handler)(id, SEL);
#endif
}

/*!
 * The name of the program (argv[0]).
 */
@property (readonly, nonatomic) OFString *programName;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    OFDictionary OF_GENERIC(OFString *, OFString *) *environment;

/*!
 * @brief Returns the only OFApplication instance in the application.
 *
 * @return The only OFApplication instance in the application
 */
+ (OFApplication *)sharedApplication;

/*!
 * @brief Returns the name of the program (argv[0]).
 *
 * @return The name of the program (argv[0])
 */
+ (OFString *)programName;

/*!
 * @brief Returns the arguments passed to the application.
 *
 * @return The arguments passed to the application
 */
+ (OFArray OF_GENERIC(OFString *) *)arguments;

/*!
 * @brief Returns the environment of the application.
 *
 * @return The environment of the application
 */
+ (OFDictionary OF_GENERIC(OFString *, OFString *) *)environment;

/*!
 * @brief Terminates the application with the EXIT_SUCCESS status.
 */
+ (void)terminate OF_NO_RETURN;

/*!







|






|






|






|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    OFDictionary OF_GENERIC(OFString *, OFString *) *environment;

/*!
 * @brief Returns the only OFApplication instance in the application.
 *
 * @return The only OFApplication instance in the application
 */
+ (nullable OFApplication *)sharedApplication;

/*!
 * @brief Returns the name of the program (argv[0]).
 *
 * @return The name of the program (argv[0])
 */
+ (nullable OFString *)programName;

/*!
 * @brief Returns the arguments passed to the application.
 *
 * @return The arguments passed to the application
 */
+ (nullable OFArray OF_GENERIC(OFString *) *)arguments;

/*!
 * @brief Returns the environment of the application.
 *
 * @return The environment of the application
 */
+ (nullable OFDictionary OF_GENERIC(OFString *, OFString *) *)environment;

/*!
 * @brief Terminates the application with the EXIT_SUCCESS status.
 */
+ (void)terminate OF_NO_RETURN;

/*!

Modified src/OFApplication.m from [c9d4f7d315] to [23fc1019fd].

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

#ifdef OF_NINTENDO_DS
# define asm __asm__
# include <nds.h>
# undef asm
#endif

#ifdef HAVE_SIGACTION
# ifndef SA_RESTART
#  define SA_RESTART 0
# endif
#endif

@interface OFApplication ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
- (void)of_setArgumentCount: (int *)argc
	  andArgumentValues: (char **[])argv;
#ifdef OF_WINDOWS
- (void)of_setArgumentCount: (int)argc
      andWideArgumentValues: (wchar_t *[])argv;







<
<
<
<
<
<







67
68
69
70
71
72
73






74
75
76
77
78
79
80

#ifdef OF_NINTENDO_DS
# define asm __asm__
# include <nds.h>
# undef asm
#endif







@interface OFApplication ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
- (void)of_setArgumentCount: (int *)argc
	  andArgumentValues: (char **[])argv;
#ifdef OF_WINDOWS
- (void)of_setArgumentCount: (int)argc
      andWideArgumentValues: (wchar_t *[])argv;
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

	if ([delegate respondsToSelector: @selector(applicationWillTerminate)])
		[delegate applicationWillTerminate];

	[delegate release];
}

#define SIGNAL_HANDLER(sig)					\
	static void						\
	handle##sig(int signal)					\
	{							\
		app->_##sig##Handler(app->_delegate,		\
		    @selector(applicationDidReceive##sig));	\
	}
SIGNAL_HANDLER(SIGINT)
#ifdef SIGHUP
SIGNAL_HANDLER(SIGHUP)
#endif
#ifdef SIGUSR1
SIGNAL_HANDLER(SIGUSR1)







|

|

|
|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

	if ([delegate respondsToSelector: @selector(applicationWillTerminate)])
		[delegate applicationWillTerminate];

	[delegate release];
}

#define SIGNAL_HANDLER(signal)					\
	static void						\
	handle##signal(int sig)					\
	{							\
		app->_##signal##Handler(app->_delegate,		\
		    @selector(applicationDidReceive##signal));	\
	}
SIGNAL_HANDLER(SIGINT)
#ifdef SIGHUP
SIGNAL_HANDLER(SIGHUP)
#endif
#ifdef SIGUSR1
SIGNAL_HANDLER(SIGUSR1)
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538

539
540
541
542
543
544
545
- (id <OFApplicationDelegate>)delegate
{
	return _delegate;
}

- (void)setDelegate: (id <OFApplicationDelegate>)delegate
{
#ifdef HAVE_SIGACTION
	struct sigaction sa = { .sa_flags = SA_RESTART };
	sigemptyset(&sa.sa_mask);

# define REGISTER_SIGNAL(sig)						\
	if ([delegate respondsToSelector:				\
	    @selector(applicationDidReceive##sig)]) {			\
		_##sig##Handler = (void (*)(id, SEL))[(id)delegate	\
		    methodForSelector:					\
		    @selector(applicationDidReceive##sig)];		\
									\
		sa.sa_handler = handle##sig;				\
	} else								\
		sa.sa_handler = SIG_DFL;				\
									\
	OF_ENSURE(sigaction(sig, &sa, NULL) == 0);
#else
# define REGISTER_SIGNAL(sig)						\
	if ([delegate respondsToSelector:				\
	    @selector(applicationDidReceive##sig)]) {			\
		_##sig##Handler = (void (*)(id, SEL))[(id)delegate	\
		    methodForSelector:					\
		    @selector(applicationDidReceive##sig)];		\
		signal(sig, handle##sig);				\
	} else								\

		signal(sig, (void (*)(int))SIG_DFL);
#endif


	_delegate = delegate;

	REGISTER_SIGNAL(SIGINT)
#ifdef SIGHUP
	REGISTER_SIGNAL(SIGHUP)
#endif







<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<






|
>
|
<
>







499
500
501
502
503
504
505




506













507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
- (id <OFApplicationDelegate>)delegate
{
	return _delegate;
}

- (void)setDelegate: (id <OFApplicationDelegate>)delegate
{




#define REGISTER_SIGNAL(sig)						\













	if ([delegate respondsToSelector:				\
	    @selector(applicationDidReceive##sig)]) {			\
		_##sig##Handler = (void (*)(id, SEL))[(id)delegate	\
		    methodForSelector:					\
		    @selector(applicationDidReceive##sig)];		\
		signal(sig, handle##sig);				\
	} else {							\
		_##sig##Handler = NULL;					\
		signal(sig, (void (*)(int))SIG_DFL);			\

	}

	_delegate = delegate;

	REGISTER_SIGNAL(SIGINT)
#ifdef SIGHUP
	REGISTER_SIGNAL(SIGHUP)
#endif

Modified src/OFArray.h from [768648064e] to [9cbd05d142].

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
 * each object.
 *
 * @note A @ref OFNull value is translated to nil!
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (nullable id)value
	  forKey: (OFString *)key;

/*!
 * @brief Copies the objects at the specified range to the specified buffer.
 *
 * @param buffer The buffer to copy the objects to
 * @param range The range to copy







|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
 * each object.
 *
 * @note A @ref OFNull value is translated to nil!
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (id)value
	  forKey: (OFString *)key;

/*!
 * @brief Copies the objects at the specified range to the specified buffer.
 *
 * @param buffer The buffer to copy the objects to
 * @param range The range to copy
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*!
 * @brief Checks whether the array contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the array
 * @return A boolean whether the array contains the specified object
 */
- (bool)containsObject: (nullable ObjectType)object;

/*!
 * @brief Checks whether the array contains an object with the specified
 *	  address.
 *
 * @param object The object which is checked for being in the array
 * @return A boolean whether the array contains an object with the specified
 *	   address
 */
- (bool)containsObjectIdenticalTo: (nullable ObjectType)object;

/*!
 * @brief Returns the first object of the array or `nil`.
 *
 * @warning The returned object is *not* retained and autoreleased for
 *	    performance reasons!
 *







|









|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*!
 * @brief Checks whether the array contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the array
 * @return A boolean whether the array contains the specified object
 */
- (bool)containsObject: (ObjectType)object;

/*!
 * @brief Checks whether the array contains an object with the specified
 *	  address.
 *
 * @param object The object which is checked for being in the array
 * @return A boolean whether the array contains an object with the specified
 *	   address
 */
- (bool)containsObjectIdenticalTo: (ObjectType)object;

/*!
 * @brief Returns the first object of the array or `nil`.
 *
 * @warning The returned object is *not* retained and autoreleased for
 *	    performance reasons!
 *
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# undef ObjectType
#endif
@end

@interface OFArrayEnumerator: OFEnumerator
{
	OFArray	      *_array;
	size_t	      _count;
	unsigned long _mutations;
	unsigned long *_mutationsPtr;
	size_t	      _position;
}

- initWithArray: (OFArray *)data
   mutationsPtr: (unsigned long *_Nullable)mutationsPtr;
@end

OF_ASSUME_NONNULL_END

#import "OFMutableArray.h"

#if !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/* Required for array literals to work */
@compatibility_alias NSArray OFArray;
#endif







|
|

|
|



|










481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# undef ObjectType
#endif
@end

@interface OFArrayEnumerator: OFEnumerator
{
	OFArray	*_array;
	size_t _count;
	unsigned long _mutations;
	unsigned long *_Nullable _mutationsPtr;
	size_t _position;
}

- initWithArray: (OFArray *)data
   mutationsPtr: (nullable unsigned long *)mutationsPtr;
@end

OF_ASSUME_NONNULL_END

#import "OFMutableArray.h"

#if !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/* Required for array literals to work */
@compatibility_alias NSArray OFArray;
#endif

Modified src/OFArray.m from [15022d3186] to [1810203c70].

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
}

- mutableCopy
{
	return [[OFMutableArray alloc] initWithArray: self];
}

- (id)objectAtIndex: (size_t)index
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)objectAtIndexedSubscript: (size_t)index
{
	return [self objectAtIndex: index];
}

- (id)valueForKey: (OFString *)key
{
	OFMutableArray *ret;

	if ([key hasPrefix: @"@"]) {
		void *pool = objc_autoreleasePoolPush();
		id ret;

		key = [key substringWithRange: of_range(1, [key length] - 1)];
		ret = [[super valueForKey: key] retain];

		objc_autoreleasePoolPop(pool);

		return [ret autorelease];







|




|

|




|



<







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
}

- mutableCopy
{
	return [[OFMutableArray alloc] initWithArray: self];
}

- (id)objectAtIndex: (size_t)idx
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)objectAtIndexedSubscript: (size_t)idx
{
	return [self objectAtIndex: idx];
}

- (id)valueForKey: (OFString *)key
{
	id ret;

	if ([key hasPrefix: @"@"]) {
		void *pool = objc_autoreleasePoolPush();


		key = [key substringWithRange: of_range(1, [key length] - 1)];
		ret = [[super valueForKey: key] retain];

		objc_autoreleasePoolPop(pool);

		return [ret autorelease];
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
		[super setValue: value
			 forKey: key];

		objc_autoreleasePoolPop(pool);
		return;
	}

	if (value == [OFNull null])
		value = nil;

	for (id object in self)
		[object setValue: value
			  forKey: key];
}

- (size_t)indexOfObject: (id)object
{







<
<
<







314
315
316
317
318
319
320



321
322
323
324
325
326
327
		[super setValue: value
			 forKey: key];

		objc_autoreleasePoolPop(pool);
		return;
	}




	for (id object in self)
		[object setValue: value
			  forKey: key];
}

- (size_t)indexOfObject: (id)object
{
448
449
450
451
452
453
454

455

456






457
458
459
460
461
462
463
464
465



466
467
468
469
470
471
472
473
474
475
476
477
478





479
480
481
482
483
484
485
486
487
488
489
490
491
492
	OFMutableString *ret;

	if (separator == nil)
		@throw [OFInvalidArgumentException exception];

	if ([self count] == 0)
		return @"";

	if ([self count] == 1)

		return [[self firstObject] performSelector: selector];







	ret = [OFMutableString string];

	if (options & OF_ARRAY_SKIP_EMPTY) {
		for (id object in self) {
			void *pool = objc_autoreleasePoolPush();
			OFString *component =
			    [object performSelector: selector];




			if ([component length] > 0) {
				if ([ret length] > 0)
					[ret appendString: separator];
				[ret appendString: component];
			}

			objc_autoreleasePoolPop(pool);
		}
	} else {
		bool first = true;

		for (id object in self) {
			void *pool = objc_autoreleasePoolPush();






			if OF_UNLIKELY (first)
				first = false;
			else
				[ret appendString: separator];

			[ret appendString: [object performSelector: selector]];

			objc_autoreleasePoolPop(pool);
		}
	}

	[ret makeImmutable];








>
|
>
|
>
>
>
>
>
>









>
>
>













>
>
>
>
>






|







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
	OFMutableString *ret;

	if (separator == nil)
		@throw [OFInvalidArgumentException exception];

	if ([self count] == 0)
		return @"";

	if ([self count] == 1) {
		OFString *component =
		    [[self firstObject] performSelector: selector];

		if (component == nil)
			@throw [OFInvalidArgumentException exception];

		return component;
	}

	ret = [OFMutableString string];

	if (options & OF_ARRAY_SKIP_EMPTY) {
		for (id object in self) {
			void *pool = objc_autoreleasePoolPush();
			OFString *component =
			    [object performSelector: selector];

			if (component == nil)
				@throw [OFInvalidArgumentException exception];

			if ([component length] > 0) {
				if ([ret length] > 0)
					[ret appendString: separator];
				[ret appendString: component];
			}

			objc_autoreleasePoolPop(pool);
		}
	} else {
		bool first = true;

		for (id object in self) {
			void *pool = objc_autoreleasePoolPush();
			OFString *component =
			    [object performSelector: selector];

			if (component == nil)
				@throw [OFInvalidArgumentException exception];

			if OF_UNLIKELY (first)
				first = false;
			else
				[ret appendString: separator];

			[ret appendString: component];

			objc_autoreleasePoolPop(pool);
		}
	}

	[ret makeImmutable];

672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
		uint8_t type = 0xDC;
		uint16_t tmp = OF_BSWAP16_IF_LE((uint16_t)count);

		[data addItem: &type];
		[data addItems: &tmp
			 count: sizeof(tmp)];
	} else if (count <= UINT32_MAX) {
		uint8_t type = 0xDC;
		uint32_t tmp = OF_BSWAP32_IF_LE((uint32_t)count);

		[data addItem: &type];
		[data addItems: &tmp
			 count: sizeof(tmp)];
	} else
		@throw [OFOutOfRangeException exception];







|







684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
		uint8_t type = 0xDC;
		uint16_t tmp = OF_BSWAP16_IF_LE((uint16_t)count);

		[data addItem: &type];
		[data addItems: &tmp
			 count: sizeof(tmp)];
	} else if (count <= UINT32_MAX) {
		uint8_t type = 0xDD;
		uint32_t tmp = OF_BSWAP32_IF_LE((uint32_t)count);

		[data addItem: &type];
		[data addItems: &tmp
			 count: sizeof(tmp)];
	} else
		@throw [OFOutOfRangeException exception];
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
	for (id object in self)
		[object performSelector: selector];
}

- (void)makeObjectsPerformSelector: (SEL)selector
			withObject: (id)object
{
	for (id object in self)
		[object performSelector: selector
			     withObject: object];
}

- (OFArray *)sortedArray
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new sort];







|
|
|







727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
	for (id object in self)
		[object performSelector: selector];
}

- (void)makeObjectsPerformSelector: (SEL)selector
			withObject: (id)object
{
	for (id objectIter in self)
		[objectIter performSelector: selector
				 withObject: object];
}

- (OFArray *)sortedArray
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new sort];
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
{
	OFArray *ret;
	size_t count = [self count];
	id *tmp = [self allocMemoryWithSize: sizeof(id)
				      count: count];

	@try {
		[self enumerateObjectsUsingBlock: ^ (id object, size_t index,
		    bool *stop) {
			tmp[index] = block(object, index);
		}];

		ret = [OFArray arrayWithObjects: tmp
					  count: count];
	} @finally {
		[self freeMemory: tmp];
	}







|

|







855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
{
	OFArray *ret;
	size_t count = [self count];
	id *tmp = [self allocMemoryWithSize: sizeof(id)
				      count: count];

	@try {
		[self enumerateObjectsUsingBlock: ^ (id object, size_t idx,
		    bool *stop) {
			tmp[idx] = block(object, idx);
		}];

		ret = [OFArray arrayWithObjects: tmp
					  count: count];
	} @finally {
		[self freeMemory: tmp];
	}
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
	size_t count = [self count];
	id *tmp = [self allocMemoryWithSize: sizeof(id)
				      count: count];

	@try {
		__block size_t i = 0;

		[self enumerateObjectsUsingBlock: ^ (id object, size_t index,
		    bool *stop) {
			if (block(object, index))
				tmp[i++] = object;
		}];

		ret = [OFArray arrayWithObjects: tmp
					  count: i];
	} @finally {
		[self freeMemory: tmp];







|

|







879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
	size_t count = [self count];
	id *tmp = [self allocMemoryWithSize: sizeof(id)
				      count: count];

	@try {
		__block size_t i = 0;

		[self enumerateObjectsUsingBlock: ^ (id object, size_t idx,
		    bool *stop) {
			if (block(object, idx))
				tmp[i++] = object;
		}];

		ret = [OFArray arrayWithObjects: tmp
					  count: i];
	} @finally {
		[self freeMemory: tmp];
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
	__block id current;

	if (count == 0)
		return nil;
	if (count == 1)
		return [[[self firstObject] retain] autorelease];

	[self enumerateObjectsUsingBlock: ^ (id object, size_t index,
	    bool *stop) {
		id new;

		if (index == 0) {
			current = [object retain];
			return;
		}

		@try {
			new = [block(current, object) retain];
		} @finally {







|



|







904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
	__block id current;

	if (count == 0)
		return nil;
	if (count == 1)
		return [[[self firstObject] retain] autorelease];

	[self enumerateObjectsUsingBlock: ^ (id object, size_t idx,
	    bool *stop) {
		id new;

		if (idx == 0) {
			current = [object retain];
			return;
		}

		@try {
			new = [block(current, object) retain];
		} @finally {

Modified src/OFArray_adjacent.m from [45617fcf1b] to [8dbc96bba7].

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
}

- (id const *)objects
{
	return [_array items];
}

- (id)objectAtIndex: (size_t)index
{
	return *((id *)[_array itemAtIndex: index]);
}

- (id)objectAtIndexedSubscript: (size_t)index
{
	return *((id *)[_array itemAtIndex: index]);
}

- (void)getObjects: (id *)buffer
	   inRange: (of_range_t)range
{
	id *objects = [_array items];
	size_t count = [_array count];







|

|


|

|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
}

- (id const *)objects
{
	return [_array items];
}

- (id)objectAtIndex: (size_t)idx
{
	return *((id *)[_array itemAtIndex: idx]);
}

- (id)objectAtIndexedSubscript: (size_t)idx
{
	return *((id *)[_array itemAtIndex: idx]);
}

- (void)getObjects: (id *)buffer
	   inRange: (of_range_t)range
{
	id *objects = [_array items];
	size_t count = [_array count];

Modified src/OFArray_subarray.m from [b087bc3ca0] to [02a02cd5d6].

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
}

- (size_t)count
{
	return _range.length;
}

- (id)objectAtIndex: (size_t)index
{
	if (index >= _range.length)
		@throw [OFOutOfRangeException exception];

	return [_array objectAtIndex: index + _range.location];
}

- (void)getObjects: (id *)buffer
	   inRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _range.length)
		@throw [OFOutOfRangeException exception];

	range.location += _range.location;

	[_array getObjects: buffer
		   inRange: range];
}

- (size_t)indexOfObject: (id)object
{
	size_t index = [_array indexOfObject: object];

	if (index < _range.location)
		return OF_NOT_FOUND;

	index -= _range.location;

	if (index >= _range.length)
		return OF_NOT_FOUND;

	return index;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	size_t index = [_array indexOfObjectIdenticalTo: object];

	if (index < _range.location)
		return OF_NOT_FOUND;

	index -= _range.location;

	if (index >= _range.length)
		return OF_NOT_FOUND;

	return index;
}

- (OFArray *)objectsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _range.length)
		@throw [OFOutOfRangeException exception];

	range.location += _range.location;

	return [_array objectsInRange: range];
}
@end







|

|


|

















|

|


|

|


|




|

|


|

|


|













53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
}

- (size_t)count
{
	return _range.length;
}

- (id)objectAtIndex: (size_t)idx
{
	if (idx >= _range.length)
		@throw [OFOutOfRangeException exception];

	return [_array objectAtIndex: idx + _range.location];
}

- (void)getObjects: (id *)buffer
	   inRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _range.length)
		@throw [OFOutOfRangeException exception];

	range.location += _range.location;

	[_array getObjects: buffer
		   inRange: range];
}

- (size_t)indexOfObject: (id)object
{
	size_t idx = [_array indexOfObject: object];

	if (idx < _range.location)
		return OF_NOT_FOUND;

	idx -= _range.location;

	if (idx >= _range.length)
		return OF_NOT_FOUND;

	return idx;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	size_t idx = [_array indexOfObjectIdenticalTo: object];

	if (idx < _range.location)
		return OF_NOT_FOUND;

	idx -= _range.location;

	if (idx >= _range.length)
		return OF_NOT_FOUND;

	return idx;
}

- (OFArray *)objectsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _range.length)
		@throw [OFOutOfRangeException exception];

	range.location += _range.location;

	return [_array objectsInRange: range];
}
@end

Modified src/OFCollection.h from [443478d52e] to [835760a641].

34
35
36
37
38
39
40
41
42
43
44
/*!
 * @brief Checks whether the collection contains an object equal to the
 *	  specified object.
 *
 * @param object The object which is checked for being in the collection
 * @return A boolean whether the collection contains the specified object
 */
- (bool)containsObject: (nullable id)object;
@end

OF_ASSUME_NONNULL_END







|



34
35
36
37
38
39
40
41
42
43
44
/*!
 * @brief Checks whether the collection contains an object equal to the
 *	  specified object.
 *
 * @param object The object which is checked for being in the collection
 * @return A boolean whether the collection contains the specified object
 */
- (bool)containsObject: (id)object;
@end

OF_ASSUME_NONNULL_END

Modified src/OFConstantString.m from [a025049426] to [e45b7abf06].

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
@implementation OFConstantString
+ (void)load
{
#if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
	/*
	 * objc_setFutureClass suddenly stopped working as OFConstantString
	 * became more complex. So the only solution is to make
	 * _OFConstantStringClassRerence the actual class, but there is no
	 * objc_initializeClassPair in 10.5. However, objc_allocateClassPair
	 * does not register the new class with the subclass in the ObjC1
	 * runtime like the ObjC2 runtime does, so this workaround should be
	 * fine.
	 */
	Class class;








|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
@implementation OFConstantString
+ (void)load
{
#if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
	/*
	 * objc_setFutureClass suddenly stopped working as OFConstantString
	 * became more complex. So the only solution is to make
	 * _OFConstantStringClassReference the actual class, but there is no
	 * objc_initializeClassPair in 10.5. However, objc_allocateClassPair
	 * does not register the new class with the subclass in the ObjC1
	 * runtime like the ObjC2 runtime does, so this workaround should be
	 * fine.
	 */
	Class class;

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
- (of_comparison_result_t)caseInsensitiveCompare: (OFString *)otherString
{
	[self finishInitialization];

	return [self caseInsensitiveCompare: otherString];
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	[self finishInitialization];

	return [self characterAtIndex: index];
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range
{
	[self finishInitialization];








|



|







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
- (of_comparison_result_t)caseInsensitiveCompare: (OFString *)otherString
{
	[self finishInitialization];

	return [self caseInsensitiveCompare: otherString];
}

- (of_unichar_t)characterAtIndex: (size_t)idx
{
	[self finishInitialization];

	return [self characterAtIndex: idx];
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range
{
	[self finishInitialization];

Modified src/OFData.h from [ef14e3ba64] to [9086a3be08].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *
 * For security reasons, serialization and deserialization is only implemented
 * for OFData with item size 1.
 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFSerialization, OFMessagePackRepresentation>
{
	char *_items;
	size_t _count, _itemSize;
	bool _freeWhenDone;
}

/*!
 * The size of a single item in the OFData in bytes.
 */







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *
 * For security reasons, serialization and deserialization is only implemented
 * for OFData with item size 1.
 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFSerialization, OFMessagePackRepresentation>
{
	unsigned char *_items;
	size_t _count, _itemSize;
	bool _freeWhenDone;
}

/*!
 * The size of a single item in the OFData in bytes.
 */

Modified src/OFData.m from [ab1e932258] to [cb311cd255].

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = (char *)items;
		_itemSize = itemSize;
		_count = count;
		_freeWhenDone = freeWhenDone;
	} @catch (id e) {
		[self release];
		@throw e;
	}







|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = (unsigned char *)items;
		_itemSize = itemSize;
		_count = count;
		_freeWhenDone = freeWhenDone;
	} @catch (id e) {
		[self release];
		@throw e;
	}
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
}

- (const void *)items
{
	return _items;
}

- (const void *)itemAtIndex: (size_t)index
{
	if (index >= _count)
		@throw [OFOutOfRangeException exception];

	return _items + index * _itemSize;
}

- (const void *)firstItem
{
	if (_items == NULL || _count == 0)
		return NULL;








|

|


|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
}

- (const void *)items
{
	return _items;
}

- (const void *)itemAtIndex: (size_t)idx
{
	if (idx >= _count)
		@throw [OFOutOfRangeException exception];

	return _items + idx * _itemSize;
}

- (const void *)firstItem
{
	if (_items == NULL || _count == 0)
		return NULL;

Modified src/OFDate.h from [7c2a95ab3f] to [29c60ccceb].

184
185
186
187
188
189
190







191
192
193
194
195
196
197
/*!
 * @brief Returns the minute of the date.
 *
 * @return The minute of the date
 */
- (uint8_t)minute;








/*!
 * @brief Returns the hour of the date.
 *
 * @return The hour of the date
 */
- (uint8_t)hour;








>
>
>
>
>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*!
 * @brief Returns the minute of the date.
 *
 * @return The minute of the date
 */
- (uint8_t)minute;

/*!
 * @brief Returns the minute of the date in local time.
 *
 * @return The minute of the date in local time
 */
- (uint8_t)localMinute;

/*!
 * @brief Returns the hour of the date.
 *
 * @return The hour of the date
 */
- (uint8_t)hour;

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
 * @brief Returns the earlier of the two dates.
 *
 * If the argument is `nil`, it returns the receiver.
 *
 * @param otherDate Another date
 * @return The earlier date of the two dates
 */
- (OFDate *)earlierDate: (OFDate *)otherDate;

/*!
 * @brief Returns the later of the two dates.
 *
 * If the argument is `nil`, it returns the receiver.
 *
 * @param otherDate Another date
 * @return The later date of the two dates
 */
- (OFDate *)laterDate: (OFDate *)otherDate;

/*!
 * @brief Returns the seconds since 1970-01-01T00:00:00Z.
 *
 * @return The seconds since 1970-01-01T00:00:00Z
 */
- (of_time_interval_t)timeIntervalSince1970;







|









|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
 * @brief Returns the earlier of the two dates.
 *
 * If the argument is `nil`, it returns the receiver.
 *
 * @param otherDate Another date
 * @return The earlier date of the two dates
 */
- (OFDate *)earlierDate: (nullable OFDate *)otherDate;

/*!
 * @brief Returns the later of the two dates.
 *
 * If the argument is `nil`, it returns the receiver.
 *
 * @param otherDate Another date
 * @return The later date of the two dates
 */
- (OFDate *)laterDate: (nullable OFDate *)otherDate;

/*!
 * @brief Returns the seconds since 1970-01-01T00:00:00Z.
 *
 * @return The seconds since 1970-01-01T00:00:00Z
 */
- (of_time_interval_t)timeIntervalSince1970;

Modified src/OFDate.m from [388aebd154] to [618922b043].

449
450
451
452
453
454
455





456
457
458
459
460
461
462
	GMTIME_RET(tm_sec)
}

- (uint8_t)minute
{
	GMTIME_RET(tm_min)
}






- (uint8_t)hour
{
	GMTIME_RET(tm_hour)
}

- (uint8_t)localHour







>
>
>
>
>







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
	GMTIME_RET(tm_sec)
}

- (uint8_t)minute
{
	GMTIME_RET(tm_min)
}

- (uint8_t)localMinute
{
	LOCALTIME_RET(tm_min)
}

- (uint8_t)hour
{
	GMTIME_RET(tm_hour)
}

- (uint8_t)localHour

Modified src/OFDictionary.h from [cf57ae790d] to [085a75867d].

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
 * If the key does not start with an `@`, this is equivalent to
 * @ref setObject:forKey:. In this case, if the dictionary is immutable, an
 * @ref OFUndefinedKeyException is thrown.
 *
 * @param key The key to set
 * @param value The value to set the key to
 */
- (void)setValue: (nullable id)value
	  forKey: (OFString *)key;

/*!
 * @brief Checks whether the dictionary contains an object equal to the
 *	  specified object.
 *
 * @param object The object which is checked for being in the dictionary
 * @return A boolean whether the dictionary contains the specified object
 */
- (bool)containsObject: (nullable ObjectType)object;

/*!
 * @brief Checks whether the dictionary contains an object with the specified
 *	  address.
 *
 * @param object The object which is checked for being in the dictionary
 * @return A boolean whether the dictionary contains an object with the
 *	   specified address
 */
- (bool)containsObjectIdenticalTo: (nullable ObjectType)object;

/*!
 * @brief Returns an array of all keys.
 *
 * @return An array of all keys
 */
- (OFArray OF_GENERIC(KeyType) *)allKeys;







|









|









|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
 * If the key does not start with an `@`, this is equivalent to
 * @ref setObject:forKey:. In this case, if the dictionary is immutable, an
 * @ref OFUndefinedKeyException is thrown.
 *
 * @param key The key to set
 * @param value The value to set the key to
 */
- (void)setValue: (id)value
	  forKey: (OFString *)key;

/*!
 * @brief Checks whether the dictionary contains an object equal to the
 *	  specified object.
 *
 * @param object The object which is checked for being in the dictionary
 * @return A boolean whether the dictionary contains the specified object
 */
- (bool)containsObject: (ObjectType)object;

/*!
 * @brief Checks whether the dictionary contains an object with the specified
 *	  address.
 *
 * @param object The object which is checked for being in the dictionary
 * @return A boolean whether the dictionary contains an object with the
 *	   specified address
 */
- (bool)containsObjectIdenticalTo: (ObjectType)object;

/*!
 * @brief Returns an array of all keys.
 *
 * @return An array of all keys
 */
- (OFArray OF_GENERIC(KeyType) *)allKeys;

Modified src/OFFile.m from [afef5a8ffe] to [44dc0ec6b9].

130
131
132
133
134
135
136


137
138
139
140




141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
static int
parseMode(const char *mode, bool *append)
{
	*append = false;

	if (strcmp(mode, "r") == 0)
		return MODE_OLDFILE;


	if (strcmp(mode, "w") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "wx") == 0)
		return MODE_NEWFILE;




	if (strcmp(mode, "a") == 0) {
		*append = true;
		return MODE_READWRITE;
	}
	if (strcmp(mode, "rb") == 0)
		return MODE_OLDFILE;
	if (strcmp(mode, "wb") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "wbx") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "ab") == 0) {
		*append = true;
		return MODE_READWRITE;
	}
	if (strcmp(mode, "r+") == 0)
		return MODE_OLDFILE;
	if (strcmp(mode, "w+") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "a+") == 0) {
		*append = true;
		return MODE_READWRITE;
	}
	if (strcmp(mode, "r+b") == 0 || strcmp(mode, "rb+") == 0)
		return MODE_OLDFILE;
	if (strcmp(mode, "w+b") == 0 || strcmp(mode, "wb+") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "w+bx") == 0 || strcmp(mode, "wb+x") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) {
		*append = true;
		return MODE_READWRITE;
	}

	return -1;
}
#endif








>
>




>
>
>
>




<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
<
<







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150














151
152










153
154
155
156
157
158
159
static int
parseMode(const char *mode, bool *append)
{
	*append = false;

	if (strcmp(mode, "r") == 0)
		return MODE_OLDFILE;
	if (strcmp(mode, "r+") == 0)
		return MODE_OLDFILE;
	if (strcmp(mode, "w") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "wx") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "w+") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "w+x") == 0)
		return MODE_NEWFILE;
	if (strcmp(mode, "a") == 0) {
		*append = true;
		return MODE_READWRITE;
	}














	if (strcmp(mode, "a+") == 0) {
		*append = true;










		return MODE_READWRITE;
	}

	return -1;
}
#endif

Modified src/OFFileManager.m from [7bb3d63d81] to [f7096a9a7b].

569
570
571
572
573
574
575

576
577
578
579
580
581
582
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: errno];

			if (dirent == NULL)
				break;
# else

			if ((dirent = readdir(dir)) == NULL) {
				if (errno == 0)
					break;
				else
					@throw [OFReadFailedException
					    exceptionWithObject: self
						requestedLength: 0







>







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: errno];

			if (dirent == NULL)
				break;
# else
			errno = 0;
			if ((dirent = readdir(dir)) == NULL) {
				if (errno == 0)
					break;
				else
					@throw [OFReadFailedException
					    exceptionWithObject: self
						requestedLength: 0

Modified src/OFGZIPStream.h from [9ece715a6e] to [5bd0cee2bc].

17
18
19
20
21
22
23






24
25
26
27
28
29
30
31
32
33
34
#import "OFStream.h"
#import "OFDate.h"

@class OFInflateStream;

OF_ASSUME_NONNULL_BEGIN







@interface OFGZIPStream: OFStream
{
	OFStream *_stream;
	OFInflateStream *_inflateStream;
	enum of_gzip_stream_state {
		OF_GZIP_STREAM_ID1,
		OF_GZIP_STREAM_ID2,
		OF_GZIP_STREAM_COMPRESSION_METHOD,
		OF_GZIP_STREAM_FLAGS,
		OF_GZIP_STREAM_MODIFICATION_TIME,
		OF_GZIP_STREAM_EXTRA_FLAGS,







>
>
>
>
>
>



|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#import "OFStream.h"
#import "OFDate.h"

@class OFInflateStream;

OF_ASSUME_NONNULL_BEGIN

/*!
 * @class OFGZIPStream OFGZIPStream.h ObjFW/OFGZIPStream.h
 *
 * @brief A class that handles GZIP compression and decompression transparently
 *	  for an underlying stream.
 */
@interface OFGZIPStream: OFStream
{
	OFStream *_stream;
	OFInflateStream *_Nullable _inflateStream;
	enum of_gzip_stream_state {
		OF_GZIP_STREAM_ID1,
		OF_GZIP_STREAM_ID2,
		OF_GZIP_STREAM_COMPRESSION_METHOD,
		OF_GZIP_STREAM_FLAGS,
		OF_GZIP_STREAM_MODIFICATION_TIME,
		OF_GZIP_STREAM_EXTRA_FLAGS,
65
66
67
68
69
70
71
72
73
74
75
76






77

78








79
80
81
82
		OF_GZIP_STREAM_OS_NTFS	       =  11,
		OF_GZIP_STREAM_OS_QDOS	       =  12,
		OF_GZIP_STREAM_OS_ACORN_RISCOS =  13,
		OF_GZIP_STREAM_OS_UNKNOWN      = 255
	} _OS;
	size_t _bytesRead;
	uint8_t _buffer[4];
	OFDate *_modificationDate;
	uint16_t _extraLength;
	uint32_t _CRC32, _uncompressedSize;
}







+ (instancetype)streamWithStream: (OFStream *)stream;

- init OF_UNAVAILABLE;








- initWithStream: (OFStream *)stream OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END







|




>
>
>
>
>
>

>

>
>
>
>
>
>
>
>




71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
		OF_GZIP_STREAM_OS_NTFS	       =  11,
		OF_GZIP_STREAM_OS_QDOS	       =  12,
		OF_GZIP_STREAM_OS_ACORN_RISCOS =  13,
		OF_GZIP_STREAM_OS_UNKNOWN      = 255
	} _OS;
	size_t _bytesRead;
	uint8_t _buffer[4];
	OFDate *_Nullable _modificationDate;
	uint16_t _extraLength;
	uint32_t _CRC32, _uncompressedSize;
}

/*!
 * @brief Creates a new OFGZIPStream with the specified underlying stream.
 *
 * @param stream The underlying stream for the OFGZIPStream
 * @return A new, autoreleased OFGZIPStream
 */
+ (instancetype)streamWithStream: (OFStream *)stream;

- init OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated OFGZIPStream with the specified
 *	  underlying stream.
 *
 * @param stream The underlying stream for the OFGZIPStream
 * @return An initialized OFGZIPStream
 */
- initWithStream: (OFStream *)stream OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHMAC.h from [78bbd3d482] to [10fea24a9c].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * @class OFHMAC OFHMAC.h ObjFW/OFHMAC.h
 *
 * @brief A class which provides methods to calculate an HMAC.
 */
@interface OFHMAC: OFObject
{
	Class <OFCryptoHash> _hashClass;
	id <OFCryptoHash> _outerHash, _innerHash;
	id <OFCryptoHash> _outerHashCopy, _innerHashCopy;
	bool _calculated;
}

/*! The class for the cryptographic hash used by the HMAC. */
@property (readonly, nonatomic) Class <OFCryptoHash> hashClass;

/*!







|
|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * @class OFHMAC OFHMAC.h ObjFW/OFHMAC.h
 *
 * @brief A class which provides methods to calculate an HMAC.
 */
@interface OFHMAC: OFObject
{
	Class <OFCryptoHash> _hashClass;
	id <OFCryptoHash> _Nullable _outerHash, _innerHash;
	id <OFCryptoHash> _Nullable _outerHashCopy, _innerHashCopy;
	bool _calculated;
}

/*! The class for the cryptographic hash used by the HMAC. */
@property (readonly, nonatomic) Class <OFCryptoHash> hashClass;

/*!

Modified src/OFHTTPClient.h from [a366523288] to [cd3656efe4].

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*!
 * @class OFHTTPClient OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A class for performing HTTP requests.
 */
@interface OFHTTPClient: OFObject
{
	id <OFHTTPClientDelegate> _delegate;
	bool _insecureRedirectsAllowed;
	OFTCPSocket *_socket;
	OFURL *_lastURL;
	bool _lastWasHEAD;
	OFHTTPResponse *_lastResponse;
}

/*!
 * The delegate of the HTTP request.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, assign)
    id <OFHTTPClientDelegate> delegate;







|

|
|

|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*!
 * @class OFHTTPClient OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A class for performing HTTP requests.
 */
@interface OFHTTPClient: OFObject
{
	id <OFHTTPClientDelegate> _Nullable _delegate;
	bool _insecureRedirectsAllowed;
	OFTCPSocket *_Nullable _socket;
	OFURL *_Nullable _lastURL;
	bool _lastWasHEAD;
	OFHTTPResponse *_Nullable _lastResponse;
}

/*!
 * The delegate of the HTTP request.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, assign)
    id <OFHTTPClientDelegate> delegate;

Modified src/OFHTTPClient.m from [29b75ba101] to [0843f75aca].

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	OFTCPSocket *_socket;
	bool _hasContentLength, _chunked, _keepAlive, _atEndOfStream;
	size_t _toRead;
}

@property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive;

- initWithSocket: (OFTCPSocket *)socket;
@end

@implementation OFHTTPClientResponse
@synthesize of_keepAlive = _keepAlive;

- initWithSocket: (OFTCPSocket *)socket
{
	self = [super init];

	_socket = [socket retain];

	return self;
}

- (void)dealloc
{
	[_socket release];







|





|



|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	OFTCPSocket *_socket;
	bool _hasContentLength, _chunked, _keepAlive, _atEndOfStream;
	size_t _toRead;
}

@property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive;

- initWithSocket: (OFTCPSocket *)sock;
@end

@implementation OFHTTPClientResponse
@synthesize of_keepAlive = _keepAlive;

- initWithSocket: (OFTCPSocket *)sock
{
	self = [super init];

	_socket = [sock retain];

	return self;
}

- (void)dealloc
{
	[_socket release];
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
	return [self performRequest: request
			  redirects: 10];
}

- (OFTCPSocket *)of_closeAndCreateSocketForRequest: (OFHTTPRequest *)request
{
	OFURL *URL = [request URL];
	OFTCPSocket *socket;

	[self close];

	if ([[URL scheme] isEqual: @"https"]) {
		if (of_tls_socket_class == Nil)
			@throw [OFUnsupportedProtocolException
			    exceptionWithURL: URL];

		socket = [[[of_tls_socket_class alloc] init]
		    autorelease];
	} else
		socket = [OFTCPSocket socket];

	if ([_delegate respondsToSelector:
	    @selector(client:didCreateSocket:request:)])
		[_delegate client: self
		  didCreateSocket: socket
			  request: request];

	[socket connectToHost: [URL host]
			 port: [URL port]];

	return socket;
}

- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request
			 redirects: (size_t)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [request URL];
	OFString *scheme = [URL scheme];
	of_http_request_method_t method = [request method];
	OFString *path;
	OFMutableString *requestString;
	OFString *user, *password;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	OFData *body = [request body];
	OFTCPSocket *socket;
	OFHTTPClientResponse *response;
	OFString *line, *version, *redirect, *connectionHeader;
	bool keepAlive;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *serverHeaders;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFString *key, *object;
	int status;

	if (![scheme isEqual: @"http"] && ![scheme isEqual: @"https"])
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];

	/* Can we reuse the socket? */
	if (_socket != nil && [[_lastURL scheme] isEqual: scheme] &&
	    [[_lastURL host] isEqual: [URL host]] &&
	    [_lastURL port] == [URL port]) {
		/*
		 * Set _socket to nil, so that in case of an error it won't be
		 * reused. If everything is successful, we set _socket again
		 * at the end.
		 */
		socket = [_socket autorelease];
		_socket = nil;

		[_lastURL release];
		_lastURL = nil;

		@try {
			if (!_lastWasHEAD) {







|








|
<

|




|


|
|

|














|




















|







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
	return [self performRequest: request
			  redirects: 10];
}

- (OFTCPSocket *)of_closeAndCreateSocketForRequest: (OFHTTPRequest *)request
{
	OFURL *URL = [request URL];
	OFTCPSocket *sock;

	[self close];

	if ([[URL scheme] isEqual: @"https"]) {
		if (of_tls_socket_class == Nil)
			@throw [OFUnsupportedProtocolException
			    exceptionWithURL: URL];

		sock = [[[of_tls_socket_class alloc] init] autorelease];

	} else
		sock = [OFTCPSocket socket];

	if ([_delegate respondsToSelector:
	    @selector(client:didCreateSocket:request:)])
		[_delegate client: self
		  didCreateSocket: sock
			  request: request];

	[sock connectToHost: [URL host]
		       port: [URL port]];

	return sock;
}

- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request
			 redirects: (size_t)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [request URL];
	OFString *scheme = [URL scheme];
	of_http_request_method_t method = [request method];
	OFString *path;
	OFMutableString *requestString;
	OFString *user, *password;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	OFData *body = [request body];
	OFTCPSocket *sock;
	OFHTTPClientResponse *response;
	OFString *line, *version, *redirect, *connectionHeader;
	bool keepAlive;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *serverHeaders;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFString *key, *object;
	int status;

	if (![scheme isEqual: @"http"] && ![scheme isEqual: @"https"])
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];

	/* Can we reuse the socket? */
	if (_socket != nil && [[_lastURL scheme] isEqual: scheme] &&
	    [[_lastURL host] isEqual: [URL host]] &&
	    [_lastURL port] == [URL port]) {
		/*
		 * Set _socket to nil, so that in case of an error it won't be
		 * reused. If everything is successful, we set _socket again
		 * at the end.
		 */
		sock = [_socket autorelease];
		_socket = nil;

		[_lastURL release];
		_lastURL = nil;

		@try {
			if (!_lastWasHEAD) {
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
				}
			}
		} @finally {
			[_lastResponse release];
			_lastResponse = nil;
		}
	} else
		socket = [self of_closeAndCreateSocketForRequest: request];

	/*
	 * As a work around for a bug with split packets in lighttpd when using
	 * HTTPS, we construct the complete request in a buffer string and then
	 * send it all at once.
	 *
	 * We do not use the socket's write buffer in case we need to resend







|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
				}
			}
		} @finally {
			[_lastResponse release];
			_lastResponse = nil;
		}
	} else
		sock = [self of_closeAndCreateSocketForRequest: request];

	/*
	 * As a work around for a bug with split packets in lighttpd when using
	 * HTTPS, we construct the complete request in a buffer string and then
	 * send it all at once.
	 *
	 * We do not use the socket's write buffer in case we need to resend
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil)
		[requestString appendFormat: @"%@: %@\r\n", key, object];

	[requestString appendString: @"\r\n"];

	@try {
		[socket writeString: requestString];
	} @catch (OFWriteFailedException *e) {
		if ([e errNo] != ECONNRESET && [e errNo] != EPIPE)
			@throw e;

		/* Reconnect in case a keep-alive connection timed out */
		socket = [self of_closeAndCreateSocketForRequest: request];
		[socket writeString: requestString];
	}

	if (body != nil)
		[socket writeBuffer: [body items]
			     length: [body count] * [body itemSize]];

	@try {
		line = [socket readLine];
	} @catch (OFInvalidEncodingException *e) {
		@throw [OFInvalidServerReplyException exception];
	}

	/*
	 * It's possible that the write succeeds on a connection that is
	 * keep-alive, but the connection has already been closed by the remote
	 * end due to a timeout. In this case, we need to reconnect.
	 */
	if (line == nil) {
		socket = [self of_closeAndCreateSocketForRequest: request];
		[socket writeString: requestString];

		if (body != nil)
			[socket writeBuffer: [body items]
				     length: [body count] *
					     [body itemSize]];

		@try {
			line = [socket readLine];
		} @catch (OFInvalidEncodingException *e) {
			@throw [OFInvalidServerReplyException exception];
		}
	}

	if (![line hasPrefix: @"HTTP/"] || [line length] < 9 ||
	    [line characterAtIndex: 8] != ' ')
		@throw [OFInvalidServerReplyException exception];

	version = [line substringWithRange: of_range(5, 3)];
	if (![version isEqual: @"1.0"] && ![version isEqual: @"1.1"])
		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];

	status = (int)[[line substringWithRange: of_range(9, 3)] decimalValue];

	serverHeaders = [OFMutableDictionary dictionary];

	for (;;) {
		OFString *key, *value, *old;
		const char *lineC, *tmp;
		char *keyC;

		@try {
			line = [socket readLine];
		} @catch (OFInvalidEncodingException *e) {
			@throw [OFInvalidServerReplyException exception];
		}

		if (line == nil)
			@throw [OFInvalidServerReplyException exception];








|





|
|



|
|


|










|
|


|
|
<


|



















|




|







467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil)
		[requestString appendFormat: @"%@: %@\r\n", key, object];

	[requestString appendString: @"\r\n"];

	@try {
		[sock writeString: requestString];
	} @catch (OFWriteFailedException *e) {
		if ([e errNo] != ECONNRESET && [e errNo] != EPIPE)
			@throw e;

		/* Reconnect in case a keep-alive connection timed out */
		sock = [self of_closeAndCreateSocketForRequest: request];
		[sock writeString: requestString];
	}

	if (body != nil)
		[sock writeBuffer: [body items]
			   length: [body count] * [body itemSize]];

	@try {
		line = [sock readLine];
	} @catch (OFInvalidEncodingException *e) {
		@throw [OFInvalidServerReplyException exception];
	}

	/*
	 * It's possible that the write succeeds on a connection that is
	 * keep-alive, but the connection has already been closed by the remote
	 * end due to a timeout. In this case, we need to reconnect.
	 */
	if (line == nil) {
		sock = [self of_closeAndCreateSocketForRequest: request];
		[sock writeString: requestString];

		if (body != nil)
			[sock writeBuffer: [body items]
				   length: [body count] * [body itemSize]];


		@try {
			line = [sock readLine];
		} @catch (OFInvalidEncodingException *e) {
			@throw [OFInvalidServerReplyException exception];
		}
	}

	if (![line hasPrefix: @"HTTP/"] || [line length] < 9 ||
	    [line characterAtIndex: 8] != ' ')
		@throw [OFInvalidServerReplyException exception];

	version = [line substringWithRange: of_range(5, 3)];
	if (![version isEqual: @"1.0"] && ![version isEqual: @"1.1"])
		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];

	status = (int)[[line substringWithRange: of_range(9, 3)] decimalValue];

	serverHeaders = [OFMutableDictionary dictionary];

	for (;;) {
		OFString *value, *old;
		const char *lineC, *tmp;
		char *keyC;

		@try {
			line = [sock readLine];
		} @catch (OFInvalidEncodingException *e) {
			@throw [OFInvalidServerReplyException exception];
		}

		if (line == nil)
			@throw [OFInvalidServerReplyException exception];

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
	if ([_delegate respondsToSelector:
	    @selector(client:didReceiveHeaders:statusCode:request:)])
		[_delegate     client: self
		    didReceiveHeaders: serverHeaders
			   statusCode: status
			      request: request];

	response = [[[OFHTTPClientResponse alloc] initWithSocket: socket]
	    autorelease];
	[response setProtocolVersionFromString: version];
	[response setStatusCode: status];
	[response setHeaders: serverHeaders];

	connectionHeader = [serverHeaders objectForKey: @"Connection"];
	if ([version isEqual: @"1.1"]) {







|







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
	if ([_delegate respondsToSelector:
	    @selector(client:didReceiveHeaders:statusCode:request:)])
		[_delegate     client: self
		    didReceiveHeaders: serverHeaders
			   statusCode: status
			      request: request];

	response = [[[OFHTTPClientResponse alloc] initWithSocket: sock]
	    autorelease];
	[response setProtocolVersionFromString: version];
	[response setStatusCode: status];
	[response setHeaders: serverHeaders];

	connectionHeader = [serverHeaders objectForKey: @"Connection"];
	if ([version isEqual: @"1.1"]) {
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
		else
			keepAlive = false;
	}

	if (keepAlive) {
		[response of_setKeepAlive: true];

		_socket = [socket retain];
		_lastURL = [URL copy];
		_lastWasHEAD = (method == OF_HTTP_REQUEST_METHOD_HEAD);
		_lastResponse = [response retain];
	}

	/* FIXME: Case-insensitive check of redirect's scheme */
	if (redirects > 0 && (status == 301 || status == 302 ||







|







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
		else
			keepAlive = false;
	}

	if (keepAlive) {
		[response of_setKeepAlive: true];

		_socket = [sock retain];
		_lastURL = [URL copy];
		_lastWasHEAD = (method == OF_HTTP_REQUEST_METHOD_HEAD);
		_lastResponse = [response retain];
	}

	/* FIXME: Case-insensitive check of redirect's scheme */
	if (redirects > 0 && (status == 301 || status == 302 ||
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

			/*
			 * 303 means the request should be converted to a GET
			 * request before redirection. This also means stripping
			 * the entity of the request.
			 */
			if (status == 303) {
				OFEnumerator *keyEnumerator, *objectEnumerator;
				id key, object;

				keyEnumerator = [headers keyEnumerator];
				objectEnumerator = [headers objectEnumerator];
				while ((key = [keyEnumerator nextObject]) !=
				    nil &&
				    (object = [objectEnumerator nextObject]) !=
				    nil)
					if ([key hasPrefix: @"Content-"])







<
<
<







665
666
667
668
669
670
671



672
673
674
675
676
677
678

			/*
			 * 303 means the request should be converted to a GET
			 * request before redirection. This also means stripping
			 * the entity of the request.
			 */
			if (status == 303) {



				keyEnumerator = [headers keyEnumerator];
				objectEnumerator = [headers objectEnumerator];
				while ((key = [keyEnumerator nextObject]) !=
				    nil &&
				    (object = [objectEnumerator nextObject]) !=
				    nil)
					if ([key hasPrefix: @"Content-"])

Modified src/OFHTTPCookie.h from [b3a1f16ba1] to [00698eed19].

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h
 *
 * @brief A class for storing and manipulating HTTP cookies.
 */
@interface OFHTTPCookie: OFObject <OFCopying>
{
	OFString *_name, *_value, *_domain, *_path;
	OFDate *_expires;
	bool _secure, _HTTPOnly;
	OFMutableArray OF_GENERIC(OFString *) *_extensions;
}

/*!
 * The name of the cookie.
 */







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h
 *
 * @brief A class for storing and manipulating HTTP cookies.
 */
@interface OFHTTPCookie: OFObject <OFCopying>
{
	OFString *_name, *_value, *_domain, *_path;
	OFDate *_Nullable _expires;
	bool _secure, _HTTPOnly;
	OFMutableArray OF_GENERIC(OFString *) *_extensions;
}

/*!
 * The name of the cookie.
 */

Modified src/OFHTTPRequest.h from [c4ecec1316] to [c06e523cb0].

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * @brief A class for storing HTTP requests.
 */
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFURL *_URL;
	of_http_request_method_t _method;
	of_http_request_protocol_version_t _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_headers;
	OFData *_body;
	OFString *_remoteAddress;
}

/*!
 * The URL of the HTTP request.
 */
@property (nonatomic, copy) OFURL *URL;








|
|
|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 * @brief A class for storing HTTP requests.
 */
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFURL *_URL;
	of_http_request_method_t _method;
	of_http_request_protocol_version_t _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers;
	OFData *_Nullable _body;
	OFString *_Nullable _remoteAddress;
}

/*!
 * The URL of the HTTP request.
 */
@property (nonatomic, copy) OFURL *URL;

Modified src/OFHTTPResponse.h from [96ba448907] to [50360976c1].

38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
 * The status code of the reply to the HTTP request.
 */
@property (nonatomic) short statusCode;

/*!
 * The headers of the reply to the HTTP request.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, copy)
    OFDictionary OF_GENERIC(OFString *, OFString *) *headers;


/*!
 * @brief Sets the protocol version of the HTTP request reply.
 *
 * @param protocolVersion The protocol version of the HTTP request reply
 */
- (void)setProtocolVersion: (of_http_request_protocol_version_t)protocolVersion;







<
|
>







38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
 * The status code of the reply to the HTTP request.
 */
@property (nonatomic) short statusCode;

/*!
 * The headers of the reply to the HTTP request.
 */

@property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *)
    *headers;

/*!
 * @brief Sets the protocol version of the HTTP request reply.
 *
 * @param protocolVersion The protocol version of the HTTP request reply
 */
- (void)setProtocolVersion: (of_http_request_protocol_version_t)protocolVersion;

Modified src/OFHTTPResponse.m from [a696a64757] to [78fcbe257c].

138
139
140
141
142
143
144

145
146





147
148
149
150
151
152
153
@implementation OFHTTPResponse
@synthesize statusCode = _statusCode, headers = _headers;

- init
{
	self = [super init];


	_protocolVersion.major = 1;
	_protocolVersion.minor = 1;






	return self;
}

- (void)dealloc
{
	[_headers release];







>
|
|
>
>
>
>
>







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
@implementation OFHTTPResponse
@synthesize statusCode = _statusCode, headers = _headers;

- init
{
	self = [super init];

	@try {
		_protocolVersion.major = 1;
		_protocolVersion.minor = 1;
		_headers = [[OFDictionary alloc] init];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_headers release];

Modified src/OFHTTPServer.h from [6f778fd782] to [e0793a9509].

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*!
 * @class OFHTTPServer OFHTTPServer.h ObjFW/OFHTTPServer.h
 *
 * @brief A class for creating a simple HTTP server inside of applications.
 */
@interface OFHTTPServer: OFObject
{
	OFString *_host;
	uint16_t _port;
	id <OFHTTPServerDelegate> _delegate;
	OFString *_name;
	OFTCPSocket *_listeningSocket;
}

/*!
 * The host on which the HTTP server will listen.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *host;








|

|
|
|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*!
 * @class OFHTTPServer OFHTTPServer.h ObjFW/OFHTTPServer.h
 *
 * @brief A class for creating a simple HTTP server inside of applications.
 */
@interface OFHTTPServer: OFObject
{
	OFString *_Nullable _host;
	uint16_t _port;
	id <OFHTTPServerDelegate> _Nullable _delegate;
	OFString *_Nullable _name;
	OFTCPSocket *_Nullable _listeningSocket;
}

/*!
 * The host on which the HTTP server will listen.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *host;

Modified src/OFHTTPServer.m from [c477e44d18] to [ae0dbd61af].

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

/*
 * FIXME: Key normalization replaces headers like "DNT" with "Dnt".
 * FIXME: Errors are not reported to the user.
 */

@interface OFHTTPServer ()
- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket
	exception: (OFException *)exception;
@end

static const char *
statusCodeToString(short code)
{







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

/*
 * FIXME: Key normalization replaces headers like "DNT" with "Dnt".
 * FIXME: Errors are not reported to the user.
 */

@interface OFHTTPServer ()
- (bool)of_socket: (OFTCPSocket *)sock
  didAcceptSocket: (OFTCPSocket *)clientSocket
	exception: (OFException *)exception;
@end

static const char *
statusCodeToString(short code)
{
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	OFHTTPRequest *_request;
	bool _chunked, _headersSent;
}

- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server
	 request: (OFHTTPRequest *)request;
@end

@implementation OFHTTPServerResponse
- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server
	 request: (OFHTTPRequest *)request
{
	self = [super init];

	_statusCode = 500;
	_socket = [socket retain];
	_server = [server retain];
	_request = [request retain];

	return self;
}

- (void)dealloc







|





|






|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	OFHTTPRequest *_request;
	bool _chunked, _headersSent;
}

- initWithSocket: (OFTCPSocket *)sock
	  server: (OFHTTPServer *)server
	 request: (OFHTTPRequest *)request;
@end

@implementation OFHTTPServerResponse
- initWithSocket: (OFTCPSocket *)sock
	  server: (OFHTTPServer *)server
	 request: (OFHTTPRequest *)request
{
	self = [super init];

	_statusCode = 500;
	_socket = [sock retain];
	_server = [server retain];
	_request = [request retain];

	return self;
}

- (void)dealloc
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	OFString *_host, *_path;
	uint16_t _port;
	OFMutableDictionary *_headers;
	size_t _contentLength;
	OFMutableData *_body;
}

- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server;
- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line
     exception: (OFException *)exception;
- (bool)parseProlog: (OFString *)line;
- (bool)parseHeaders: (OFString *)line;
-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	  exception: (OFException *)exception;
- (bool)sendErrorAndClose: (short)statusCode;
- (void)createResponse;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server
{
	self = [super init];

	@try {
		_socket = [socket retain];
		_server = [server retain];
		_timer = [[OFTimer
		    scheduledTimerWithTimeInterval: 10
					    target: socket
					  selector: @selector(
							cancelAsyncRequests)
					   repeats: false] retain];
		_state = AWAITING_PROLOG;
	} @catch (id e) {
		[self release];
		@throw e;







|

|




|








|





|



|







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	OFString *_host, *_path;
	uint16_t _port;
	OFMutableDictionary *_headers;
	size_t _contentLength;
	OFMutableData *_body;
}

- initWithSocket: (OFTCPSocket *)sock
	  server: (OFHTTPServer *)server;
- (bool)socket: (OFTCPSocket *)sock
   didReadLine: (OFString *)line
     exception: (OFException *)exception;
- (bool)parseProlog: (OFString *)line;
- (bool)parseHeaders: (OFString *)line;
-      (bool)socket: (OFTCPSocket *)sock
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	  exception: (OFException *)exception;
- (bool)sendErrorAndClose: (short)statusCode;
- (void)createResponse;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket *)sock
	  server: (OFHTTPServer *)server
{
	self = [super init];

	@try {
		_socket = [sock retain];
		_server = [server retain];
		_timer = [[OFTimer
		    scheduledTimerWithTimeInterval: 10
					    target: _socket
					  selector: @selector(
							cancelAsyncRequests)
					   repeats: false] retain];
		_state = AWAITING_PROLOG;
	} @catch (id e) {
		[self release];
		@throw e;
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	[_path release];
	[_headers release];
	[_body release];

	[super dealloc];
}

- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line
     exception: (OFException *)exception
{
	if (line == nil || exception != nil)
		return false;

	@try {







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	[_path release];
	[_headers release];
	[_body release];

	[super dealloc];
}

- (bool)socket: (OFTCPSocket *)sock
   didReadLine: (OFString *)line
     exception: (OFException *)exception
{
	if (line == nil || exception != nil)
		return false;

	@try {
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
			_port = 80;
		}
	}

	return true;
}

-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	  exception: (OFException *)exception
{
	if ([socket isAtEndOfStream] || exception != nil)
		return false;

	[_body addItems: buffer
		  count: length];

	if ([_body count] >= _contentLength) {
		/*







|




|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
			_port = 80;
		}
	}

	return true;
}

-      (bool)socket: (OFTCPSocket *)sock
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	  exception: (OFException *)exception
{
	if ([sock isAtEndOfStream] || exception != nil)
		return false;

	[_body addItems: buffer
		  count: length];

	if ([_body count] >= _contentLength) {
		/*
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket
	exception: (OFException *)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:







|







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (bool)of_socket: (OFTCPSocket *)sock
  didAcceptSocket: (OFTCPSocket *)clientSocket
	exception: (OFException *)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:

Modified src/OFINICategory+Private.h from [59ee9ce154] to [5583b4a433].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;

@interface OFINICategory ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
- (void)of_parseLine: (OFString *)line;
- (bool)of_writeToStream: (OFStream *)stream
		encoding: (of_string_encoding_t)encoding
		   first: (bool)first;
@end

OF_ASSUME_NONNULL_END







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;

@interface OFINICategory ()
- (instancetype)of_initWithName: (OFString *)name OF_METHOD_FAMILY(init);
- (void)of_parseLine: (OFString *)line;
- (bool)of_writeToStream: (OFStream *)stream
		encoding: (of_string_encoding_t)encoding
		   first: (bool)first;
@end

OF_ASSUME_NONNULL_END

Modified src/OFINICategory.m from [77ec98f4c0] to [95cd2a6086].

117
118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
	[super dealloc];
}
@end

@implementation OFINICategory
@synthesize name = _name;

- (instancetype)of_init
{
	self = [super init];

	@try {

		_lines = [[OFMutableArray alloc] init];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







|




>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
	[super dealloc];
}
@end

@implementation OFINICategory
@synthesize name = _name;

- (instancetype)of_initWithName: (OFString *)name
{
	self = [super init];

	@try {
		_name = [name copy];
		_lines = [[OFMutableArray alloc] init];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
		if ([line isKindOfClass: [OFINICategory_Comment class]]) {
			OFINICategory_Comment *comment = line;
			[stream writeFormat: @"%@\r\n", comment->_comment];
		} else if ([line isKindOfClass: [OFINICategory_Pair class]]) {
			OFINICategory_Pair *pair = line;
			OFString *key = escapeString(pair->_key);
			OFString *value = escapeString(pair->_value);
			OFString *line = [OFString
			    stringWithFormat: @"%@=%@\r\n", key, value];

			[stream writeString: line
				   encoding: encoding];
		} else
			@throw [OFInvalidArgumentException exception];
	}

	return true;
}
@end







|


|








506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
		if ([line isKindOfClass: [OFINICategory_Comment class]]) {
			OFINICategory_Comment *comment = line;
			[stream writeFormat: @"%@\r\n", comment->_comment];
		} else if ([line isKindOfClass: [OFINICategory_Pair class]]) {
			OFINICategory_Pair *pair = line;
			OFString *key = escapeString(pair->_key);
			OFString *value = escapeString(pair->_value);
			OFString *tmp = [OFString
			    stringWithFormat: @"%@=%@\r\n", key, value];

			[stream writeString: tmp
				   encoding: encoding];
		} else
			@throw [OFInvalidArgumentException exception];
	}

	return true;
}
@end

Modified src/OFINIFile.m from [5212c0b9d0] to [01663115e7].

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
	void *pool = objc_autoreleasePoolPush();
	OFINICategory *category;

	for (category in _categories)
		if ([[category name] isEqual: name])
			return category;

	category = [[[OFINICategory alloc] of_init] autorelease];
	[category setName: name];
	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}








|
<







100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
	void *pool = objc_autoreleasePoolPush();
	OFINICategory *category;

	for (category in _categories)
		if ([[category name] isEqual: name])
			return category;

	category = [[[OFINICategory alloc] of_initWithName: name] autorelease];

	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
			if (![line hasSuffix: @"]"])
				@throw [OFInvalidFormatException exception];

			categoryName = [line substringWithRange:
			    of_range(1, [line length] - 2)];

			category = [[[OFINICategory alloc]
			    of_init] autorelease];
			[category setName: categoryName];
			[_categories addObject: category];
		} else {
			if (category == nil)
				@throw [OFInvalidFormatException exception];

			[category of_parseLine: line];
		}







<
|







141
142
143
144
145
146
147

148
149
150
151
152
153
154
155
			if (![line hasSuffix: @"]"])
				@throw [OFInvalidFormatException exception];

			categoryName = [line substringWithRange:
			    of_range(1, [line length] - 2)];

			category = [[[OFINICategory alloc]

			    of_initWithName: categoryName] autorelease];
			[_categories addObject: category];
		} else {
			if (category == nil)
				@throw [OFInvalidFormatException exception];

			[category of_parseLine: line];
		}

Modified src/OFInflateStream.h from [2b188fa81c] to [d858471aa3].

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52

53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
#endif
	OFStream *_stream;
	uint8_t _buffer[OF_INFLATE_STREAM_BUFFER_SIZE];
	uint16_t _bufferIndex, _bufferLength;
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	uint8_t *_slidingWindow;
	uint16_t _slidingWindowIndex, _slidingWindowMask;
	int _state;
	union {
		struct {
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {

			struct huffman_tree *litLenTree, *distTree;

			struct huffman_tree *codeLenTree, *treeIter;
			uint8_t *lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {

			struct huffman_tree *litLenTree, *distTree;
			struct huffman_tree *treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}








|











>
|
>
|
|





>
|
|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#endif
	OFStream *_stream;
	uint8_t _buffer[OF_INFLATE_STREAM_BUFFER_SIZE];
	uint16_t _bufferIndex, _bufferLength;
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	uint8_t *_Nullable _slidingWindow;
	uint16_t _slidingWindowIndex, _slidingWindowMask;
	int _state;
	union {
		struct {
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {
			struct huffman_tree *_Nullable litLenTree;
			struct huffman_tree *_Nullable distTree;
			struct huffman_tree *_Nullable codeLenTree;
			struct huffman_tree *_Nullable treeIter;
			uint8_t *_Nullable lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {
			struct huffman_tree *_Nullable litLenTree;
			struct huffman_tree *_Nullable distTree;
			struct huffman_tree *_Nullable treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}

Modified src/OFInflateStream.m from [fc22c7448d] to [93ad641546].

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
				uint16_t j;

				if OF_UNLIKELY (_slidingWindow == NULL)
					@throw [OFInvalidFormatException
					    exception];

				for (j = 0; j < CTX.length; j++) {
					uint16_t index;

					if OF_UNLIKELY (length == 0) {
						CTX.length -= j;
						return bytesWritten;
					}

					index = (_slidingWindowIndex -
					    CTX.distance) & _slidingWindowMask;
					value = _slidingWindow[index];

					buffer[bytesWritten++] = value;
					length--;

					_slidingWindow[_slidingWindowIndex] =
					    value;
					_slidingWindowIndex =







|






|

|







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
				uint16_t j;

				if OF_UNLIKELY (_slidingWindow == NULL)
					@throw [OFInvalidFormatException
					    exception];

				for (j = 0; j < CTX.length; j++) {
					uint16_t idx;

					if OF_UNLIKELY (length == 0) {
						CTX.length -= j;
						return bytesWritten;
					}

					idx = (_slidingWindowIndex -
					    CTX.distance) & _slidingWindowMask;
					value = _slidingWindow[idx];

					buffer[bytesWritten++] = value;
					length--;

					_slidingWindow[_slidingWindowIndex] =
					    value;
					_slidingWindowIndex =

Modified src/OFIntrospection.h from [be287d0416] to [69d1f3e9bd].

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 *
 * @brief A class for describing a property.
 */
@interface OFProperty: OFObject
{
	OFString *_name;
	unsigned _attributes;
	OFString *_getter, *_setter;
}

/*!
 * The name of the property.
 */
@property (readonly, nonatomic) OFString *name;








|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 *
 * @brief A class for describing a property.
 */
@interface OFProperty: OFObject
{
	OFString *_name;
	unsigned _attributes;
	OFString *_Nullable _getter, *_Nullable _setter;
}

/*!
 * The name of the property.
 */
@property (readonly, nonatomic) OFString *name;

Modified src/OFIntrospection.m from [0844281f73] to [b70bed1465].

383
384
385
386
387
388
389



390
391
392
393
394
395
396
397
398
}
#elif defined(OF_APPLE_RUNTIME)
- (instancetype)of_initWithIvar: (Ivar)ivar
{
	self = [super init];

	@try {



		_name = [[OFString alloc]
		    initWithUTF8String: ivar_getName(ivar)];
		_typeEncoding = ivar_getTypeEncoding(ivar);
		_offset = ivar_getOffset(ivar);
	} @catch (id e) {
		[self release];
		@throw e;
	}








>
>
>
|
|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
}
#elif defined(OF_APPLE_RUNTIME)
- (instancetype)of_initWithIvar: (Ivar)ivar
{
	self = [super init];

	@try {
		const char *name = ivar_getName(ivar);

		if (name != NULL)
			_name = [[OFString alloc] initWithUTF8String: name];

		_typeEncoding = ivar_getTypeEncoding(ivar);
		_offset = ivar_getOffset(ivar);
	} @catch (id e) {
		[self release];
		@throw e;
	}

Modified src/OFKernelEventObserver.h from [46bd90f11e] to [25392c4526].

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;
	id <OFKernelEventObserverDelegate> _delegate;
#ifdef OF_HAVE_PIPE
	int _cancelFD[2];
#else
	of_socket_t _cancelFD[2];
	struct sockaddr_in _cancelAddr;
#endif
#ifdef OF_HAVE_THREADS







|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;
	id <OFKernelEventObserverDelegate> _Nullable _delegate;
#ifdef OF_HAVE_PIPE
	int _cancelFD[2];
#else
	of_socket_t _cancelFD[2];
	struct sockaddr_in _cancelAddr;
#endif
#ifdef OF_HAVE_THREADS

Modified src/OFKeyValueCoding.h from [f12732c01d] to [b40de73f7d].

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

/*!
 * @brief Set the value for the specified key
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (nullable id)value
	  forKey: (OFString *)key;

/*!
 * @brief This is called by @ref setValue:forKey: if the specified key does not
 *	  exist.
 *
 * By default, this throws an @ref OFUndefinedKeyException.







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

/*!
 * @brief Set the value for the specified key
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (id)value
	  forKey: (OFString *)key;

/*!
 * @brief This is called by @ref setValue:forKey: if the specified key does not
 *	  exist.
 *
 * By default, this throws an @ref OFUndefinedKeyException.

Modified src/OFList.h from [156b26bb39] to [2bcd2e7a45].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 *
 * @brief A list object.
 *
 * A struct that contains a pointer to the next list object, the previous list
 * object and the object.
 */
struct of_list_object_t {
	/// A pointer to the next list object in the list
	of_list_object_t *next;
	/// A pointer to the previous list object in the list
	of_list_object_t *previous;
	/// The object for the list object
	id __unsafe_unretained object;
};

/*!
 * @class OFList OFList.h ObjFW/OFList.h
 *
 * @brief A class which provides easy to use double-linked lists.
 */
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection,
    OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	of_list_object_t *_firstListObject;
	of_list_object_t *_lastListObject;
	size_t		 _count;
	unsigned long	 _mutations;
}

/*!
 * The first list object of the list.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    of_list_object_t *firstListObject;







|
|
|
|
|














|
|
|
|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 *
 * @brief A list object.
 *
 * A struct that contains a pointer to the next list object, the previous list
 * object and the object.
 */
struct of_list_object_t {
	/*! A pointer to the next list object in the list */
	of_list_object_t *_Nullable next;
	/*! A pointer to the previous list object in the list */
	of_list_object_t *_Nullable previous;
	/*! The object for the list object */
	id __unsafe_unretained object;
};

/*!
 * @class OFList OFList.h ObjFW/OFList.h
 *
 * @brief A class which provides easy to use double-linked lists.
 */
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection,
    OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	of_list_object_t *_Nullable _firstListObject;
	of_list_object_t *_Nullable _lastListObject;
	size_t _count;
	unsigned long  _mutations;
}

/*!
 * The first list object of the list.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    of_list_object_t *firstListObject;
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*!
 * @brief Checks whether the list contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the list
 * @return A boolean whether the list contains the specified object
 */
- (bool)containsObject: (nullable ObjectType)object;

/*!
 * @brief Checks whether the list contains an object with the specified address.
 *
 * @param object The object which is checked for being in the list
 * @return A boolean whether the list contains an object with the specified
 *	   address
 */
- (bool)containsObjectIdenticalTo: (nullable ObjectType)object;

/*!
 * @brief Returns an OFEnumerator to enumerate through all objects of the list.
 *
 * @returns An OFEnumerator to enumerate through all objects of the list
 */
- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator;







|








|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*!
 * @brief Checks whether the list contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the list
 * @return A boolean whether the list contains the specified object
 */
- (bool)containsObject: (ObjectType)object;

/*!
 * @brief Checks whether the list contains an object with the specified address.
 *
 * @param object The object which is checked for being in the list
 * @return A boolean whether the list contains an object with the specified
 *	   address
 */
- (bool)containsObjectIdenticalTo: (ObjectType)object;

/*!
 * @brief Returns an OFEnumerator to enumerate through all objects of the list.
 *
 * @returns An OFEnumerator to enumerate through all objects of the list
 */
- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator;
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# undef ObjectType
#endif
@end

@interface OFListEnumerator: OFEnumerator
{
	OFList		 *_list;
	of_list_object_t *_current;
	unsigned long	 _mutations;
	unsigned long	 *_mutationsPtr;
}

-     initWithList: (OFList *)list
  mutationsPointer: (unsigned long *)mutationsPtr;
@end

OF_ASSUME_NONNULL_END







|
|
|
|







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# undef ObjectType
#endif
@end

@interface OFListEnumerator: OFEnumerator
{
	OFList *_list;
	of_list_object_t *_Nullable _current;
	unsigned long _mutations;
	unsigned long *_Nullable _mutationsPtr;
}

-     initWithList: (OFList *)list
  mutationsPointer: (unsigned long *)mutationsPtr;
@end

OF_ASSUME_NONNULL_END

Modified src/OFLocalization.h from [f635a4f99c] to [68b2b646cf].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*!
 * @class OFLocalization OFLocalization.h ObjFW/OFLocalization.h
 *
 * @brief A class for querying the locale and retrieving localized strings.
 */
@interface OFLocalization: OFObject
{
	OFString *_language;
	OFString *_territory;
	of_string_encoding_t _encoding;
	OFString *_decimalPoint;
	OFMutableArray OF_GENERIC(OFDictionary OF_GENERIC(OFString *, id) *)
	    *_localizedStrings;
}

/**







|
<







32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
/*!
 * @class OFLocalization OFLocalization.h ObjFW/OFLocalization.h
 *
 * @brief A class for querying the locale and retrieving localized strings.
 */
@interface OFLocalization: OFObject
{
	OFString *_Nullable _language, *_Nullable _territory;

	of_string_encoding_t _encoding;
	OFString *_decimalPoint;
	OFMutableArray OF_GENERIC(OFDictionary OF_GENERIC(OFString *, id) *)
	    *_localizedStrings;
}

/**
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 *
 * @warning If you don't use @ref OFApplication, this might be `nil`! In this
 *	    case, you need to manually allocate an instance and call
 *	    @ref init once.
 *
 * @return The shared OFLocalization instance
 */
+ (instancetype)sharedLocalization;

/**
 * @brief Returns the language of the locale.
 *
 * If the language is unknown, `nil` is returned.
 *
 * @return The language of the locale.







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 *
 * @warning If you don't use @ref OFApplication, this might be `nil`! In this
 *	    case, you need to manually allocate an instance and call
 *	    @ref init once.
 *
 * @return The shared OFLocalization instance
 */
+ (nullable instancetype)sharedLocalization;

/**
 * @brief Returns the language of the locale.
 *
 * If the language is unknown, `nil` is returned.
 *
 * @return The language of the locale.
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
+ (of_string_encoding_t)encoding;

/*!
 * @brief Returns the decimal point of the system's locale.
 *
 * @return The decimal point of the system's locale
 */
+ (OFString *)decimalPoint;

#ifdef OF_HAVE_FILES
/*!
 * @brief Adds a directory to scan for language files.
 *
 * @param path The path to the directory to scan for language files
 */







|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
+ (of_string_encoding_t)encoding;

/*!
 * @brief Returns the decimal point of the system's locale.
 *
 * @return The decimal point of the system's locale
 */
+ (nullable OFString *)decimalPoint;

#ifdef OF_HAVE_FILES
/*!
 * @brief Adds a directory to scan for language files.
 *
 * @param path The path to the directory to scan for language files
 */

Modified src/OFLocalization.m from [1e6c9574a4] to [448b3a7501].

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		if (messagesLocale == NULL)
			messagesLocale = locale;

		if (messagesLocale != NULL) {
			void *pool = objc_autoreleasePoolPush();

			parseLocale(messagesLocale, &_encoding,
			    &_language, &_language);

			[_language retain];
			[_territory retain];

			objc_autoreleasePoolPop(pool);
		}
#else







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		if (messagesLocale == NULL)
			messagesLocale = locale;

		if (messagesLocale != NULL) {
			void *pool = objc_autoreleasePoolPush();

			parseLocale(messagesLocale, &_encoding,
			    &_language, &_territory);

			[_language retain];
			[_territory retain];

			objc_autoreleasePoolPop(pool);
		}
#else

Modified src/OFMapTable.h from [9ffd8ae151] to [59f43aca32].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44

/*!
 * @struct of_map_table_functions_t OFMapTable.h ObjFW/OFMapTable.h
 *
 * @brief A struct describing the functions to be used by the map table.
 */
typedef struct {
	/// The function to retain keys / objects
	void *_Nonnull (*_Nullable retain)(void *object);
	/// The function to release keys / objects
	void (*_Nullable release)(void *object);
	/// The function to hash keys
	uint32_t (*_Nullable hash)(void *object);
	/// The function to compare keys / objects
	bool (*_Nullable equal)(void *object1, void *object2);

} of_map_table_functions_t;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief A block for enumerating an OFMapTable.
 *
 * @param key The current key







|
|
|
|
|
|
|
|
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

/*!
 * @struct of_map_table_functions_t OFMapTable.h ObjFW/OFMapTable.h
 *
 * @brief A struct describing the functions to be used by the map table.
 */
typedef struct {
	/*! The function to retain keys / objects */
	void *_Nullable (*_Nullable retain)(void *_Nullable object);
	/*! The function to release keys / objects */
	void (*_Nullable release)(void *_Nullable object);
	/*! The function to hash keys */
	uint32_t (*_Nullable hash)(void *_Nullable object);
	/*! The function to compare keys / objects */
	bool (*_Nullable equal)(void *_Nullable object1,
	    void *_Nullable object2);
} of_map_table_functions_t;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief A block for enumerating an OFMapTable.
 *
 * @param key The current key
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 *
 * @brief A class similar to OFDictionary, but providing more options how keys
 *	  and objects should be retained, released, compared and hashed.
 */
@interface OFMapTable: OFObject <OFCopying, OFFastEnumeration>
{
	of_map_table_functions_t _keyFunctions, _objectFunctions;
	struct of_map_table_bucket **_buckets;
	uint32_t _count, _capacity;
	uint8_t _rotate;
	unsigned long _mutations;
}

/*!
 * The key functions used by the map table.







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 *
 * @brief A class similar to OFDictionary, but providing more options how keys
 *	  and objects should be retained, released, compared and hashed.
 */
@interface OFMapTable: OFObject <OFCopying, OFFastEnumeration>
{
	of_map_table_functions_t _keyFunctions, _objectFunctions;
	struct of_map_table_bucket *_Nonnull *_Nullable _buckets;
	uint32_t _count, _capacity;
	uint8_t _rotate;
	unsigned long _mutations;
}

/*!
 * The key functions used by the map table.
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
 *
 * @brief A class which provides methods to enumerate through an OFMapTable's
 *	  keys or objects.
 */
@interface OFMapTableEnumerator: OFObject
{
	OFMapTable *_mapTable;
	struct of_map_table_bucket **_buckets;
	uint32_t _capacity;
	unsigned long _mutations;
	unsigned long *_mutationsPtr;
	uint32_t _position;
}

- init OF_UNAVAILABLE;

/*!
 * @brief Returns the next object.
 *
 * @return The next object
 */
- (void *)nextObject;

/*!
 * @brief Resets the enumerator, so the next call to @ref nextKey returns the
 *	  first key again.
 */
- (void)reset;
@end

OF_ASSUME_NONNULL_END







|


|










|









234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
 *
 * @brief A class which provides methods to enumerate through an OFMapTable's
 *	  keys or objects.
 */
@interface OFMapTableEnumerator: OFObject
{
	OFMapTable *_mapTable;
	struct of_map_table_bucket *_Nonnull *_Nullable _buckets;
	uint32_t _capacity;
	unsigned long _mutations;
	unsigned long *_Nullable _mutationsPtr;
	uint32_t _position;
}

- init OF_UNAVAILABLE;

/*!
 * @brief Returns the next object.
 *
 * @return The next object
 */
- (nullable void *)nextObject;

/*!
 * @brief Resets the enumerator, so the next call to @ref nextKey returns the
 *	  first key again.
 */
- (void)reset;
@end

OF_ASSUME_NONNULL_END

Modified src/OFMapTable.m from [9a08c57256] to [1517e60617].

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
	if (mapTable->_count != _count ||
	    mapTable->_keyFunctions.equal != _keyFunctions.equal ||
	    mapTable->_objectFunctions.equal != _objectFunctions.equal)
		return false;

	for (uint32_t i = 0; i < _capacity; i++) {
		if (_buckets[i] != NULL && _buckets[i] != &deleted) {
			void *object =
			    [mapTable objectForKey: _buckets[i]->key];

			if (!_objectFunctions.equal(object,
			    _buckets[i]->object))
				return false;
		}
	}

	return true;
}







|


|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
	if (mapTable->_count != _count ||
	    mapTable->_keyFunctions.equal != _keyFunctions.equal ||
	    mapTable->_objectFunctions.equal != _objectFunctions.equal)
		return false;

	for (uint32_t i = 0; i < _capacity; i++) {
		if (_buckets[i] != NULL && _buckets[i] != &deleted) {
			void *objectIter =
			    [mapTable objectForKey: _buckets[i]->key];

			if (!_objectFunctions.equal(objectIter,
			    _buckets[i]->object))
				return false;
		}
	}

	return true;
}

Modified src/OFMutableArray.m from [f7473af41f] to [a54de56242].

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
- (void)addObjectsFromArray: (OFArray *)array
{
	[self insertObjectsFromArray: array
			     atIndex: [self count]];
}

- (void)insertObject: (id)object
	     atIndex: (size_t)index
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)insertObjectsFromArray: (OFArray *)array
		       atIndex: (size_t)index
{
	size_t i = 0;

	for (id object in array)
		[self insertObject: object
			   atIndex: index + i++];
}

- (void)replaceObjectAtIndex: (size_t)index
		  withObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

-    (void)setObject: (id)object
  atIndexedSubscript: (size_t)index
{
	[self replaceObjectAtIndex: index
			withObject: object];
}

- (void)replaceObject: (id)oldObject
	   withObject: (id)newObject
{
	size_t count;







|





|





|


|






|

|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
- (void)addObjectsFromArray: (OFArray *)array
{
	[self insertObjectsFromArray: array
			     atIndex: [self count]];
}

- (void)insertObject: (id)object
	     atIndex: (size_t)idx
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)insertObjectsFromArray: (OFArray *)array
		       atIndex: (size_t)idx
{
	size_t i = 0;

	for (id object in array)
		[self insertObject: object
			   atIndex: idx + i++];
}

- (void)replaceObjectAtIndex: (size_t)idx
		  withObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

-    (void)setObject: (id)object
  atIndexedSubscript: (size_t)idx
{
	[self replaceObjectAtIndex: idx
			withObject: object];
}

- (void)replaceObject: (id)oldObject
	   withObject: (id)newObject
{
	size_t count;
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
					withObject: newObject];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)index
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeObject: (id)object
{
	size_t count;







|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
					withObject: newObject];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)idx
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeObject: (id)object
{
	size_t count;
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
{
	[self removeObjectsInRange: of_range(0, [self count])];
}

#ifdef OF_HAVE_BLOCKS
- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block
{
	[self enumerateObjectsUsingBlock: ^ (id object, size_t index,
	    bool *stop) {
		id new = block(object, index);

		if (new != object)
			[self replaceObjectAtIndex: index
					withObject: new];
	}];
}
#endif

- (void)exchangeObjectAtIndex: (size_t)index1
	    withObjectAtIndex: (size_t)index2
{
	id object1 = [self objectAtIndex: index1];
	id object2 = [self objectAtIndex: index2];

	[object1 retain];
	@try {
		[self replaceObjectAtIndex: index1
				withObject: object2];
		[self replaceObjectAtIndex: index2
				withObject: object1];
	} @finally {
		[object1 release];
	}
}

- (void)sort







|

|


|





|
|

|
|



|

|







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
{
	[self removeObjectsInRange: of_range(0, [self count])];
}

#ifdef OF_HAVE_BLOCKS
- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block
{
	[self enumerateObjectsUsingBlock: ^ (id object, size_t idx,
	    bool *stop) {
		id new = block(object, idx);

		if (new != object)
			[self replaceObjectAtIndex: idx
					withObject: new];
	}];
}
#endif

- (void)exchangeObjectAtIndex: (size_t)idx1
	    withObjectAtIndex: (size_t)idx2
{
	id object1 = [self objectAtIndex: idx1];
	id object2 = [self objectAtIndex: idx2];

	[object1 retain];
	@try {
		[self replaceObjectAtIndex: idx1
				withObject: object2];
		[self replaceObjectAtIndex: idx2
				withObject: object1];
	} @finally {
		[object1 release];
	}
}

- (void)sort

Modified src/OFMutableArray_adjacent.m from [e5a95ab2b1] to [32af0c25d1].

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	[_array addItem: &object];
	[object retain];

	_mutations++;
}

- (void)insertObject: (id)object
	     atIndex: (size_t)index
{
	if (object == nil)
		@throw [OFInvalidArgumentException exception];

	@try {
		[_array insertItem: &object
			   atIndex: index];
	} @catch (OFOutOfRangeException *e) {
		@throw [OFOutOfRangeException exception];
	}
	[object retain];

	_mutations++;
}

- (void)insertObjectsFromArray: (OFArray *)array
		       atIndex: (size_t)index
{
	id const *objects = [array objects];
	size_t count = [array count];

	@try {
		[_array insertItems: objects
			    atIndex: index
			      count: count];
	} @catch (OFOutOfRangeException *e) {
		@throw [OFOutOfRangeException exception];
	}

	for (size_t i = 0; i < count; i++)
		[objects[i] retain];







|






|









|






|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	[_array addItem: &object];
	[object retain];

	_mutations++;
}

- (void)insertObject: (id)object
	     atIndex: (size_t)idx
{
	if (object == nil)
		@throw [OFInvalidArgumentException exception];

	@try {
		[_array insertItem: &object
			   atIndex: idx];
	} @catch (OFOutOfRangeException *e) {
		@throw [OFOutOfRangeException exception];
	}
	[object retain];

	_mutations++;
}

- (void)insertObjectsFromArray: (OFArray *)array
		       atIndex: (size_t)idx
{
	id const *objects = [array objects];
	size_t count = [array count];

	@try {
		[_array insertItems: objects
			    atIndex: idx
			      count: count];
	} @catch (OFOutOfRangeException *e) {
		@throw [OFOutOfRangeException exception];
	}

	for (size_t i = 0; i < count; i++)
		[objects[i] retain];
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
			objects[i] = newObject;

			return;
		}
	}
}

- (void)replaceObjectAtIndex: (size_t)index
		  withObject: (id)object
{
	id *objects;
	id oldObject;

	if (object == nil)
		@throw [OFInvalidArgumentException exception];

	objects = [_array items];

	if (index >= [_array count])
		@throw [OFOutOfRangeException exception];

	oldObject = objects[index];
	objects[index] = [object retain];
	[oldObject release];
}

- (void)replaceObjectIdenticalTo: (id)oldObject
		      withObject: (id)newObject
{
	id *objects;







|










|


|
|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
			objects[i] = newObject;

			return;
		}
	}
}

- (void)replaceObjectAtIndex: (size_t)idx
		  withObject: (id)object
{
	id *objects;
	id oldObject;

	if (object == nil)
		@throw [OFInvalidArgumentException exception];

	objects = [_array items];

	if (idx >= [_array count])
		@throw [OFOutOfRangeException exception];

	oldObject = objects[idx];
	objects[idx] = [object retain];
	[oldObject release];
}

- (void)replaceObjectIdenticalTo: (id)oldObject
		      withObject: (id)newObject
{
	id *objects;
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
			[object release];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)index
{
	id object = [self objectAtIndex: index];
	[_array removeItemAtIndex: index];
	[object release];

	_mutations++;
}

- (void)removeAllObjects
{







|

|
|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
			[object release];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)idx
{
	id object = [self objectAtIndex: idx];
	[_array removeItemAtIndex: idx];
	[object release];

	_mutations++;
}

- (void)removeAllObjects
{
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
	object = [self objectAtIndex: count - 1];
	[_array removeLastItem];
	[object release];

	_mutations++;
}

- (void)exchangeObjectAtIndex: (size_t)index1
	    withObjectAtIndex: (size_t)index2
{
	id *objects = [_array items];
	size_t count = [_array count];
	id tmp;

	if (index1 >= count || index2 >= count)
		@throw [OFOutOfRangeException exception];

	tmp = objects[index1];
	objects[index1] = objects[index2];
	objects[index2] = tmp;
}

- (void)reverse
{
	id *objects = [_array items];
	size_t i, j, count = [_array count];








|
|





|


|
|
|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
	object = [self objectAtIndex: count - 1];
	[_array removeLastItem];
	[object release];

	_mutations++;
}

- (void)exchangeObjectAtIndex: (size_t)idx1
	    withObjectAtIndex: (size_t)idx2
{
	id *objects = [_array items];
	size_t count = [_array count];
	id tmp;

	if (idx1 >= count || idx2 >= count)
		@throw [OFOutOfRangeException exception];

	tmp = objects[idx1];
	objects[idx1] = objects[idx2];
	objects[idx2] = tmp;
}

- (void)reverse
{
	id *objects = [_array items];
	size_t i, j, count = [_array count];

Modified src/OFMutableData.m from [fd7ae0376c] to [905c436919].

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

	memcpy(_items + _count * _itemSize, item, _itemSize);

	_count++;
}

- (void)insertItem: (const void *)item
	   atIndex: (size_t)index
{
	[self insertItems: item
		  atIndex: index
		    count: 1];
}

- (void)addItems: (const void *)items
	   count: (size_t)count
{
	if (count > SIZE_MAX - _count)







|


|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

	memcpy(_items + _count * _itemSize, item, _itemSize);

	_count++;
}

- (void)insertItem: (const void *)item
	   atIndex: (size_t)idx
{
	[self insertItems: item
		  atIndex: idx
		    count: 1];
}

- (void)addItems: (const void *)items
	   count: (size_t)count
{
	if (count > SIZE_MAX - _count)
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
	}

	memcpy(_items + _count * _itemSize, items, count * _itemSize);
	_count += count;
}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)index
	      count: (size_t)count
{
	if (count > SIZE_MAX - _count || index > _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = [self resizeMemory: _items
				       size: _itemSize
				      count: _count + count];
		_capacity = _count + count;
	}

	memmove(_items + (index + count) * _itemSize,
	    _items + index * _itemSize, (_count - index) * _itemSize);
	memcpy(_items + index * _itemSize, items, count * _itemSize);

	_count += count;
}

- (void)removeItemAtIndex: (size_t)index
{
	[self removeItemsInRange: of_range(index, 1)];
}

- (void)removeItemsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];







|


|









|
|
|




|

|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
	}

	memcpy(_items + _count * _itemSize, items, count * _itemSize);
	_count += count;
}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{
	if (count > SIZE_MAX - _count || idx > _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = [self resizeMemory: _items
				       size: _itemSize
				      count: _count + count];
		_capacity = _count + count;
	}

	memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize,
	   (_count - idx) * _itemSize);
	memcpy(_items + idx * _itemSize, items, count * _itemSize);

	_count += count;
}

- (void)removeItemAtIndex: (size_t)idx
{
	[self removeItemsInRange: of_range(idx, 1)];
}

- (void)removeItemsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

Modified src/OFMutableSet.m from [be0ab30e62] to [475e73874b].

139
140
141
142
143
144
145





146
147
148
149
150
151
152
	return [super init];
}

- initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}






- (void)addObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeObject: (id)object







>
>
>
>
>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	return [super init];
}

- initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}

- copy
{
	return [[OFSet alloc] initWithSet: self];
}

- (void)addObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeObject: (id)object

Modified src/OFMutableString.m from [7b8005c3d9] to [d0679a5108].

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	}

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)setCharacter: (of_unichar_t)character
	     atIndex: (size_t)index
{
	void *pool = objc_autoreleasePoolPush();
	OFString *string;

	string = [OFString stringWithCharacters: &character
					 length: 1];

	[self replaceCharactersInRange: of_range(index, 1)
			    withString: string];

	objc_autoreleasePoolPop(pool);
}

- (void)appendString: (OFString *)string
{







|







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	}

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)setCharacter: (of_unichar_t)character
	     atIndex: (size_t)idx
{
	void *pool = objc_autoreleasePoolPush();
	OFString *string;

	string = [OFString stringWithCharacters: &character
					 length: 1];

	[self replaceCharactersInRange: of_range(idx, 1)
			    withString: string];

	objc_autoreleasePoolPop(pool);
}

- (void)appendString: (OFString *)string
{
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
{
	[self of_convertWithWordStartFunction: of_ascii_toupper
			   wordMiddleFunction: of_ascii_tolower];
}
#endif

- (void)insertString: (OFString *)string
	     atIndex: (size_t)index
{
	[self replaceCharactersInRange: of_range(index, 0)
			    withString: string];
}

- (void)deleteCharactersInRange: (of_range_t)range
{
	[self replaceCharactersInRange: range
			    withString: @""];







|

|







462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
{
	[self of_convertWithWordStartFunction: of_ascii_toupper
			   wordMiddleFunction: of_ascii_tolower];
}
#endif

- (void)insertString: (OFString *)string
	     atIndex: (size_t)idx
{
	[self replaceCharactersInRange: of_range(idx, 0)
			    withString: string];
}

- (void)deleteCharactersInRange: (of_range_t)range
{
	[self replaceCharactersInRange: range
			    withString: @""];

Modified src/OFMutableString_UTF8.m from [4a3385c744] to [688bb89a18].

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
	/*
	 * Even though cStringLength can change, length cannot, therefore no
	 * need to change it.
	 */
}

- (void)setCharacter: (of_unichar_t)character
	     atIndex: (size_t)index
{
	char buffer[4];
	of_unichar_t c;
	size_t lenNew;
	ssize_t lenOld;

	if (_s->isUTF8)
		index = of_string_utf8_get_position(_s->cString, index,
		    _s->cStringLength);

	if (index > _s->cStringLength)
		@throw [OFOutOfRangeException exception];

	/* Shortcut if old and new character both are ASCII */
	if (character < 0x80 && !(_s->cString[index] & 0x80)) {
		_s->hashed = false;
		_s->cString[index] = character;
		return;
	}

	if ((lenNew = of_string_utf8_encode(character, buffer)) == 0)
		@throw [OFInvalidEncodingException exception];

	if ((lenOld = of_string_utf8_decode(_s->cString + index,
	    _s->cStringLength - index, &c)) <= 0)
		@throw [OFInvalidEncodingException exception];

	_s->hashed = false;

	if (lenNew == (size_t)lenOld)
		memcpy(_s->cString + index, buffer, lenNew);
	else if (lenNew > (size_t)lenOld) {
		_s->cString = [self resizeMemory: _s->cString
					    size: _s->cStringLength -
						  lenOld + lenNew + 1];

		memmove(_s->cString + index + lenNew,
		    _s->cString + index + lenOld,
		    _s->cStringLength - index - lenOld);
		memcpy(_s->cString + index, buffer, lenNew);

		_s->cStringLength -= lenOld;
		_s->cStringLength += lenNew;
		_s->cString[_s->cStringLength] = '\0';

		if (character >= 0x80)
			_s->isUTF8 = true;
	} else if (lenNew < (size_t)lenOld) {
		memmove(_s->cString + index + lenNew,
		    _s->cString + index + lenOld,
		    _s->cStringLength - index - lenOld);
		memcpy(_s->cString + index, buffer, lenNew);

		_s->cStringLength -= lenOld;
		_s->cStringLength += lenNew;
		_s->cString[_s->cStringLength] = '\0';

		if (character >= 0x80)
			_s->isUTF8 = true;







|







|


|



|

|






|
|





|





|
<
|
|








|
<
|
|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
	/*
	 * Even though cStringLength can change, length cannot, therefore no
	 * need to change it.
	 */
}

- (void)setCharacter: (of_unichar_t)character
	     atIndex: (size_t)idx
{
	char buffer[4];
	of_unichar_t c;
	size_t lenNew;
	ssize_t lenOld;

	if (_s->isUTF8)
		idx = of_string_utf8_get_position(_s->cString, idx,
		    _s->cStringLength);

	if (idx > _s->cStringLength)
		@throw [OFOutOfRangeException exception];

	/* Shortcut if old and new character both are ASCII */
	if (character < 0x80 && !(_s->cString[idx] & 0x80)) {
		_s->hashed = false;
		_s->cString[idx] = character;
		return;
	}

	if ((lenNew = of_string_utf8_encode(character, buffer)) == 0)
		@throw [OFInvalidEncodingException exception];

	if ((lenOld = of_string_utf8_decode(_s->cString + idx,
	    _s->cStringLength - idx, &c)) <= 0)
		@throw [OFInvalidEncodingException exception];

	_s->hashed = false;

	if (lenNew == (size_t)lenOld)
		memcpy(_s->cString + idx, buffer, lenNew);
	else if (lenNew > (size_t)lenOld) {
		_s->cString = [self resizeMemory: _s->cString
					    size: _s->cStringLength -
						  lenOld + lenNew + 1];

		memmove(_s->cString + idx + lenNew, _s->cString + idx + lenOld,

		    _s->cStringLength - idx - lenOld);
		memcpy(_s->cString + idx, buffer, lenNew);

		_s->cStringLength -= lenOld;
		_s->cStringLength += lenNew;
		_s->cString[_s->cStringLength] = '\0';

		if (character >= 0x80)
			_s->isUTF8 = true;
	} else if (lenNew < (size_t)lenOld) {
		memmove(_s->cString + idx + lenNew, _s->cString + idx + lenOld,

		    _s->cStringLength - idx - lenOld);
		memcpy(_s->cString + idx, buffer, lenNew);

		_s->cStringLength -= lenOld;
		_s->cStringLength += lenNew;
		_s->cString[_s->cStringLength] = '\0';

		if (character >= 0x80)
			_s->isUTF8 = true;
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

		/* UTF-8 does not allow more than 4 bytes per character */
		@throw [OFInvalidEncodingException exception];
	}
}

- (void)insertString: (OFString *)string
	     atIndex: (size_t)index
{
	size_t newCStringLength;

	if (index > _s->length)
		@throw [OFOutOfRangeException exception];

	if (_s->isUTF8)
		index = of_string_utf8_get_position(_s->cString, index,
		    _s->cStringLength);

	newCStringLength = _s->cStringLength + [string UTF8StringLength];
	_s->hashed = false;
	_s->cString = [self resizeMemory: _s->cString
				    size: newCStringLength + 1];

	memmove(_s->cString + index + [string UTF8StringLength],
	    _s->cString + index, _s->cStringLength - index);
	memcpy(_s->cString + index, [string UTF8String],
	    [string UTF8StringLength]);
	_s->cString[newCStringLength] = '\0';

	_s->cStringLength = newCStringLength;
	_s->length += [string length];

	if ([string isKindOfClass: [OFString_UTF8 class]] ||







|



|



|







|
|
|







504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

		/* UTF-8 does not allow more than 4 bytes per character */
		@throw [OFInvalidEncodingException exception];
	}
}

- (void)insertString: (OFString *)string
	     atIndex: (size_t)idx
{
	size_t newCStringLength;

	if (idx > _s->length)
		@throw [OFOutOfRangeException exception];

	if (_s->isUTF8)
		idx = of_string_utf8_get_position(_s->cString, idx,
		    _s->cStringLength);

	newCStringLength = _s->cStringLength + [string UTF8StringLength];
	_s->hashed = false;
	_s->cString = [self resizeMemory: _s->cString
				    size: newCStringLength + 1];

	memmove(_s->cString + idx + [string UTF8StringLength],
	    _s->cString + idx, _s->cStringLength - idx);
	memcpy(_s->cString + idx, [string UTF8String],
	    [string UTF8StringLength]);
	_s->cString[newCStringLength] = '\0';

	_s->cStringLength = newCStringLength;
	_s->length += [string length];

	if ([string isKindOfClass: [OFString_UTF8 class]] ||

Modified src/OFMutableURL.m from [60a5553f44] to [d83d33a394].

14
15
16
17
18
19
20

21
22
23
24
25
26
27
 * file.
 */

#include "config.h"

#import "OFMutableURL.h"
#import "OFURL+Private.h"


@implementation OFMutableURL
@dynamic scheme, host, port, user, password, path, parameters, query, fragment;

+ (instancetype)URL
{
	return [[[self alloc] init] autorelease];







>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 * file.
 */

#include "config.h"

#import "OFMutableURL.h"
#import "OFURL+Private.h"
#import "OFString.h"

@implementation OFMutableURL
@dynamic scheme, host, port, user, password, path, parameters, query, fragment;

+ (instancetype)URL
{
	return [[[self alloc] init] autorelease];

Modified src/OFMutex.h from [60b100f7b5] to [0ee6091df5].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *
 * @brief A class for creating mutual exclusions.
 */
@interface OFMutex: OFObject <OFLocking>
{
	of_mutex_t _mutex;
	bool _initialized;
	OFString *_name;
}

/*!
 * @brief Creates a new mutex.
 *
 * @return A new autoreleased mutex.
 */
+ (instancetype)mutex;
@end

OF_ASSUME_NONNULL_END







|











26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *
 * @brief A class for creating mutual exclusions.
 */
@interface OFMutex: OFObject <OFLocking>
{
	of_mutex_t _mutex;
	bool _initialized;
	OFString *_Nullable _name;
}

/*!
 * @brief Creates a new mutex.
 *
 * @return A new autoreleased mutex.
 */
+ (instancetype)mutex;
@end

OF_ASSUME_NONNULL_END

Modified src/OFNumber.h from [b4280b6f63] to [c8232cc931].

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 * @brief Provides a way to store a number in an object.
 */
@interface OFNumber: OFObject <OFCopying, OFComparing, OFSerialization,
    OFJSONRepresentation, OFMessagePackRepresentation>
{
	union of_number_value {
		bool		   bool_;
		signed char	   schar;
		signed short	   sshort;
		signed int	   sint;
		signed long	   slong;
		signed long long   slonglong;
		unsigned char	   uchar;
		unsigned short	   ushort;
		unsigned int	   uint;
		unsigned long	   ulong;
		unsigned long long ulonglong;
		int8_t		   int8;
		int16_t		   int16;
		int32_t		   int32;
		int64_t		   int64;
		uint8_t		   uint8;
		uint16_t	   uint16;
		uint32_t	   uint32;
		uint64_t	   uint64;
		size_t		   size;
		ssize_t		   ssize;
		intmax_t	   intmax;
		uintmax_t	   uintmax;
		ptrdiff_t	   ptrdiff;
		intptr_t	   intptr;
		uintptr_t	   uintptr;
		float		   float_;
		double		   double_;
	} _value;
	of_number_type_t _type;
}

/*!







|
|
|
|
|
|
|
|
|
|




|
|
|
|

|
|
|
|
|
|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 * @brief Provides a way to store a number in an object.
 */
@interface OFNumber: OFObject <OFCopying, OFComparing, OFSerialization,
    OFJSONRepresentation, OFMessagePackRepresentation>
{
	union of_number_value {
		bool		   bool_;
		signed char	   sChar;
		signed short	   sShort;
		signed int	   sInt;
		signed long	   sLong;
		signed long long   sLongLong;
		unsigned char	   uChar;
		unsigned short	   uShort;
		unsigned int	   uInt;
		unsigned long	   uLong;
		unsigned long long uLongLong;
		int8_t		   int8;
		int16_t		   int16;
		int32_t		   int32;
		int64_t		   int64;
		uint8_t		   uInt8;
		uint16_t	   uInt16;
		uint32_t	   uInt32;
		uint64_t	   uInt64;
		size_t		   size;
		ssize_t		   sSize;
		intmax_t	   intMax;
		uintmax_t	   uIntMax;
		ptrdiff_t	   ptrDiff;
		intptr_t	   intPtr;
		uintptr_t	   uIntPtr;
		float		   float_;
		double		   double_;
	} _value;
	of_number_type_t _type;
}

/*!

Modified src/OFNumber.m from [3d97fc0b3e] to [3da26d55ba].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#import "OFOutOfRangeException.h"

#define RETURN_AS(t)							\
	switch (_type) {						\
	case OF_NUMBER_TYPE_BOOL:					\
		return (t)_value.bool_;					\
	case OF_NUMBER_TYPE_CHAR:					\
		return (t)_value.schar;					\
	case OF_NUMBER_TYPE_SHORT:					\
		return (t)_value.sshort;				\
	case OF_NUMBER_TYPE_INT:					\
		return (t)_value.sint;					\
	case OF_NUMBER_TYPE_LONG:					\
		return (t)_value.slong;					\
	case OF_NUMBER_TYPE_LONGLONG:					\
		return (t)_value.slonglong;				\
	case OF_NUMBER_TYPE_UCHAR:					\
		return (t)_value.uchar;					\
	case OF_NUMBER_TYPE_USHORT:					\
		return (t)_value.ushort;				\
	case OF_NUMBER_TYPE_UINT:					\
		return (t)_value.uint;					\
	case OF_NUMBER_TYPE_ULONG:					\
		return (t)_value.ulong;					\
	case OF_NUMBER_TYPE_ULONGLONG:					\
		return (t)_value.ulonglong;				\
	case OF_NUMBER_TYPE_INT8:					\
		return (t)_value.int8;					\
	case OF_NUMBER_TYPE_INT16:					\
		return (t)_value.int16;					\
	case OF_NUMBER_TYPE_INT32:					\
		return (t)_value.int32;					\
	case OF_NUMBER_TYPE_INT64:					\
		return (t)_value.int64;					\
	case OF_NUMBER_TYPE_UINT8:					\
		return (t)_value.uint8;					\
	case OF_NUMBER_TYPE_UINT16:					\
		return (t)_value.uint16;				\
	case OF_NUMBER_TYPE_UINT32:					\
		return (t)_value.uint32;				\
	case OF_NUMBER_TYPE_UINT64:					\
		return (t)_value.uint64;				\
	case OF_NUMBER_TYPE_SIZE:					\
		return (t)_value.size;					\
	case OF_NUMBER_TYPE_SSIZE:					\
		return (t)_value.ssize;					\
	case OF_NUMBER_TYPE_INTMAX:					\
		return (t)_value.intmax;				\
	case OF_NUMBER_TYPE_UINTMAX:					\
		return (t)_value.uintmax;				\
	case OF_NUMBER_TYPE_PTRDIFF:					\
		return (t)_value.ptrdiff;				\
	case OF_NUMBER_TYPE_INTPTR:					\
		return (t)_value.intptr;				\
	case OF_NUMBER_TYPE_UINTPTR:					\
		return (t)_value.uintptr;				\
	case OF_NUMBER_TYPE_FLOAT:					\
		return (t)_value.float_;				\
	case OF_NUMBER_TYPE_DOUBLE:					\
		return (t)_value.double_;				\
	default:							\
		@throw [OFInvalidFormatException exception];		\
	}







|

|

|

|

|

|

|

|

|

|









|

|

|

|



|

|

|

|

|

|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#import "OFOutOfRangeException.h"

#define RETURN_AS(t)							\
	switch (_type) {						\
	case OF_NUMBER_TYPE_BOOL:					\
		return (t)_value.bool_;					\
	case OF_NUMBER_TYPE_CHAR:					\
		return (t)_value.sChar;					\
	case OF_NUMBER_TYPE_SHORT:					\
		return (t)_value.sShort;				\
	case OF_NUMBER_TYPE_INT:					\
		return (t)_value.sInt;					\
	case OF_NUMBER_TYPE_LONG:					\
		return (t)_value.sLong;					\
	case OF_NUMBER_TYPE_LONGLONG:					\
		return (t)_value.sLongLong;				\
	case OF_NUMBER_TYPE_UCHAR:					\
		return (t)_value.uChar;					\
	case OF_NUMBER_TYPE_USHORT:					\
		return (t)_value.uShort;				\
	case OF_NUMBER_TYPE_UINT:					\
		return (t)_value.uInt;					\
	case OF_NUMBER_TYPE_ULONG:					\
		return (t)_value.uLong;					\
	case OF_NUMBER_TYPE_ULONGLONG:					\
		return (t)_value.uLongLong;				\
	case OF_NUMBER_TYPE_INT8:					\
		return (t)_value.int8;					\
	case OF_NUMBER_TYPE_INT16:					\
		return (t)_value.int16;					\
	case OF_NUMBER_TYPE_INT32:					\
		return (t)_value.int32;					\
	case OF_NUMBER_TYPE_INT64:					\
		return (t)_value.int64;					\
	case OF_NUMBER_TYPE_UINT8:					\
		return (t)_value.uInt8;					\
	case OF_NUMBER_TYPE_UINT16:					\
		return (t)_value.uInt16;				\
	case OF_NUMBER_TYPE_UINT32:					\
		return (t)_value.uInt32;				\
	case OF_NUMBER_TYPE_UINT64:					\
		return (t)_value.uInt64;				\
	case OF_NUMBER_TYPE_SIZE:					\
		return (t)_value.size;					\
	case OF_NUMBER_TYPE_SSIZE:					\
		return (t)_value.sSize;					\
	case OF_NUMBER_TYPE_INTMAX:					\
		return (t)_value.intMax;				\
	case OF_NUMBER_TYPE_UINTMAX:					\
		return (t)_value.uIntMax;				\
	case OF_NUMBER_TYPE_PTRDIFF:					\
		return (t)_value.ptrDiff;				\
	case OF_NUMBER_TYPE_INTPTR:					\
		return (t)_value.intPtr;				\
	case OF_NUMBER_TYPE_UINTPTR:					\
		return (t)_value.uIntPtr;				\
	case OF_NUMBER_TYPE_FLOAT:					\
		return (t)_value.float_;				\
	case OF_NUMBER_TYPE_DOUBLE:					\
		return (t)_value.double_;				\
	default:							\
		@throw [OFInvalidFormatException exception];		\
	}
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
@synthesize type = _type;

+ (instancetype)numberWithBool: (bool)bool_
{
	return [[[self alloc] initWithBool: bool_] autorelease];
}

+ (instancetype)numberWithChar: (signed char)schar
{
	return [[[self alloc] initWithChar: schar] autorelease];
}

+ (instancetype)numberWithShort: (signed short)sshort
{
	return [[[self alloc] initWithShort: sshort] autorelease];
}

+ (instancetype)numberWithInt: (signed int)sint
{
	return [[[self alloc] initWithInt: sint] autorelease];
}

+ (instancetype)numberWithLong: (signed long)slong
{
	return [[[self alloc] initWithLong: slong] autorelease];
}

+ (instancetype)numberWithLongLong: (signed long long)slonglong
{
	return [[[self alloc] initWithLongLong: slonglong] autorelease];
}

+ (instancetype)numberWithUnsignedChar: (unsigned char)uchar
{
	return [[[self alloc] initWithUnsignedChar: uchar] autorelease];
}

+ (instancetype)numberWithUnsignedShort: (unsigned short)ushort
{
	return [[[self alloc] initWithUnsignedShort: ushort] autorelease];
}

+ (instancetype)numberWithUnsignedInt: (unsigned int)uint
{
	return [[[self alloc] initWithUnsignedInt: uint] autorelease];
}

+ (instancetype)numberWithUnsignedLong: (unsigned long)ulong
{
	return [[[self alloc] initWithUnsignedLong: ulong] autorelease];
}

+ (instancetype)numberWithUnsignedLongLong: (unsigned long long)ulonglong
{
	return [[[self alloc] initWithUnsignedLongLong: ulonglong] autorelease];
}

+ (instancetype)numberWithInt8: (int8_t)int8
{
	return [[[self alloc] initWithInt8: int8] autorelease];
}








|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|


|

|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
@synthesize type = _type;

+ (instancetype)numberWithBool: (bool)bool_
{
	return [[[self alloc] initWithBool: bool_] autorelease];
}

+ (instancetype)numberWithChar: (signed char)sChar
{
	return [[[self alloc] initWithChar: sChar] autorelease];
}

+ (instancetype)numberWithShort: (signed short)sShort
{
	return [[[self alloc] initWithShort: sShort] autorelease];
}

+ (instancetype)numberWithInt: (signed int)sInt
{
	return [[[self alloc] initWithInt: sInt] autorelease];
}

+ (instancetype)numberWithLong: (signed long)sLong
{
	return [[[self alloc] initWithLong: sLong] autorelease];
}

+ (instancetype)numberWithLongLong: (signed long long)sLongLong
{
	return [[[self alloc] initWithLongLong: sLongLong] autorelease];
}

+ (instancetype)numberWithUnsignedChar: (unsigned char)uChar
{
	return [[[self alloc] initWithUnsignedChar: uChar] autorelease];
}

+ (instancetype)numberWithUnsignedShort: (unsigned short)uShort
{
	return [[[self alloc] initWithUnsignedShort: uShort] autorelease];
}

+ (instancetype)numberWithUnsignedInt: (unsigned int)uInt
{
	return [[[self alloc] initWithUnsignedInt: uInt] autorelease];
}

+ (instancetype)numberWithUnsignedLong: (unsigned long)uLong
{
	return [[[self alloc] initWithUnsignedLong: uLong] autorelease];
}

+ (instancetype)numberWithUnsignedLongLong: (unsigned long long)uLongLong
{
	return [[[self alloc] initWithUnsignedLongLong: uLongLong] autorelease];
}

+ (instancetype)numberWithInt8: (int8_t)int8
{
	return [[[self alloc] initWithInt8: int8] autorelease];
}

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
}

+ (instancetype)numberWithUInt8: (uint8_t)uint8
{
	return [[[self alloc] initWithUInt8: uint8] autorelease];
}

+ (instancetype)numberWithUInt16: (uint16_t)uint16
{
	return [[[self alloc] initWithUInt16: uint16] autorelease];
}

+ (instancetype)numberWithUInt32: (uint32_t)uint32
{
	return [[[self alloc] initWithUInt32: uint32] autorelease];
}

+ (instancetype)numberWithUInt64: (uint64_t)uint64
{
	return [[[self alloc] initWithUInt64: uint64] autorelease];
}

+ (instancetype)numberWithSize: (size_t)size
{
	return [[[self alloc] initWithSize: size] autorelease];
}

+ (instancetype)numberWithSSize: (ssize_t)ssize
{
	return [[[self alloc] initWithSSize: ssize] autorelease];
}

+ (instancetype)numberWithIntMax: (intmax_t)intmax
{
	return [[[self alloc] initWithIntMax: intmax] autorelease];
}

+ (instancetype)numberWithUIntMax: (uintmax_t)uintmax
{
	return [[[self alloc] initWithUIntMax: uintmax] autorelease];
}

+ (instancetype)numberWithPtrDiff: (ptrdiff_t)ptrdiff
{
	return [[[self alloc] initWithPtrDiff: ptrdiff] autorelease];
}

+ (instancetype)numberWithIntPtr: (intptr_t)intptr
{
	return [[[self alloc] initWithIntPtr: intptr] autorelease];
}

+ (instancetype)numberWithUIntPtr: (uintptr_t)uintptr
{
	return [[[self alloc] initWithUIntPtr: uintptr] autorelease];
}

+ (instancetype)numberWithFloat: (float)float_
{
	return [[[self alloc] initWithFloat: float_] autorelease];
}








|

|


|

|


|

|







|

|


|

|


|

|


|

|


|

|


|

|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
}

+ (instancetype)numberWithUInt8: (uint8_t)uint8
{
	return [[[self alloc] initWithUInt8: uint8] autorelease];
}

+ (instancetype)numberWithUInt16: (uint16_t)uInt16
{
	return [[[self alloc] initWithUInt16: uInt16] autorelease];
}

+ (instancetype)numberWithUInt32: (uint32_t)uInt32
{
	return [[[self alloc] initWithUInt32: uInt32] autorelease];
}

+ (instancetype)numberWithUInt64: (uint64_t)uInt64
{
	return [[[self alloc] initWithUInt64: uInt64] autorelease];
}

+ (instancetype)numberWithSize: (size_t)size
{
	return [[[self alloc] initWithSize: size] autorelease];
}

+ (instancetype)numberWithSSize: (ssize_t)sSize
{
	return [[[self alloc] initWithSSize: sSize] autorelease];
}

+ (instancetype)numberWithIntMax: (intmax_t)intMax
{
	return [[[self alloc] initWithIntMax: intMax] autorelease];
}

+ (instancetype)numberWithUIntMax: (uintmax_t)uIntMax
{
	return [[[self alloc] initWithUIntMax: uIntMax] autorelease];
}

+ (instancetype)numberWithPtrDiff: (ptrdiff_t)ptrDiff
{
	return [[[self alloc] initWithPtrDiff: ptrDiff] autorelease];
}

+ (instancetype)numberWithIntPtr: (intptr_t)intPtr
{
	return [[[self alloc] initWithIntPtr: intPtr] autorelease];
}

+ (instancetype)numberWithUIntPtr: (uintptr_t)uIntPtr
{
	return [[[self alloc] initWithUIntPtr: uIntPtr] autorelease];
}

+ (instancetype)numberWithFloat: (float)float_
{
	return [[[self alloc] initWithFloat: float_] autorelease];
}

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

	_value.bool_ = bool_;
	_type = OF_NUMBER_TYPE_BOOL;

	return self;
}

- initWithChar: (signed char)schar
{
	self = [super init];

	_value.schar = schar;
	_type = OF_NUMBER_TYPE_CHAR;

	return self;
}

- initWithShort: (signed short)sshort
{
	self = [super init];

	_value.sshort = sshort;
	_type = OF_NUMBER_TYPE_SHORT;

	return self;
}

- initWithInt: (signed int)sint
{
	self = [super init];

	_value.sint = sint;
	_type = OF_NUMBER_TYPE_INT;

	return self;
}

- initWithLong: (signed long)slong
{
	self = [super init];

	_value.slong = slong;
	_type = OF_NUMBER_TYPE_LONG;

	return self;
}

- initWithLongLong: (signed long long)slonglong
{
	self = [super init];

	_value.slonglong = slonglong;
	_type = OF_NUMBER_TYPE_LONGLONG;

	return self;
}

- initWithUnsignedChar: (unsigned char)uchar
{
	self = [super init];

	_value.uchar = uchar;
	_type = OF_NUMBER_TYPE_UCHAR;

	return self;
}

- initWithUnsignedShort: (unsigned short)ushort
{
	self = [super init];

	_value.ushort = ushort;
	_type = OF_NUMBER_TYPE_USHORT;

	return self;
}

- initWithUnsignedInt: (unsigned int)uint
{
	self = [super init];

	_value.uint = uint;
	_type = OF_NUMBER_TYPE_UINT;

	return self;
}

- initWithUnsignedLong: (unsigned long)ulong
{
	self = [super init];

	_value.ulong = ulong;
	_type = OF_NUMBER_TYPE_ULONG;

	return self;
}

- initWithUnsignedLongLong: (unsigned long long)ulonglong
{
	self = [super init];

	_value.ulonglong = ulonglong;
	_type = OF_NUMBER_TYPE_ULONGLONG;

	return self;
}

- initWithInt8: (int8_t)int8
{







|



|





|



|





|



|





|



|





|



|





|



|





|



|





|



|





|



|





|



|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

	_value.bool_ = bool_;
	_type = OF_NUMBER_TYPE_BOOL;

	return self;
}

- initWithChar: (signed char)sChar
{
	self = [super init];

	_value.sChar = sChar;
	_type = OF_NUMBER_TYPE_CHAR;

	return self;
}

- initWithShort: (signed short)sShort
{
	self = [super init];

	_value.sShort = sShort;
	_type = OF_NUMBER_TYPE_SHORT;

	return self;
}

- initWithInt: (signed int)sInt
{
	self = [super init];

	_value.sInt = sInt;
	_type = OF_NUMBER_TYPE_INT;

	return self;
}

- initWithLong: (signed long)sLong
{
	self = [super init];

	_value.sLong = sLong;
	_type = OF_NUMBER_TYPE_LONG;

	return self;
}

- initWithLongLong: (signed long long)sLongLong
{
	self = [super init];

	_value.sLongLong = sLongLong;
	_type = OF_NUMBER_TYPE_LONGLONG;

	return self;
}

- initWithUnsignedChar: (unsigned char)uChar
{
	self = [super init];

	_value.uChar = uChar;
	_type = OF_NUMBER_TYPE_UCHAR;

	return self;
}

- initWithUnsignedShort: (unsigned short)uShort
{
	self = [super init];

	_value.uShort = uShort;
	_type = OF_NUMBER_TYPE_USHORT;

	return self;
}

- initWithUnsignedInt: (unsigned int)uInt
{
	self = [super init];

	_value.uInt = uInt;
	_type = OF_NUMBER_TYPE_UINT;

	return self;
}

- initWithUnsignedLong: (unsigned long)uLong
{
	self = [super init];

	_value.uLong = uLong;
	_type = OF_NUMBER_TYPE_ULONG;

	return self;
}

- initWithUnsignedLongLong: (unsigned long long)uLongLong
{
	self = [super init];

	_value.uLongLong = uLongLong;
	_type = OF_NUMBER_TYPE_ULONGLONG;

	return self;
}

- initWithInt8: (int8_t)int8
{
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

	_value.int64 = int64;
	_type = OF_NUMBER_TYPE_INT64;

	return self;
}

- initWithUInt8: (uint8_t)uint8
{
	self = [super init];

	_value.uint8 = uint8;
	_type = OF_NUMBER_TYPE_UINT8;

	return self;
}

- initWithUInt16: (uint16_t)uint16
{
	self = [super init];

	_value.uint16 = uint16;
	_type = OF_NUMBER_TYPE_UINT16;

	return self;
}

- initWithUInt32: (uint32_t)uint32
{
	self = [super init];

	_value.uint32 = uint32;
	_type = OF_NUMBER_TYPE_UINT32;

	return self;
}

- initWithUInt64: (uint64_t)uint64
{
	self = [super init];

	_value.uint64 = uint64;
	_type = OF_NUMBER_TYPE_UINT64;

	return self;
}

- initWithSize: (size_t)size
{
	self = [super init];

	_value.size = size;
	_type = OF_NUMBER_TYPE_SIZE;

	return self;
}

- initWithSSize: (ssize_t)ssize
{
	self = [super init];

	_value.ssize = ssize;
	_type = OF_NUMBER_TYPE_SSIZE;

	return self;
}

- initWithIntMax: (intmax_t)intmax
{
	self = [super init];

	_value.intmax = intmax;
	_type = OF_NUMBER_TYPE_INTMAX;

	return self;
}

- initWithUIntMax: (uintmax_t)uintmax
{
	self = [super init];

	_value.uintmax = uintmax;
	_type = OF_NUMBER_TYPE_UINTMAX;

	return self;
}

- initWithPtrDiff: (ptrdiff_t)ptrdiff
{
	self = [super init];

	_value.ptrdiff = ptrdiff;
	_type = OF_NUMBER_TYPE_PTRDIFF;

	return self;
}

- initWithIntPtr: (intptr_t)intptr
{
	self = [super init];

	_value.intptr = intptr;
	_type = OF_NUMBER_TYPE_INTPTR;

	return self;
}

- initWithUIntPtr: (uintptr_t)uintptr
{
	self = [super init];

	_value.uintptr = uintptr;
	_type = OF_NUMBER_TYPE_UINTPTR;

	return self;
}

- initWithFloat: (float)float_
{







|



|





|



|





|



|





|



|















|



|





|



|





|



|





|



|





|



|





|



|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

	_value.int64 = int64;
	_type = OF_NUMBER_TYPE_INT64;

	return self;
}

- initWithUInt8: (uint8_t)uInt8
{
	self = [super init];

	_value.uInt8 = uInt8;
	_type = OF_NUMBER_TYPE_UINT8;

	return self;
}

- initWithUInt16: (uint16_t)uInt16
{
	self = [super init];

	_value.uInt16 = uInt16;
	_type = OF_NUMBER_TYPE_UINT16;

	return self;
}

- initWithUInt32: (uint32_t)uInt32
{
	self = [super init];

	_value.uInt32 = uInt32;
	_type = OF_NUMBER_TYPE_UINT32;

	return self;
}

- initWithUInt64: (uint64_t)uInt64
{
	self = [super init];

	_value.uInt64 = uInt64;
	_type = OF_NUMBER_TYPE_UINT64;

	return self;
}

- initWithSize: (size_t)size
{
	self = [super init];

	_value.size = size;
	_type = OF_NUMBER_TYPE_SIZE;

	return self;
}

- initWithSSize: (ssize_t)sSize
{
	self = [super init];

	_value.sSize = sSize;
	_type = OF_NUMBER_TYPE_SSIZE;

	return self;
}

- initWithIntMax: (intmax_t)intMax
{
	self = [super init];

	_value.intMax = intMax;
	_type = OF_NUMBER_TYPE_INTMAX;

	return self;
}

- initWithUIntMax: (uintmax_t)uIntMax
{
	self = [super init];

	_value.uIntMax = uIntMax;
	_type = OF_NUMBER_TYPE_UINTMAX;

	return self;
}

- initWithPtrDiff: (ptrdiff_t)ptrDiff
{
	self = [super init];

	_value.ptrDiff = ptrDiff;
	_type = OF_NUMBER_TYPE_PTRDIFF;

	return self;
}

- initWithIntPtr: (intptr_t)intPtr
{
	self = [super init];

	_value.intPtr = intPtr;
	_type = OF_NUMBER_TYPE_INTPTR;

	return self;
}

- initWithUIntPtr: (uintptr_t)uIntPtr
{
	self = [super init];

	_value.uIntPtr = uIntPtr;
	_type = OF_NUMBER_TYPE_UINTPTR;

	return self;
}

- initWithFloat: (float)float_
{
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
				@throw [OFInvalidArgumentException exception];
		} else if ([typeString isEqual: @"unsigned"]) {
			/*
			 * FIXME: This will fail if the value is bigger than
			 *	  INTMAX_MAX!
			 */
			_type = OF_NUMBER_TYPE_UINTMAX;
			_value.uintmax = [element decimalValue];
		} else if ([typeString isEqual: @"signed"]) {
			_type = OF_NUMBER_TYPE_INTMAX;
			_value.intmax = [element decimalValue];
		} else if ([typeString isEqual: @"float"]) {
			union {
				float f;
				uint32_t u;
			} f;

			f.u = OF_BSWAP32_IF_LE(







|


|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
				@throw [OFInvalidArgumentException exception];
		} else if ([typeString isEqual: @"unsigned"]) {
			/*
			 * FIXME: This will fail if the value is bigger than
			 *	  INTMAX_MAX!
			 */
			_type = OF_NUMBER_TYPE_UINTMAX;
			_value.uIntMax = [element decimalValue];
		} else if ([typeString isEqual: @"signed"]) {
			_type = OF_NUMBER_TYPE_INTMAX;
			_value.intMax = [element decimalValue];
		} else if ([typeString isEqual: @"float"]) {
			union {
				float f;
				uint32_t u;
			} f;

			f.u = OF_BSWAP32_IF_LE(

Modified src/OFObject.h from [9973173cd1] to [7fadabcfb1].

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
- (Class)class;

/*!
 * @brief Returns the superclass of the object.
 *
 * @return The superclass of the object
 */
- (Class)superclass;

/*!
 * @brief Returns a boolean whether the object of the specified kind.
 *
 * @param class_ The class whose kind is checked
 * @return A boolean whether the object is of the specified kind
 */







|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
- (Class)class;

/*!
 * @brief Returns the superclass of the object.
 *
 * @return The superclass of the object
 */
- (nullable Class)superclass;

/*!
 * @brief Returns a boolean whether the object of the specified kind.
 *
 * @param class_ The class whose kind is checked
 * @return A boolean whether the object is of the specified kind
 */
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
+ (bool)isSubclassOfClass: (Class)class_;

/*!
 * @brief Returns the superclass of the class.
 *
 * @return The superclass of the class
 */
+ (Class)superclass;

/*!
 * @brief Checks whether instances of the class respond to a given selector.
 *
 * @param selector The selector which should be checked for respondence
 * @return A boolean whether instances of the class respond to the specified
 *	   selector







|







457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
+ (bool)isSubclassOfClass: (Class)class_;

/*!
 * @brief Returns the superclass of the class.
 *
 * @return The superclass of the class
 */
+ (nullable Class)superclass;

/*!
 * @brief Checks whether instances of the class respond to a given selector.
 *
 * @param selector The selector which should be checked for respondence
 * @return A boolean whether instances of the class respond to the specified
 *	   selector
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673

/*!
 * @brief Allocates memory and stores it in the object's memory pool.
 *
 * It will be freed automatically when the object is deallocated.
 *
 * @param size The size of the memory to allocate
 * @return A pointer to the allocated memory

 */
- (void *)allocMemoryWithSize: (size_t)size;

/*!
 * @brief Allocates memory for the specified number of items and stores it in
 *	  the object's memory pool.
 *
 * It will be freed automatically when the object is deallocated.
 *
 * @param size The size of each item to allocate
 * @param count The number of items to allocate
 * @return A pointer to the allocated memory

 */
- (void *)allocMemoryWithSize: (size_t)size
			count: (size_t)count;

/*!
 * @brief Resizes memory in the object's memory pool to the specified size.
 *
 * If the pointer is NULL, this is equivalent to allocating memory.
 * If the size is 0, this is equivalent to freeing memory.
 *







|
>

|









|
>

|
|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

/*!
 * @brief Allocates memory and stores it in the object's memory pool.
 *
 * It will be freed automatically when the object is deallocated.
 *
 * @param size The size of the memory to allocate
 * @return A pointer to the allocated memory. May return NULL if the specified
 *	   size is 0.
 */
- (nullable void *)allocMemoryWithSize: (size_t)size;

/*!
 * @brief Allocates memory for the specified number of items and stores it in
 *	  the object's memory pool.
 *
 * It will be freed automatically when the object is deallocated.
 *
 * @param size The size of each item to allocate
 * @param count The number of items to allocate
 * @return A pointer to the allocated memory. May return NULL if the specified
 *	   size or count is 0.
 */
- (nullable void *)allocMemoryWithSize: (size_t)size
				 count: (size_t)count;

/*!
 * @brief Resizes memory in the object's memory pool to the specified size.
 *
 * If the pointer is NULL, this is equivalent to allocating memory.
 * If the size is 0, this is equivalent to freeing memory.
 *

Modified src/OFObject.m from [c072b00a16] to [4d9911935a].

468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
				withMethodFromClass: class];
		}
	} @finally {
		free(methodList);
	}
#endif

	[self inheritMethodsFromClass: [class superclass]];
}

+ (BOOL)resolveClassMethod: (SEL)selector
{
	return NO;
}








|







468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
				withMethodFromClass: class];
		}
	} @finally {
		free(methodList);
	}
#endif

	[self inheritMethodsFromClass: superclass];
}

+ (BOOL)resolveClassMethod: (SEL)selector
{
	return NO;
}

Modified src/OFOptionsParser.h from [b82c75fff0] to [b57dc17fb3].

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@interface OFOptionsParser: OFObject
{
	of_options_parser_option_t *_options;
	OFMapTable *_longOptions;
	OFArray OF_GENERIC(OFString *) *_arguments;
	size_t _index, _subIndex;
	of_unichar_t _lastOption;
	OFString *_lastLongOption, *_argument;
	bool _done;
}

/*!
 * The last parsed option.
 *
 * If @ref nextOption returned `?` or `:`, this returns the option which was







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@interface OFOptionsParser: OFObject
{
	of_options_parser_option_t *_options;
	OFMapTable *_longOptions;
	OFArray OF_GENERIC(OFString *) *_arguments;
	size_t _index, _subIndex;
	of_unichar_t _lastOption;
	OFString *_Nullable _lastLongOption, *_Nullable _argument;
	bool _done;
}

/*!
 * The last parsed option.
 *
 * If @ref nextOption returned `?` or `:`, this returns the option which was

Modified src/OFRecursiveMutex.h from [8408c300d0] to [6ef5e2c06f].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * @brief A class for creating mutual exclusions which can be entered
 *	  recursively.
 */
@interface OFRecursiveMutex: OFObject <OFLocking>
{
	of_rmutex_t _rmutex;
	bool _initialized;
	OFString *_name;
}

/*!
 * @brief Creates a new recursive mutex.
 *
 * @return A new autoreleased recursive mutex.
 */
+ (instancetype)mutex;
@end

OF_ASSUME_NONNULL_END







|











27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * @brief A class for creating mutual exclusions which can be entered
 *	  recursively.
 */
@interface OFRecursiveMutex: OFObject <OFLocking>
{
	of_rmutex_t _rmutex;
	bool _initialized;
	OFString *_Nullable _name;
}

/*!
 * @brief Creates a new recursive mutex.
 *
 * @return A new autoreleased recursive mutex.
 */
+ (instancetype)mutex;
@end

OF_ASSUME_NONNULL_END

Modified src/OFRunLoop.h from [584523a360] to [493e731362].

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}

/*!
 * @brief Returns the run loop for the main thread.
 *
 * @return The run loop for the main thread
 */
+ (OFRunLoop *)mainRunLoop;

/*!
 * @brief Returns the run loop for the current thread.
 *
 * @return The run loop for the current thread
 */
+ (OFRunLoop *)currentRunLoop;

/*!
 * @brief Adds an OFTimer to the run loop.
 *
 * @param timer The timer to add
 */
- (void)addTimer: (OFTimer *)timer;







|






|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}

/*!
 * @brief Returns the run loop for the main thread.
 *
 * @return The run loop for the main thread
 */
+ (nullable OFRunLoop *)mainRunLoop;

/*!
 * @brief Returns the run loop for the current thread.
 *
 * @return The run loop for the current thread
 */
+ (nullable OFRunLoop *)currentRunLoop;

/*!
 * @brief Adds an OFTimer to the run loop.
 *
 * @param timer The timer to add
 */
- (void)addTimer: (OFTimer *)timer;

Modified src/OFRunLoop.m from [50df1150e8] to [15a7c5ffb7].

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35


36
37
38
39
40
41
42
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <assert.h>


#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_SOCKETS
# import "OFKernelEventObserver.h"
#endif
#import "OFThread.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
# import "OFCondition.h"
#endif
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"



static OFRunLoop *mainRunLoop = nil;

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public







>
















>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <assert.h>
#include <errno.h>

#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_SOCKETS
# import "OFKernelEventObserver.h"
#endif
#import "OFThread.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
# import "OFCondition.h"
#endif
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"

#import "OFObserveFailedException.h"

static OFRunLoop *mainRunLoop = nil;

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, address, exception);
	else {
# endif
		bool (*func)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t address, OFException *) =
		    (bool (*)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    address, exception);
# ifdef OF_HAVE_BLOCKS







|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, address, exception);
	else {
# endif
		bool (*func)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t, OFException *) =
		    (bool (*)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    address, exception);
# ifdef OF_HAVE_BLOCKS
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, socket, {
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
	})
}








|





|







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)sock
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, sock, {
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
	})
}

480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
				block: (of_tcp_socket_async_accept_block_t)block
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_block = [block copy];
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				 block: (of_udp_socket_async_receive_block_t)
					    block
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, socket, {
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_block = [block copy];
	})
}
# endif
# undef ADD_READ







|





|







483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
				block: (of_tcp_socket_async_accept_block_t)block
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_block = [block copy];
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)sock
				buffer: (void *)buffer
				length: (size_t)length
				 block: (of_udp_socket_async_receive_block_t)
					    block
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, sock, {
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_block = [block copy];
	})
}
# endif
# undef ADD_READ
715
716
717
718
719
720
721

722
723




724
725
726
727
728
729
730
731
732
733
734
735
736
737

738




739
740
741
742
743
744
745
				timeout = [[nextTimer earlierDate: deadline]
				    timeIntervalSinceNow];

			if (timeout < 0)
				timeout = 0;

#if defined(OF_HAVE_SOCKETS)

			[_kernelEventObserver
			    observeForTimeInterval: timeout];




#elif defined(OF_HAVE_THREADS)
			[_condition lock];
			[_condition waitForTimeInterval: timeout];
			[_condition unlock];
#else
			[OFThread sleepForTimeInterval: timeout];
#endif
		} else {
			/*
			 * No more timers and no deadline: Just watch for I/O
			 * until we get an event. If a timer is added by
			 * another thread, it cancels the observe.
			 */
#if defined(OF_HAVE_SOCKETS)

			[_kernelEventObserver observe];




#elif defined(OF_HAVE_THREADS)
			[_condition lock];
			[_condition wait];
			[_condition unlock];
#else
			[OFThread sleepForTimeInterval: 86400];
#endif







>
|
|
>
>
>
>














>
|
>
>
>
>







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
				timeout = [[nextTimer earlierDate: deadline]
				    timeIntervalSinceNow];

			if (timeout < 0)
				timeout = 0;

#if defined(OF_HAVE_SOCKETS)
			@try {
				[_kernelEventObserver
				    observeForTimeInterval: timeout];
			} @catch (OFObserveFailedException *e) {
				if ([e errNo] != EINTR)
					@throw e;
			}
#elif defined(OF_HAVE_THREADS)
			[_condition lock];
			[_condition waitForTimeInterval: timeout];
			[_condition unlock];
#else
			[OFThread sleepForTimeInterval: timeout];
#endif
		} else {
			/*
			 * No more timers and no deadline: Just watch for I/O
			 * until we get an event. If a timer is added by
			 * another thread, it cancels the observe.
			 */
#if defined(OF_HAVE_SOCKETS)
			@try {
				[_kernelEventObserver observe];
			} @catch (OFObserveFailedException *e) {
				if ([e errNo] != EINTR)
					@throw e;
			}
#elif defined(OF_HAVE_THREADS)
			[_condition lock];
			[_condition wait];
			[_condition unlock];
#else
			[OFThread sleepForTimeInterval: 86400];
#endif

Modified src/OFSet.h from [b570ea6601] to [28701b2ea5].

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
- (OFArray OF_GENERIC(ObjectType) *)allObjects;

/*!
 * @brief Returns an arbitrary object in the set.
 *
 * @return An arbitrary object in the set
 */
- (ObjectType)anyObject;

/*!
 * @brief Checks whether the set contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the set
 * @return A boolean whether the set contains the specified object
 */
- (bool)containsObject: (nullable ObjectType)object;

/*!
 * @brief Returns the value for the specified key
 *
 * If the key starts with an `@`, the `@` is stripped and
 * `[super valueForKey:]` is called.
 * If the key does not start with an `@`, a new set with the value for the







|








|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
- (OFArray OF_GENERIC(ObjectType) *)allObjects;

/*!
 * @brief Returns an arbitrary object in the set.
 *
 * @return An arbitrary object in the set
 */
- (nullable ObjectType)anyObject;

/*!
 * @brief Checks whether the set contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the set
 * @return A boolean whether the set contains the specified object
 */
- (bool)containsObject: (ObjectType)object;

/*!
 * @brief Returns the value for the specified key
 *
 * If the key starts with an `@`, the `@` is stripped and
 * `[super valueForKey:]` is called.
 * If the key does not start with an `@`, a new set with the value for the
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
 * each object.
 *
 * @note A @ref OFNull value is translated to nil!
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (nullable id)value
	  forKey: (OFString *)key;

/*!
 * @brief Returns an OFEnumerator to enumerate through all objects of the set.
 *
 * @returns An OFEnumerator to enumerate through all objects of the set
 */







|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
 * each object.
 *
 * @note A @ref OFNull value is translated to nil!
 *
 * @param value The value for the specified key
 * @param key The key of the value to set
 */
- (void)setValue: (id)value
	  forKey: (OFString *)key;

/*!
 * @brief Returns an OFEnumerator to enumerate through all objects of the set.
 *
 * @returns An OFEnumerator to enumerate through all objects of the set
 */

Modified src/OFSet.m from [62db370766] to [9a3d14535d].

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)valueForKey: (OFString *)key
{
	OFMutableSet *ret;

	if ([key hasPrefix: @"@"]) {
		void *pool = objc_autoreleasePoolPush();
		id ret;

		key = [key substringWithRange: of_range(1, [key length] - 1)];
		ret = [[super valueForKey: key] retain];

		objc_autoreleasePoolPop(pool);

		return [ret autorelease];







|



<







209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)valueForKey: (OFString *)key
{
	id ret;

	if ([key hasPrefix: @"@"]) {
		void *pool = objc_autoreleasePoolPush();


		key = [key substringWithRange: of_range(1, [key length] - 1)];
		ret = [[super valueForKey: key] retain];

		objc_autoreleasePoolPop(pool);

		return [ret autorelease];
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
		[super setValue: value
			 forKey: key];

		objc_autoreleasePoolPop(pool);
		return;
	}

	if (value == [OFNull null])
		value = nil;

	for (id object in self)
		[object setValue: value
			  forKey: key];
}

- (bool)containsObject: (id)object
{







<
<
<







250
251
252
253
254
255
256



257
258
259
260
261
262
263
		[super setValue: value
			 forKey: key];

		objc_autoreleasePoolPop(pool);
		return;
	}




	for (id object in self)
		[object setValue: value
			  forKey: key];
}

- (bool)containsObject: (id)object
{

Modified src/OFStream.h from [fc84511d6f] to [1cb5dc2e2d].

90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
    OFReadyForReadingObserving, OFReadyForWritingObserving,
#endif
    OFCopying>
{
#if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M)
@private
#endif

	char *_readBuffer, *_readBufferMemory, *_writeBuffer;
	size_t _readBufferLength, _writeBufferLength;
	bool _writeBuffered, _waitingForDelimiter;
@protected
	bool _blocking;
}

/*!







>
|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
    OFReadyForReadingObserving, OFReadyForWritingObserving,
#endif
    OFCopying>
{
#if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M)
@private
#endif
	char *_Nullable _readBuffer, *_Nullable _readBufferMemory;
	char *_Nullable _writeBuffer;
	size_t _readBufferLength, _writeBufferLength;
	bool _writeBuffered, _waitingForDelimiter;
@protected
	bool _blocking;
}

/*!

Modified src/OFStream.m from [d30563e398] to [e48fbb2fa9].

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#import "of_asprintf.h"

#define MIN_READ_SIZE 512

@implementation OFStream
@synthesize of_waitingForDelimiter = _waitingForDelimiter;

#if !defined(OF_WINDOWS) && !defined(OF_MORPHOS)
+ (void)initialize
{
	if (self == [OFStream class])
		signal(SIGPIPE, SIG_IGN);
}
#endif








|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#import "of_asprintf.h"

#define MIN_READ_SIZE 512

@implementation OFStream
@synthesize of_waitingForDelimiter = _waitingForDelimiter;

#if defined(SIGPIPE) && defined(SIG_IGN)
+ (void)initialize
{
	if (self == [OFStream class])
		signal(SIGPIPE, SIG_IGN);
}
#endif

Modified src/OFString+XMLUnescaping.h from [0f77351c40] to [48a186039b].

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 * it is unknown to the callback as well, in which case an exception will be
 * thrown.
 *
 * @param string The string which contains the unknown entity
 * @param entity The name of the entity that is unknown
 * @return A substitution for the entity or `nil`
 */
-	  (OFString *)string: (OFString *)string
  containsUnknownEntityNamed: (OFString *)entity;
@end

@interface OFString (XMLUnescaping)
/*!
 * @brief Unescapes XML in the string.
 */
- (OFString *)stringByXMLUnescaping;







|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 * it is unknown to the callback as well, in which case an exception will be
 * thrown.
 *
 * @param string The string which contains the unknown entity
 * @param entity The name of the entity that is unknown
 * @return A substitution for the entity or `nil`
 */
- (nullable OFString *)string: (OFString *)string
   containsUnknownEntityNamed: (OFString *)entity;
@end

@interface OFString (XMLUnescaping)
/*!
 * @brief Unescapes XML in the string.
 */
- (OFString *)stringByXMLUnescaping;

Modified src/OFString+XMLUnescaping.m from [d6e6b667b8] to [9667538219].

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
					    length: 1];
			else if (entityLength == 3 &&
			    memcmp(entity, "amp", 3) == 0)
				[ret appendCString: "&"
					  encoding: OF_STRING_ENCODING_ASCII
					    length: 1];
			else if (entity[0] == '#') {
				void *pool;
				OFString *tmp;

				pool = objc_autoreleasePoolPush();
				tmp = parseNumericEntity(entity,
				    entityLength);

				if (tmp == nil)
					@throw [OFInvalidFormatException
					    exception];

				[ret appendString: tmp];

				objc_autoreleasePoolPop(pool);
			} else {
				void *pool;
				OFString *name, *tmp;

				pool = objc_autoreleasePoolPush();

				name = [OFString
				    stringWithUTF8String: entity
						  length: entityLength];
				tmp = lookup(context, self, name);

				if (tmp == nil)
					@throw [OFUnknownXMLEntityException
					    exceptionWithEntityName: name];

				[ret appendString: tmp];

				objc_autoreleasePoolPop(pool);
			}

			last = i + 1;
			inEntity = false;
		}
	}








|


|








>
|

|


|











>
|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
					    length: 1];
			else if (entityLength == 3 &&
			    memcmp(entity, "amp", 3) == 0)
				[ret appendCString: "&"
					  encoding: OF_STRING_ENCODING_ASCII
					    length: 1];
			else if (entity[0] == '#') {
				void *pool2;
				OFString *tmp;

				pool2 = objc_autoreleasePoolPush();
				tmp = parseNumericEntity(entity,
				    entityLength);

				if (tmp == nil)
					@throw [OFInvalidFormatException
					    exception];

				[ret appendString: tmp];

				objc_autoreleasePoolPop(pool2);
			} else {
				void *pool2;
				OFString *name, *tmp;

				pool2 = objc_autoreleasePoolPush();

				name = [OFString
				    stringWithUTF8String: entity
						  length: entityLength];
				tmp = lookup(context, self, name);

				if (tmp == nil)
					@throw [OFUnknownXMLEntityException
					    exceptionWithEntityName: name];

				[ret appendString: tmp];

				objc_autoreleasePoolPop(pool2);
			}

			last = i + 1;
			inEntity = false;
		}
	}

Modified src/OFString.h from [f5efa5d129] to [7c41844eaa].

16
17
18
19
20
21
22






23
24
25
26
27
28
29

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif







#include <stdarg.h>
#include <stdint.h>

#import "OFObject.h"
#import "OFSerialization.h"
#import "OFJSONRepresentation.h"







>
>
>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#import "objfw-defs.h"

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#include <stdarg.h>
#include <stdint.h>

#import "OFObject.h"
#import "OFSerialization.h"
#import "OFJSONRepresentation.h"
131
132
133
134
135
136
137
138





139
140
141
142
143
144
145
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8String: (const char *)UTF8String
			      length: (size_t)UTF8StringLength;

/*!
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string.





 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String







|
>
>
>
>
>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8String: (const char *)UTF8String
			      length: (size_t)UTF8StringLength;

/*!
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String
372
373
374
375
376
377
378
379
380



381
382
383
384
385
386
387
388
 * @return An initialized OFString
 */
- initWithUTF8String: (const char *)UTF8String
	      length: (size_t)UTF8StringLength;

/*!
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying it, if possible.
 *



 * @note Mutable versions always create a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 */
- initWithUTF8StringNoCopy: (char *)UTF8String







|

>
>
>
|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
 * @return An initialized OFString
 */
- initWithUTF8String: (const char *)UTF8String
	      length: (size_t)UTF8StringLength;

/*!
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 */
- initWithUTF8StringNoCopy: (char *)UTF8String

Modified src/OFString.m from [fc3a0af468] to [e6724ae75a].

846
847
848
849
850
851
852

853




854
855
856
857
858
859
860
			    encoding: OF_STRING_ENCODING_UTF_8
			      length: UTF8StringLength];
}

- initWithUTF8StringNoCopy: (char *)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{

	return [self initWithUTF8String: UTF8String];




}

- initWithCString: (const char *)cString
	 encoding: (of_string_encoding_t)encoding
{
	return [self initWithCString: cString
			    encoding: encoding







>
|
>
>
>
>







846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
			    encoding: OF_STRING_ENCODING_UTF_8
			      length: UTF8StringLength];
}

- initWithUTF8StringNoCopy: (char *)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{
	@try {
		return [self initWithUTF8String: UTF8String];
	} @finally {
		if (freeWhenDone)
			free(UTF8String);
	}
}

- initWithCString: (const char *)cString
	 encoding: (of_string_encoding_t)encoding
{
	return [self initWithCString: cString
			    encoding: encoding
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
}

- (size_t)UTF8StringLength
{
	return [self cStringLengthWithEncoding: OF_STRING_ENCODING_UTF_8];
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range
{







|







1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
}

- (size_t)UTF8StringLength
{
	return [self cStringLengthWithEncoding: OF_STRING_ENCODING_UTF_8];
}

- (of_unichar_t)characterAtIndex: (size_t)idx
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range
{

Modified src/OFString_UTF8.h from [27665fb3c4] to [b15a7ec396].

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
	struct of_string_utf8_ivars {
		char	 *cString;
		size_t	 cStringLength;
		bool	 isUTF8;
		size_t	 length;
		bool	 hashed;
		uint32_t hash;
		char	 *freeWhenDone;
	} *restrict _s;
	struct of_string_utf8_ivars _storage;
}
@end

#ifdef __cplusplus
extern "C" {







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
	struct of_string_utf8_ivars {
		char	 *cString;
		size_t	 cStringLength;
		bool	 isUTF8;
		size_t	 length;
		bool	 hashed;
		uint32_t hash;
		char	 *_Nullable freeWhenDone;
	} *restrict _s;
	struct of_string_utf8_ivars _storage;
}
@end

#ifdef __cplusplus
extern "C" {

Modified src/OFString_UTF8.m from [62af83b584] to [0ee13f2fd8].

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

	return isUTF8;
}

size_t
of_string_utf8_get_index(const char *string, size_t position)
{
	size_t index = position;

	for (size_t i = 0; i < position; i++)
		if OF_UNLIKELY ((string[i] & 0xC0) == 0x80)
			index--;

	return index;
}

size_t
of_string_utf8_get_position(const char *string, size_t index, size_t length)
{
	for (size_t i = 0; i <= index; i++)
		if OF_UNLIKELY ((string[i] & 0xC0) == 0x80)
			if (++index > length)
				return OF_NOT_FOUND;

	return index;
}

@implementation OFString_UTF8
- init
{
	self = [super init];








|



|

|



|

|

|


|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

	return isUTF8;
}

size_t
of_string_utf8_get_index(const char *string, size_t position)
{
	size_t idx = position;

	for (size_t i = 0; i < position; i++)
		if OF_UNLIKELY ((string[i] & 0xC0) == 0x80)
			idx--;

	return idx;
}

size_t
of_string_utf8_get_position(const char *string, size_t idx, size_t length)
{
	for (size_t i = 0; i <= idx; i++)
		if OF_UNLIKELY ((string[i] & 0xC0) == 0x80)
			if (++idx > length)
				return OF_NOT_FOUND;

	return idx;
}

@implementation OFString_UTF8
- init
{
	self = [super init];

389
390
391
392
393
394
395

396





397
398
399
400





401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

	return self;
}

- initWithUTF8StringNoCopy: (char *)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{

	self = [super init];






	@try {
		size_t UTF8StringLength = strlen(UTF8String);






		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;
			UTF8StringLength -= 3;
		}

		_s = &_storage;

		_s->cString = (char *)UTF8String;
		_s->cStringLength = UTF8StringLength;

		if (freeWhenDone)
			_s->freeWhenDone = UTF8String;

		switch (of_string_utf8_check(UTF8String, UTF8StringLength,
		    &_s->length)) {
		case 1:
			_s->isUTF8 = true;
			break;
		case -1:
			@throw [OFInvalidEncodingException exception];







>
|
>
>
>
>
>




>
>
>
>
>






<
<



<
<
<







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417


418
419
420



421
422
423
424
425
426
427

	return self;
}

- initWithUTF8StringNoCopy: (char *)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{
	@try {
		self = [super init];
	} @catch (id e) {
		if (freeWhenDone)
			free(UTF8String);
		@throw e;
	}

	@try {
		size_t UTF8StringLength = strlen(UTF8String);

		_s = &_storage;

		if (freeWhenDone)
			_s->freeWhenDone = UTF8String;

		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;
			UTF8StringLength -= 3;
		}



		_s->cString = (char *)UTF8String;
		_s->cStringLength = UTF8StringLength;




		switch (of_string_utf8_check(UTF8String, UTF8StringLength,
		    &_s->length)) {
		case 1:
			_s->isUTF8 = true;
			break;
		case -1:
			@throw [OFInvalidEncodingException exception];
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

	_s->hash = hash;
	_s->hashed = true;

	return hash;
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	of_unichar_t character;

	if (index >= _s->length)
		@throw [OFOutOfRangeException exception];

	if (!_s->isUTF8)
		return _s->cString[index];

	index = of_string_utf8_get_position(_s->cString, index,
	    _s->cStringLength);

	if (of_string_utf8_decode(_s->cString + index,
	    _s->cStringLength - index, &character) <= 0)
		@throw [OFInvalidEncodingException exception];

	return character;
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range







|



|



|

|
<

|
|







948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965

966
967
968
969
970
971
972
973
974
975

	_s->hash = hash;
	_s->hashed = true;

	return hash;
}

- (of_unichar_t)characterAtIndex: (size_t)idx
{
	of_unichar_t character;

	if (idx >= _s->length)
		@throw [OFOutOfRangeException exception];

	if (!_s->isUTF8)
		return _s->cString[idx];

	idx = of_string_utf8_get_position(_s->cString, idx, _s->cStringLength);


	if (of_string_utf8_decode(_s->cString + idx,
	    _s->cStringLength - idx, &character) <= 0)
		@throw [OFInvalidEncodingException exception];

	return character;
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range

Modified src/OFSystemInfo.h from [e8b6bc242b] to [7f1cbbaaf1].

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 *
 * @return The path where user data for the application can be stored
 */
+ (OFString *)userDataPath;

/*!
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `Preferences` directory inside of
 * `NSLibraryDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 *
 * @return The path where user configuration for the application can be stored
 */
+ (OFString *)userConfigPath;

/*!
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *
 * @return The vendor of the CPU







|













|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 *
 * @return The path where user data for the application can be stored
 */
+ (nullable OFString *)userDataPath;

/*!
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `Preferences` directory inside of
 * `NSLibraryDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 *
 * @return The path where user configuration for the application can be stored
 */
+ (nullable OFString *)userConfigPath;

/*!
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *
 * @return The vendor of the CPU

Modified src/OFTCPSocket+SOCKS5.m from [08455d53f4] to [7ec0dff4e0].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

#import "socket_helpers.h"

/* Reference for static linking */
int _OFTCPSocket_SOCKS5_reference;

static void
send_or_exception(OFTCPSocket *self, of_socket_t socket, char *buffer,
    int length)
{
#ifndef OF_WINDOWS
	ssize_t bytesWritten;
#else
	int bytesWritten;
#endif

	if ((bytesWritten = send(socket, (const void *)buffer, length, 0)) < 0)
		@throw [OFWriteFailedException
		    exceptionWithObject: self
			requestedLength: length
			   bytesWritten: 0
				  errNo: of_socket_errno()];

	if ((int)bytesWritten != length)
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length
						      bytesWritten: bytesWritten
							     errNo: 0];
}

static void
recv_exact(OFTCPSocket *self, of_socket_t socket, char *buffer, int length)
{
	while (length > 0) {
		ssize_t ret = recv(socket, (void *)buffer, length, 0);

		if (ret < 0)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: length
					  errNo: of_socket_errno()];








|








|














|


|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

#import "socket_helpers.h"

/* Reference for static linking */
int _OFTCPSocket_SOCKS5_reference;

static void
send_or_exception(OFTCPSocket *self, of_socket_t sock, char *buffer,
    int length)
{
#ifndef OF_WINDOWS
	ssize_t bytesWritten;
#else
	int bytesWritten;
#endif

	if ((bytesWritten = send(sock, (const void *)buffer, length, 0)) < 0)
		@throw [OFWriteFailedException
		    exceptionWithObject: self
			requestedLength: length
			   bytesWritten: 0
				  errNo: of_socket_errno()];

	if ((int)bytesWritten != length)
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length
						      bytesWritten: bytesWritten
							     errNo: 0];
}

static void
recv_exact(OFTCPSocket *self, of_socket_t sock, char *buffer, int length)
{
	while (length > 0) {
		ssize_t ret = recv(sock, (void *)buffer, length, 0);

		if (ret < 0)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: length
					  errNo: of_socket_errno()];

Modified src/OFTCPSocket.h from [0d4361b9a8] to [91bb6c7528].

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 *
 * 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 _listening;
	struct sockaddr *_address;
	socklen_t _addressLength;
	OFString *_SOCKS5Host;
	uint16_t _SOCKS5Port;
#ifdef OF_WII
	uint16_t _port;
#endif
}

/*!







|

|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 *
 * 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 _listening;
	struct sockaddr *_Nullable _address;
	socklen_t _addressLength;
	OFString *_Nullable _SOCKS5Host;
	uint16_t _SOCKS5Port;
#ifdef OF_WII
	uint16_t _port;
#endif
}

/*!

Modified src/OFTCPSocket.m from [56b097e84a] to [51b517e269].

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block;
# endif
@end

@implementation OFTCPSocket_ConnectThread
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [socket retain];
		_host = [host copy];
		_port = port;
		_target = [target retain];
		_selector = selector;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [socket retain];
		_host = [host copy];
		_port = port;
		_block = [block copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}







|









|














|








|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block;
# endif
@end

@implementation OFTCPSocket_ConnectThread
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)sock
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [sock retain];
		_host = [host copy];
		_port = port;
		_target = [target retain];
		_selector = selector;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)sock
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [sock retain];
		_host = [host copy];
		_port = port;
		_block = [block copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{
	void *pool = objc_autoreleasePoolPush();

	@try {
		[_socket connectToHost: _host
				  port: _port];
	} @catch (OFException *e) {
		_exception = e;
	}

	[self performSelector: @selector(didConnect)
		     onThread: _sourceThread
		waitUntilDone: false];

	objc_autoreleasePoolPop(pool);







|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{
	void *pool = objc_autoreleasePoolPush();

	@try {
		[_socket connectToHost: _host
				  port: _port];
	} @catch (OFException *e) {
		_exception = [e retain];
	}

	[self performSelector: @selector(didConnect)
		     onThread: _sourceThread
		waitUntilDone: false];

	objc_autoreleasePoolPop(pool);

Modified src/OFTarArchive.h from [90a272ca60] to [9c5a85aa2e].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@interface OFTarArchive: OFObject
{
#ifdef OF_TAR_ARCHIVE_ENTRY_M
@public
#endif
	OFStream *_stream;
@protected
	OFTarArchiveEntry *_lastReturnedEntry;
}

/*!
 * @brief Creates a new OFTarArchive object with the specified stream.
 *
 * @param stream A stream from which the tar archive will be read
 * @return A new, autoreleased OFTarArchive







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@interface OFTarArchive: OFObject
{
#ifdef OF_TAR_ARCHIVE_ENTRY_M
@public
#endif
	OFStream *_stream;
@protected
	OFTarArchiveEntry *_Nullable _lastReturnedEntry;
}

/*!
 * @brief Creates a new OFTarArchive object with the specified stream.
 *
 * @param stream A stream from which the tar archive will be read
 * @return A new, autoreleased OFTarArchive
82
83
84
85
86
87
88
89
90
91
92
 * @warning Calling @ref nextEntry will invalidate all streams returned by the
 *	    previous entry! Reading from an invalidated stream will throw an
 *	    @ref OFReadFailedException!
 *
 * @return The next entry from the tar archive or `nil` if all entries have
 *	   been read
 */
- (OFTarArchiveEntry *)nextEntry;
@end

OF_ASSUME_NONNULL_END







|



82
83
84
85
86
87
88
89
90
91
92
 * @warning Calling @ref nextEntry will invalidate all streams returned by the
 *	    previous entry! Reading from an invalidated stream will throw an
 *	    @ref OFReadFailedException!
 *
 * @return The next entry from the tar archive or `nil` if all entries have
 *	   been read
 */
- (nullable OFTarArchiveEntry *)nextEntry;
@end

OF_ASSUME_NONNULL_END

Modified src/OFTarArchiveEntry.h from [37e5a4326d] to [c755caa995].

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	OFStream *_stream;
	bool _atEndOfStream;
	OFString *_fileName;
	uint32_t _mode;
	uint64_t _size, _toRead;
	OFDate *_modificationDate;
	of_tar_archive_entry_type_t _type;
	OFString *_targetFileName;
	OFString *_owner, *_group;
	uint32_t _deviceMajor, _deviceMinor;
}

/*!
 * The file name of the entry.
 */
@property (readonly, nonatomic) OFString *fileName;







|
|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	OFStream *_stream;
	bool _atEndOfStream;
	OFString *_fileName;
	uint32_t _mode;
	uint64_t _size, _toRead;
	OFDate *_modificationDate;
	of_tar_archive_entry_type_t _type;
	OFString *_Nullable _targetFileName;
	OFString *_Nullable _owner, *_Nullable _group;
	uint32_t _deviceMajor, _deviceMinor;
}

/*!
 * The file name of the entry.
 */
@property (readonly, nonatomic) OFString *fileName;

Modified src/OFTarArchiveEntry.m from [e3da7730a5] to [1b943dcfae].

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100



101
102
103
104

105
106
107
108
109
110
111
		_type = header[156];
		_targetFileName = [stringFromBuffer(header + 157, 100) copy];

		if (_type == '\0')
			_type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE;

		if (memcmp(header + 257, "ustar\0" "00", 8) == 0) {
			OFString *fileName;

			_owner = [stringFromBuffer(header + 265, 32) copy];
			_group = [stringFromBuffer(header + 297, 32) copy];

			_deviceMajor = (uint32_t)octalValueFromBuffer(
			    header + 329, 8, UINT32_MAX);
			_deviceMinor = (uint32_t)octalValueFromBuffer(
			    header + 337, 8, UINT32_MAX);




			fileName = [OFString stringWithFormat: @"%@/%@",
			    stringFromBuffer(header + 345, 155), _fileName];
			[_fileName release];
			_fileName = [fileName copy];

		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}







|









>
>
>
|
|
|
|
>







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
		_type = header[156];
		_targetFileName = [stringFromBuffer(header + 157, 100) copy];

		if (_type == '\0')
			_type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE;

		if (memcmp(header + 257, "ustar\0" "00", 8) == 0) {
			OFString *prefix;

			_owner = [stringFromBuffer(header + 265, 32) copy];
			_group = [stringFromBuffer(header + 297, 32) copy];

			_deviceMajor = (uint32_t)octalValueFromBuffer(
			    header + 329, 8, UINT32_MAX);
			_deviceMinor = (uint32_t)octalValueFromBuffer(
			    header + 337, 8, UINT32_MAX);

			prefix = stringFromBuffer(header + 345, 155);
			if ([prefix length] > 0) {
				OFString *fileName = [OFString
				    stringWithFormat: @"%@/%@",
						      prefix, _fileName];
				[_fileName release];
				_fileName = [fileName copy];
			}
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

Modified src/OFThread.h from [f3aa3dc787] to [cd0a2c76ca].

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79





80
81
82
83

84
85
86
87
88
89
90
91
92
	enum of_thread_running {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} _running;
	void *_pool;
# ifdef OF_HAVE_BLOCKS
	of_thread_block_t _threadBlock;
# endif
	id _returnValue;
	OFRunLoop *_runLoop;
	OFMutableDictionary *_threadDictionary;
@private
	OFString *_name;
}






#ifdef OF_HAVE_BLOCKS
/*!
 * The block to execute in the thread.
 */

@property (readonly, nonatomic) of_thread_block_t threadBlock;
#endif

/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */
+ (instancetype)thread;







|


|


|


>
>
>
>
>
|



>
|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
	enum of_thread_running {
		OF_THREAD_NOT_RUNNING,
		OF_THREAD_RUNNING,
		OF_THREAD_WAITING_FOR_JOIN
	} _running;
	void *_pool;
# ifdef OF_HAVE_BLOCKS
	of_thread_block_t _Nullable _threadBlock;
# endif
	id _returnValue;
	OFRunLoop *_Nullable _runLoop;
	OFMutableDictionary *_threadDictionary;
@private
	OFString *_Nullable _name;
}

/*!
 * The name for the thread to use when starting it.
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *name;

# ifdef OF_HAVE_BLOCKS
/*!
 * The block to execute in the thread.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    of_thread_block_t threadBlock;
# endif

/*!
 * @brief Creates a new thread.
 *
 * @return A new, autoreleased thread
 */
+ (instancetype)thread;
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# endif

/*!
 * @brief Returns the current thread.
 *
 * @return The current thread
 */
+ (OFThread *)currentThread;

/*!
 * @brief Returns the main thread.
 *
 * @return The main thread
 */
+ (OFThread *)mainThread;

/*!
 * @brief Returns a dictionary to store thread-specific data, meaning it
 *	  returns a different dictionary for every thread.
 *
 * @return A dictionary to store thread-specific data.
 */
+ (OFMutableDictionary *)threadDictionary;
#endif

/*!
 * @brief Suspends execution of the current thread for the specified time
 *	  interval.
 *
 * @param timeInterval The number of seconds to sleep







|






|







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# endif

/*!
 * @brief Returns the current thread.
 *
 * @return The current thread
 */
+ (nullable OFThread *)currentThread;

/*!
 * @brief Returns the main thread.
 *
 * @return The main thread
 */
+ (nullable OFThread *)mainThread;

/*!
 * @brief Returns a dictionary to store thread-specific data, meaning it
 *	  returns a different dictionary for every thread.
 *
 * @return A dictionary to store thread-specific data.
 */
+ (nullable OFMutableDictionary *)threadDictionary;
#endif

/*!
 * @brief Suspends execution of the current thread for the specified time
 *	  interval.
 *
 * @param timeInterval The number of seconds to sleep
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*!
 * @brief Returns the run loop for the thread.
 *
 * @return The run loop for the thread
 */
- (OFRunLoop *)runLoop;

/*!
 * @brief Returns the name of the thread or `nil` if none has been set.
 *
 * @return The name of the thread or nil if none has been set
 */
- (nullable OFString *)name;

/*!
 * @brief Sets the name for the thread.
 *
 * @param name The name for the thread
 */
- (void)setName: (nullable OFString *)name;

/*!
 * @brief Returns the priority of the thread.
 *
 * This is a value between -1.0 (meaning lowest priority that still schedules)
 * and +1.0 (meaning highest priority that still allows getting preempted)
 * with normal priority being 0.0 (meaning being the same as the main thread).
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<







204
205
206
207
208
209
210














211
212
213
214
215
216
217
/*!
 * @brief Returns the run loop for the thread.
 *
 * @return The run loop for the thread
 */
- (OFRunLoop *)runLoop;















/*!
 * @brief Returns the priority of the thread.
 *
 * This is a value between -1.0 (meaning lowest priority that still schedules)
 * and +1.0 (meaning highest priority that still allows getting preempted)
 * with normal priority being 0.0 (meaning being the same as the main thread).
 *

Modified src/OFThread.m from [3ff1e2b592] to [a4d40e057a].

93
94
95
96
97
98
99

100
101
102
103
104
105
106






107
108
109
110
111
112
113
static of_tlskey_t threadSelfKey;
static OFThread *mainThread;

static void
callMain(id object)
{
	OFThread *thread = (OFThread *)object;


	if (!of_tlskey_set(threadSelfKey, thread))
		@throw [OFInitializationFailedException
		    exceptionWithClass: [thread class]];

	thread->_pool = objc_autoreleasePoolPush();







	/*
	 * Nasty workaround for thread implementations which can't return a
	 * pointer on join.
	 */
# ifdef OF_HAVE_BLOCKS
	if (thread->_threadBlock != NULL)
		thread->_returnValue = [thread->_threadBlock() retain];







>







>
>
>
>
>
>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
static of_tlskey_t threadSelfKey;
static OFThread *mainThread;

static void
callMain(id object)
{
	OFThread *thread = (OFThread *)object;
	OFString *name;

	if (!of_tlskey_set(threadSelfKey, thread))
		@throw [OFInitializationFailedException
		    exceptionWithClass: [thread class]];

	thread->_pool = objc_autoreleasePoolPush();

	name = [thread name];
	if (name != nil)
		of_thread_set_name([name UTF8String]);
	else
		of_thread_set_name(object_getClassName(thread));

	/*
	 * Nasty workaround for thread implementations which can't return a
	 * pointer on join.
	 */
# ifdef OF_HAVE_BLOCKS
	if (thread->_threadBlock != NULL)
		thread->_returnValue = [thread->_threadBlock() retain];
124
125
126
127
128
129
130

131
132
133
134
135
136
137

	[thread release];
}
#endif

@implementation OFThread
#ifdef OF_HAVE_THREADS

# ifdef OF_HAVE_BLOCKS
@synthesize threadBlock = _threadBlock;
# endif

+ (void)initialize
{
	if (self != [OFThread class])







>







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

	[thread release];
}
#endif

@implementation OFThread
#ifdef OF_HAVE_THREADS
@synthesize name = _name;
# ifdef OF_HAVE_BLOCKS
@synthesize threadBlock = _threadBlock;
# endif

+ (void)initialize
{
	if (self != [OFThread class])
163
164
165
166
167
168
169



170
171
172
173
174
175
176
{
	return mainThread;
}

+ (OFMutableDictionary *)threadDictionary
{
	OFThread *thread = of_tlskey_get(threadSelfKey);




	if (thread->_threadDictionary == nil)
		thread->_threadDictionary = [[OFMutableDictionary alloc] init];

	return thread->_threadDictionary;
}
#endif







>
>
>







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
{
	return mainThread;
}

+ (OFMutableDictionary *)threadDictionary
{
	OFThread *thread = of_tlskey_get(threadSelfKey);

	if (thread == nil)
		return nil;

	if (thread->_threadDictionary == nil)
		thread->_threadDictionary = [[OFMutableDictionary alloc] init];

	return thread->_threadDictionary;
}
#endif
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

	_running = OF_THREAD_RUNNING;

	if (!of_thread_new(&_thread, callMain, self, &_attr)) {
		[self release];
		@throw [OFThreadStartFailedException exceptionWithThread: self];
	}

	if (_name != nil)
		of_thread_set_name(_thread, [_name UTF8String]);
	else
		of_thread_set_name(_thread, class_getName([self class]));
}

- (id)join
{
	if (_running == OF_THREAD_NOT_RUNNING || !of_thread_join(_thread))
		@throw [OFThreadJoinFailedException exceptionWithThread: self];








<
<
<
<
<







356
357
358
359
360
361
362





363
364
365
366
367
368
369

	_running = OF_THREAD_RUNNING;

	if (!of_thread_new(&_thread, callMain, self, &_attr)) {
		[self release];
		@throw [OFThreadStartFailedException exceptionWithThread: self];
	}





}

- (id)join
{
	if (_running == OF_THREAD_NOT_RUNNING || !of_thread_join(_thread))
		@throw [OFThreadJoinFailedException exceptionWithThread: self];

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
			_runLoop = [[OFRunLoop alloc] init];
	}
# endif

	return _runLoop;
}

- (OFString *)name
{
	return [[_name copy] autorelease];
}

- (void)setName: (OFString *)name
{
	OFString *old = name;
	_name = [name copy];
	[old release];

	if (_running == OF_THREAD_RUNNING)
		of_thread_set_name(_thread, (_name != nil
		    ? [_name UTF8String] : class_getName([self class])));
}

- (float)priority
{
	return _attr.priority;
}

- (void)setPriority: (float)priority
{







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







392
393
394
395
396
397
398
















399
400
401
402
403
404
405
			_runLoop = [[OFRunLoop alloc] init];
	}
# endif

	return _runLoop;
}

















- (float)priority
{
	return _attr.priority;
}

- (void)setPriority: (float)priority
{

Modified src/OFTimer.h from [a9d9f7dbbd] to [71d9d15e16].

41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 *
 * @brief A class for creating and firing timers.
 */
@interface OFTimer: OFObject <OFComparing>
{
	OFDate *_fireDate;
	of_time_interval_t _interval;
	id _target, _object1, _object2;

	SEL _selector;
	uint8_t _arguments;
	bool _repeats;
#ifdef OF_HAVE_BLOCKS
	of_timer_block_t _block;
#endif
	bool _valid;
#ifdef OF_HAVE_THREADS
	OFCondition *_condition;
	bool _done;
#endif
	OFRunLoop *_inRunLoop;
}

/*!
 * The time interval in which the timer will repeat, if it is a repeating
 * timer.
 */
@property (readonly, nonatomic) of_time_interval_t timeInterval;







|
>











|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 *
 * @brief A class for creating and firing timers.
 */
@interface OFTimer: OFObject <OFComparing>
{
	OFDate *_fireDate;
	of_time_interval_t _interval;
	id _target;
	id _Nullable _object1, _object2;
	SEL _selector;
	uint8_t _arguments;
	bool _repeats;
#ifdef OF_HAVE_BLOCKS
	of_timer_block_t _block;
#endif
	bool _valid;
#ifdef OF_HAVE_THREADS
	OFCondition *_condition;
	bool _done;
#endif
	OFRunLoop *_Nullable _inRunLoop;
}

/*!
 * The time interval in which the timer will repeat, if it is a repeating
 * timer.
 */
@property (readonly, nonatomic) of_time_interval_t timeInterval;

Modified src/OFUDPSocket.h from [05fb60ba2c] to [03e3db3557].

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 * @param host A pointer to an @ref OFString *. If it is not NULL, it will be
 *	       set to the host of the host / port pair.
 * @param port A pointer to an uint16_t. If it is not NULL, the port of the
 *	       host / port pair will be written to it.
 * @param address The address for which the host and port should be retrieved
 */
+ (void)getHost: (OFString *__autoreleasing _Nonnull *_Nullable)host
	andPort: (uint16_t *_Nullable)port
     forAddress: (of_udp_socket_address_t *)address;

/*!
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.







|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 * @param host A pointer to an @ref OFString *. If it is not NULL, it will be
 *	       set to the host of the host / port pair.
 * @param port A pointer to an uint16_t. If it is not NULL, the port of the
 *	       host / port pair will be written to it.
 * @param address The address for which the host and port should be retrieved
 */
+ (void)getHost: (OFString *__autoreleasing _Nonnull *_Nullable)host
	andPort: (nullable uint16_t *)port
     forAddress: (of_udp_socket_address_t *)address;

/*!
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.

Modified src/OFUDPSocket.m from [c8e3c83553] to [fdfc6330cc].

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
@end
#endif

bool
of_udp_socket_address_equal(of_udp_socket_address_t *address1,
    of_udp_socket_address_t *address2)
{
	struct sockaddr_in *sin_1, *sin_2;
#ifdef HAVE_IPV6
	struct sockaddr_in6 *sin6_1, *sin6_2;
#endif

	if (address1->address.ss_family != address2->address.ss_family)
		return false;

	switch (address1->address.ss_family) {
	case AF_INET:
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
		if (address1->length < (socklen_t)sizeof(struct sockaddr_in) ||
		    address2->length < (socklen_t)sizeof(struct sockaddr_in))
			@throw [OFInvalidArgumentException exception];
#else
		if (address1->length < 8 || address2->length < 8)
			@throw [OFInvalidArgumentException exception];
#endif

		sin_1 = (struct sockaddr_in *)&address1->address;
		sin_2 = (struct sockaddr_in *)&address2->address;

		if (sin_1->sin_port != sin_2->sin_port)
			return false;
		if (sin_1->sin_addr.s_addr != sin_2->sin_addr.s_addr)
			return false;

		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		if (address1->length < sizeof(struct sockaddr_in6) ||
		    address2->length < sizeof(struct sockaddr_in6))
			@throw [OFInvalidArgumentException exception];

		sin6_1 = (struct sockaddr_in6 *)&address1->address;
		sin6_2 = (struct sockaddr_in6 *)&address2->address;

		if (sin6_1->sin6_port != sin6_2->sin6_port)
			return false;
		if (memcmp(sin6_1->sin6_addr.s6_addr,
		    sin6_2->sin6_addr.s6_addr,
		    sizeof(sin6_1->sin6_addr.s6_addr)) != 0)
			return false;

		break;
#endif
	default:
		@throw [OFInvalidArgumentException exception];
	}

	return true;
}

uint32_t
of_udp_socket_address_hash(of_udp_socket_address_t *address)
{
	uint32_t hash = of_hash_seed;
	struct sockaddr_in *sin;
#ifdef HAVE_IPV6
	struct sockaddr_in6 *sin6;
	uint32_t subhash;
#endif

	hash += address->address.ss_family;

	switch (address->address.ss_family) {
	case AF_INET:
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
		if (address->length < (socklen_t)sizeof(struct sockaddr_in))
			@throw [OFInvalidArgumentException exception];
#else
		if (address->length < 8)
			@throw [OFInvalidArgumentException exception];
#endif

		sin = (struct sockaddr_in *)&address->address;

		hash += (sin->sin_port << 1);
		hash ^= sin->sin_addr.s_addr;

		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		if (address->length < sizeof(struct sockaddr_in6))
			@throw [OFInvalidArgumentException exception];

		sin6 = (struct sockaddr_in6 *)&address->address;

		hash += (sin6->sin6_port << 1);

		OF_HASH_INIT(subhash);

		for (size_t i = 0; i < sizeof(sin6->sin6_addr.s6_addr); i++)
			OF_HASH_ADD(subhash, sin6->sin6_addr.s6_addr[i]);

		OF_HASH_FINALIZE(subhash);

		hash ^= subhash;

		break;
#endif







|

|
















|
|

|

|









|
|

|

|
|
|















|

|















|

|
|







|

|



|
|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
@end
#endif

bool
of_udp_socket_address_equal(of_udp_socket_address_t *address1,
    of_udp_socket_address_t *address2)
{
	struct sockaddr_in *addrIn1, *addrIn2;
#ifdef HAVE_IPV6
	struct sockaddr_in6 *addrIn6_1, *addrIn6_2;
#endif

	if (address1->address.ss_family != address2->address.ss_family)
		return false;

	switch (address1->address.ss_family) {
	case AF_INET:
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
		if (address1->length < (socklen_t)sizeof(struct sockaddr_in) ||
		    address2->length < (socklen_t)sizeof(struct sockaddr_in))
			@throw [OFInvalidArgumentException exception];
#else
		if (address1->length < 8 || address2->length < 8)
			@throw [OFInvalidArgumentException exception];
#endif

		addrIn1 = (struct sockaddr_in *)&address1->address;
		addrIn2 = (struct sockaddr_in *)&address2->address;

		if (addrIn1->sin_port != addrIn2->sin_port)
			return false;
		if (addrIn1->sin_addr.s_addr != addrIn2->sin_addr.s_addr)
			return false;

		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		if (address1->length < sizeof(struct sockaddr_in6) ||
		    address2->length < sizeof(struct sockaddr_in6))
			@throw [OFInvalidArgumentException exception];

		addrIn6_1 = (struct sockaddr_in6 *)&address1->address;
		addrIn6_2 = (struct sockaddr_in6 *)&address2->address;

		if (addrIn6_1->sin6_port != addrIn6_2->sin6_port)
			return false;
		if (memcmp(addrIn6_1->sin6_addr.s6_addr,
		    addrIn6_2->sin6_addr.s6_addr,
		    sizeof(addrIn6_1->sin6_addr.s6_addr)) != 0)
			return false;

		break;
#endif
	default:
		@throw [OFInvalidArgumentException exception];
	}

	return true;
}

uint32_t
of_udp_socket_address_hash(of_udp_socket_address_t *address)
{
	uint32_t hash = of_hash_seed;
	struct sockaddr_in *addrIn;
#ifdef HAVE_IPV6
	struct sockaddr_in6 *addrIn6;
	uint32_t subhash;
#endif

	hash += address->address.ss_family;

	switch (address->address.ss_family) {
	case AF_INET:
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
		if (address->length < (socklen_t)sizeof(struct sockaddr_in))
			@throw [OFInvalidArgumentException exception];
#else
		if (address->length < 8)
			@throw [OFInvalidArgumentException exception];
#endif

		addrIn = (struct sockaddr_in *)&address->address;

		hash += (addrIn->sin_port << 1);
		hash ^= addrIn->sin_addr.s_addr;

		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		if (address->length < sizeof(struct sockaddr_in6))
			@throw [OFInvalidArgumentException exception];

		addrIn6 = (struct sockaddr_in6 *)&address->address;

		hash += (addrIn6->sin6_port << 1);

		OF_HASH_INIT(subhash);

		for (size_t i = 0; i < sizeof(addrIn6->sin6_addr.s6_addr); i++)
			OF_HASH_ADD(subhash, adrIn6->sin6_addr.s6_addr[i]);

		OF_HASH_FINALIZE(subhash);

		hash ^= subhash;

		break;
#endif

Modified src/OFURL.h from [94ac818021] to [d9d859f93e].

26
27
28
29
30
31
32
33


34
35
36
37
38
39
40
 *
 * @brief A class for parsing URLs and accessing parts of it.
 */
@interface OFURL: OFObject <OFCopying, OFMutableCopying, OFSerialization>
{
	OFString *_scheme, *_host;
	uint16_t _port;
	OFString *_user, *_password, *_path, *_parameters, *_query, *_fragment;


}

/*!
 * The scheme part of the URL.
 */
@property (readonly, nonatomic, copy) OFString *scheme;








|
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 *
 * @brief A class for parsing URLs and accessing parts of it.
 */
@interface OFURL: OFObject <OFCopying, OFMutableCopying, OFSerialization>
{
	OFString *_scheme, *_host;
	uint16_t _port;
	OFString *_Nullable _user, *_Nullable _password, *_path;
	OFString *_Nullable _parameters, *_Nullable _query;
	OFString *_Nullable _fragment;
}

/*!
 * The scheme part of the URL.
 */
@property (readonly, nonatomic, copy) OFString *scheme;

Modified src/OFURL.m from [114ec293ed] to [2082375f0b].

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
				_user = [[OFString alloc]
				    initWithUTF8String: UTF8String];

			UTF8String = tmp2;
		}

		if ((tmp2 = strchr(UTF8String, ':')) != NULL) {
			void *pool;
			OFString *portString;

			*tmp2 = '\0';
			tmp2++;

			_host = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			pool = objc_autoreleasePoolPush();
			portString = [OFString stringWithUTF8String: tmp2];

			if ([portString decimalValue] > 65535)
				@throw [OFInvalidFormatException exception];

			_port = [portString decimalValue];

			objc_autoreleasePoolPop(pool);
		} else {
			_host = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			if ([_scheme isEqual: @"http"])
				_port = 80;
			else if ([_scheme isEqual: @"https"])







|








|







|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
				_user = [[OFString alloc]
				    initWithUTF8String: UTF8String];

			UTF8String = tmp2;
		}

		if ((tmp2 = strchr(UTF8String, ':')) != NULL) {
			void *pool2;
			OFString *portString;

			*tmp2 = '\0';
			tmp2++;

			_host = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			pool2 = objc_autoreleasePoolPush();
			portString = [OFString stringWithUTF8String: tmp2];

			if ([portString decimalValue] > 65535)
				@throw [OFInvalidFormatException exception];

			_port = [portString decimalValue];

			objc_autoreleasePoolPop(pool2);
		} else {
			_host = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			if ([_scheme isEqual: @"http"])
				_port = 80;
			else if ([_scheme isEqual: @"https"])

Modified src/OFXMLAttribute.h from [3dd574a92f] to [30a9d4482b].

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * @class OFXMLAttribute OFXMLAttribute.h ObjFW/OFXMLAttribute.h
 *
 * @brief A representation of an attribute of an XML element as an object.
 */
@interface OFXMLAttribute: OFXMLNode
{
@public
	OFString *_name, *_namespace, *_stringValue;
}

/*!
 * The name of the attribute.
 */
@property (readonly, nonatomic) OFString *name;








|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * @class OFXMLAttribute OFXMLAttribute.h ObjFW/OFXMLAttribute.h
 *
 * @brief A representation of an attribute of an XML element as an object.
 */
@interface OFXMLAttribute: OFXMLNode
{
@public
	OFString *_name, *_Nullable _namespace, *_stringValue;
}

/*!
 * The name of the attribute.
 */
@property (readonly, nonatomic) OFString *name;

Modified src/OFXMLElement.h from [2f9d064e3a] to [f3e2075c5a].

28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
/*!
 * @class OFXMLElement OFXMLElement.h ObjFW/OFXMLElement.h
 *
 * @brief A class which stores an XML element.
 */
@interface OFXMLElement: OFXMLNode
{
	OFString *_name, *_namespace, *_defaultNamespace;
	OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_namespaces;

	OFMutableArray OF_GENERIC(OFXMLNode *) *_children;
}

/*!
 * The name of the element.
 */
@property (nonatomic, copy) OFString *name;








|
|
|
>
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*!
 * @class OFXMLElement OFXMLElement.h ObjFW/OFXMLElement.h
 *
 * @brief A class which stores an XML element.
 */
@interface OFXMLElement: OFXMLNode
{
	OFString *_name, *_Nullable _namespace, *_Nullable _defaultNamespace;
	OFMutableArray OF_GENERIC(OFXMLAttribute *) *_Nullable _attributes;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_Nullable
	    _namespaces;
	OFMutableArray OF_GENERIC(OFXMLNode *) *_Nullable _children;
}

/*!
 * The name of the element.
 */
@property (nonatomic, copy) OFString *name;

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

/*!
 * @brief Returns the attribute with the specified name.
 *
 * @param attributeName The name of the attribute
 * @return The attribute with the specified name
 */
- (OFXMLAttribute *)attributeForName: (OFString *)attributeName;

/*!
 * @brief Returns the attribute with the specified name and namespace.
 *
 * @param attributeName The name of the attribute
 * @param attributeNS The namespace of the attribute
 * @return The attribute with the specified name and namespace
 */
- (OFXMLAttribute *)attributeForName: (OFString *)attributeName
			   namespace: (nullable OFString *)attributeNS;

/*!
 * @brief Removes the attribute with the specified name.
 *
 * @param attributeName The name of the attribute
 */
- (void)removeAttributeForName: (OFString *)attributeName;







|








|
|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/*!
 * @brief Returns the attribute with the specified name.
 *
 * @param attributeName The name of the attribute
 * @return The attribute with the specified name
 */
- (nullable OFXMLAttribute *)attributeForName: (OFString *)attributeName;

/*!
 * @brief Returns the attribute with the specified name and namespace.
 *
 * @param attributeName The name of the attribute
 * @param attributeNS The namespace of the attribute
 * @return The attribute with the specified name and namespace
 */
- (nullable OFXMLAttribute *)attributeForName: (OFString *)attributeName
				    namespace: (nullable OFString *)attributeNS;

/*!
 * @brief Removes the attribute with the specified name.
 *
 * @param attributeName The name of the attribute
 */
- (void)removeAttributeForName: (OFString *)attributeName;
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428

/*!
 * @brief Returns the first child element with the specified name.
 *
 * @param elementName The name of the element
 * @return The first child element with the specified name
 */
- (OFXMLElement *)elementForName: (OFString *)elementName;

/*!
 * @brief Returns the child elements with the specified name.
 *
 * @param elementName The name of the elements
 * @return The child elements with the specified name
 */
- (OFArray OF_GENERIC(OFXMLElement *) *)elementsForName:
    (OFString *)elementName;

/*!
 * @brief Returns the first child element with the specified name and namespace.
 *
 * @param elementName The name of the element
 * @param elementNS The namespace of the element
 * @return The first child element with the specified name and namespace
 */
- (OFXMLElement *)elementForName: (OFString *)elementName
		       namespace: (nullable OFString *)elementNS;

/*!
 * @brief Returns the child elements with the specified name and namespace.
 *
 * @param elementName The name of the elements
 * @param elementNS The namespace of the elements
 * @return The child elements with the specified name and namespace







|

















|
|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

/*!
 * @brief Returns the first child element with the specified name.
 *
 * @param elementName The name of the element
 * @return The first child element with the specified name
 */
- (nullable OFXMLElement *)elementForName: (OFString *)elementName;

/*!
 * @brief Returns the child elements with the specified name.
 *
 * @param elementName The name of the elements
 * @return The child elements with the specified name
 */
- (OFArray OF_GENERIC(OFXMLElement *) *)elementsForName:
    (OFString *)elementName;

/*!
 * @brief Returns the first child element with the specified name and namespace.
 *
 * @param elementName The name of the element
 * @param elementNS The namespace of the element
 * @return The first child element with the specified name and namespace
 */
- (nullable OFXMLElement *)elementForName: (OFString *)elementName
				namespace: (nullable OFString *)elementNS;

/*!
 * @brief Returns the child elements with the specified name and namespace.
 *
 * @param elementName The name of the elements
 * @param elementNS The namespace of the elements
 * @return The child elements with the specified name and namespace

Modified src/OFXMLElement.m from [28440d417d] to [1630a09e19].

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
{
	return [[_attributes copy] autorelease];
}

- (void)setChildren: (OFArray *)children
{
	OFArray *old = _children;
	_children = [children copy];
	[old release];
}

- (OFArray *)children
{
	return [[_children copy] autorelease];
}







|







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
{
	return [[_attributes copy] autorelease];
}

- (void)setChildren: (OFArray *)children
{
	OFArray *old = _children;
	_children = [children mutableCopy];
	[old release];
}

- (OFArray *)children
{
	return [[_children copy] autorelease];
}
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
	if (_children == nil)
		_children = [[OFMutableArray alloc] init];

	[_children addObject: child];
}

- (void)insertChild: (OFXMLNode *)child
	    atIndex: (size_t)index
{
	if ([child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	if (_children == nil)
		_children = [[OFMutableArray alloc] init];

	[_children insertObject: child
			atIndex: index];
}

- (void)insertChildren: (OFArray *)children
	       atIndex: (size_t)index
{
	for (OFXMLNode *node in children)
		if ([node isKindOfClass: [OFXMLAttribute class]])
			@throw [OFInvalidArgumentException exception];

	[_children insertObjectsFromArray: children
				  atIndex: index];
}

- (void)removeChild: (OFXMLNode *)child
{
	if ([child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children removeObject: child];
}

- (void)removeChildAtIndex: (size_t)index
{
	[_children removeObjectAtIndex: index];
}

- (void)replaceChild: (OFXMLNode *)child
	    withNode: (OFXMLNode *)node
{
	if ([node isKindOfClass: [OFXMLAttribute class]] ||
	    [child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children replaceObject: child
		      withObject: node];
}

- (void)replaceChildAtIndex: (size_t)index
		   withNode: (OFXMLNode *)node
{
	if ([node isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children replaceObjectAtIndex: index
			     withObject: node];
}

- (OFXMLElement *)elementForName: (OFString *)elementName
{
	return [[self elementsForName: elementName] firstObject];
}







|








|



|






|










|

|













|





|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
	if (_children == nil)
		_children = [[OFMutableArray alloc] init];

	[_children addObject: child];
}

- (void)insertChild: (OFXMLNode *)child
	    atIndex: (size_t)idx
{
	if ([child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	if (_children == nil)
		_children = [[OFMutableArray alloc] init];

	[_children insertObject: child
			atIndex: idx];
}

- (void)insertChildren: (OFArray *)children
	       atIndex: (size_t)idx
{
	for (OFXMLNode *node in children)
		if ([node isKindOfClass: [OFXMLAttribute class]])
			@throw [OFInvalidArgumentException exception];

	[_children insertObjectsFromArray: children
				  atIndex: idx];
}

- (void)removeChild: (OFXMLNode *)child
{
	if ([child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children removeObject: child];
}

- (void)removeChildAtIndex: (size_t)idx
{
	[_children removeObjectAtIndex: idx];
}

- (void)replaceChild: (OFXMLNode *)child
	    withNode: (OFXMLNode *)node
{
	if ([node isKindOfClass: [OFXMLAttribute class]] ||
	    [child isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children replaceObject: child
		      withObject: node];
}

- (void)replaceChildAtIndex: (size_t)idx
		   withNode: (OFXMLNode *)node
{
	if ([node isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	[_children replaceObjectAtIndex: idx
			     withObject: node];
}

- (OFXMLElement *)elementForName: (OFString *)elementName
{
	return [[self elementsForName: elementName] firstObject];
}

Modified src/OFXMLElementBuilder.h from [f7df881b5d] to [fb6eb4c1ba].

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 * It can also be used to build OFXMLElements from parts of the document by
 * first parsing stuff using the OFXMLParser with another delegate and then
 * setting the OFXMLElementBuilder as delegate for the parser.
 */
@interface OFXMLElementBuilder: OFObject <OFXMLParserDelegate>
{
	OFMutableArray OF_GENERIC(OFXMLElement *) *_stack;
	id <OFXMLElementBuilderDelegate> _delegate;
}

/*!
 * The delegate for the OFXMLElementBuilder.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, assign)
    id <OFXMLElementBuilderDelegate> delegate;







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 * It can also be used to build OFXMLElements from parts of the document by
 * first parsing stuff using the OFXMLParser with another delegate and then
 * setting the OFXMLElementBuilder as delegate for the parser.
 */
@interface OFXMLElementBuilder: OFObject <OFXMLParserDelegate>
{
	OFMutableArray OF_GENERIC(OFXMLElement *) *_stack;
	id <OFXMLElementBuilderDelegate> _Nullable _delegate;
}

/*!
 * The delegate for the OFXMLElementBuilder.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, assign)
    id <OFXMLElementBuilderDelegate> delegate;

Modified src/OFXMLParser.h from [66eb0bc029] to [f9d631bcc2].

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
 * it is not known to the callback as well, in which case an exception will be
 * risen.
 *
 * @param parser The parser which found an unknown entity
 * @param entity The name of the entity the XML parser didn't know
 * @return A substitution for the entity or `nil`
 */
-      (OFString *)parser: (OFXMLParser *)parser
  foundUnknownEntityNamed: (OFString *)entity;
@end

/*!
 * @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h
 *
 * @brief An event-based XML parser.
 *
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon as it finds something, thus suitable for streams as well.
 */
@interface OFXMLParser: OFObject <OFStringXMLUnescapingDelegate>
{
	id <OFXMLParserDelegate> _delegate;
	enum of_xml_parser_state {
		OF_XMLPARSER_IN_BYTE_ORDER_MARK,
		OF_XMLPARSER_OUTSIDE_TAG,
		OF_XMLPARSER_TAG_OPENED,
		OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS,
		OF_XMLPARSER_IN_TAG_NAME,
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,







|
|












|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
 * it is not known to the callback as well, in which case an exception will be
 * risen.
 *
 * @param parser The parser which found an unknown entity
 * @param entity The name of the entity the XML parser didn't know
 * @return A substitution for the entity or `nil`
 */
- (nullable OFString *)parser: (OFXMLParser *)parser
      foundUnknownEntityNamed: (OFString *)entity;
@end

/*!
 * @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h
 *
 * @brief An event-based XML parser.
 *
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon as it finds something, thus suitable for streams as well.
 */
@interface OFXMLParser: OFObject <OFStringXMLUnescapingDelegate>
{
	id <OFXMLParserDelegate> _Nullable _delegate;
	enum of_xml_parser_state {
		OF_XMLPARSER_IN_BYTE_ORDER_MARK,
		OF_XMLPARSER_OUTSIDE_TAG,
		OF_XMLPARSER_TAG_OPENED,
		OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS,
		OF_XMLPARSER_IN_TAG_NAME,
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		OF_XMLPARSER_IN_COMMENT_OPENING,
		OF_XMLPARSER_IN_COMMENT_1,
		OF_XMLPARSER_IN_COMMENT_2,
		OF_XMLPARSER_IN_DOCTYPE,
		OF_XMLPARSER_NUM_STATES
	} _state;
	size_t _i, _last;
	const char *_data;
	OFMutableData *_buffer;
	OFString *_name, *_prefix;
	OFMutableArray
	    OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *)
	    *_namespaces;
	OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes;
	OFString *_attributeName, *_attributePrefix;
	char _delimiter;
	OFMutableArray OF_GENERIC(OFString *) *_previous;
	size_t _level;
	bool _acceptProlog;
	size_t _lineNumber;
	bool _lastCarriageReturn, _finishedParsing;
	of_string_encoding_t _encoding;







|

|




|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		OF_XMLPARSER_IN_COMMENT_OPENING,
		OF_XMLPARSER_IN_COMMENT_1,
		OF_XMLPARSER_IN_COMMENT_2,
		OF_XMLPARSER_IN_DOCTYPE,
		OF_XMLPARSER_NUM_STATES
	} _state;
	size_t _i, _last;
	const char *_Nullable _data;
	OFMutableData *_buffer;
	OFString *_Nullable _name, *_Nullable _prefix;
	OFMutableArray
	    OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *)
	    *_namespaces;
	OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes;
	OFString *_Nullable _attributeName, *_Nullable _attributePrefix;
	char _delimiter;
	OFMutableArray OF_GENERIC(OFString *) *_previous;
	size_t _level;
	bool _acceptProlog;
	size_t _lineNumber;
	bool _lastCarriageReturn, _finishedParsing;
	of_string_encoding_t _encoding;

Modified src/OFZIPArchive.h from [b61ed08fb0] to [c1d40e93ed].

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@interface OFZIPArchive: OFObject
{
	OFSeekableStream *_stream;
	uint32_t _diskNumber, _centralDirectoryDisk;
	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_archiveComment;
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)
	    *_pathToEntryMap;
	OFStream *_lastReturnedStream;
}

/*!
 * The archive comment.
 */
@property (readonly, nonatomic) OFString *archiveComment;








|



|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@interface OFZIPArchive: OFObject
{
	OFSeekableStream *_stream;
	uint32_t _diskNumber, _centralDirectoryDisk;
	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_Nullable _archiveComment;
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)
	    *_pathToEntryMap;
	OFStream *_Nullable _lastReturnedStream;
}

/*!
 * The archive comment.
 */
@property (readonly, nonatomic) OFString *archiveComment;

Modified src/OFZIPArchive.m from [8c3891b987] to [cf738fc904].

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
- initWithStream: (OFStream *)stream;
- (bool)matchesEntry: (OFZIPArchiveEntry *)entry;
@end

@interface OFZIPArchive_FileStream: OFStream
{
	OFStream *_stream, *_decompressedStream;
	OFZIPArchive_LocalFileHeader *_localFileHeader;
	bool _hasDataDescriptor;
	uint64_t _size;
	uint32_t _CRC32;
	bool _atEndOfStream;
}

-  initWithStream: (OFStream *)path
  localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader;
@end

uint32_t
of_zip_archive_read_field32(const uint8_t **data, uint16_t *size)
{
	uint32_t field = 0;








|
<
|





|







69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
- initWithStream: (OFStream *)stream;
- (bool)matchesEntry: (OFZIPArchiveEntry *)entry;
@end

@interface OFZIPArchive_FileStream: OFStream
{
	OFStream *_stream, *_decompressedStream;
	OFZIPArchiveEntry *_entry;

	uint64_t _toRead;
	uint32_t _CRC32;
	bool _atEndOfStream;
}

-  initWithStream: (OFStream *)path
	    entry: (OFZIPArchiveEntry *)localFileHeader;
@end

uint32_t
of_zip_archive_read_field32(const uint8_t **data, uint16_t *size)
{
	uint32_t field = 0;

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];
	}

	_lastReturnedStream = [[OFZIPArchive_FileStream alloc]
	     initWithStream: _stream
	    localFileHeader: localFileHeader];

	objc_autoreleasePoolPop(pool);

	return _lastReturnedStream;
}
@end








|







355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];
	}

	_lastReturnedStream = [[OFZIPArchive_FileStream alloc]
	     initWithStream: _stream
		      entry: entry];

	objc_autoreleasePoolPop(pool);

	return _lastReturnedStream;
}
@end

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

	return true;
}
@end

@implementation OFZIPArchive_FileStream
-  initWithStream: (OFStream *)stream
  localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader
{
	self = [super init];

	@try {
		_stream = [stream retain];

		switch (localFileHeader->_compressionMethod) {
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE:
			_decompressedStream = [stream retain];
			break;
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE:
			_decompressedStream = [[OFInflateStream alloc]
			    initWithStream: stream];
			break;
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE64:
			_decompressedStream = [[OFInflate64Stream alloc]
			    initWithStream: stream];
			break;
		default:
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
		}

		_localFileHeader = [localFileHeader retain];
		_hasDataDescriptor = (localFileHeader->_generalPurposeBitFlag &
		    (1 << 3));
		_size = localFileHeader->_uncompressedSize;
		_CRC32 = ~0;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[self close];


	[_decompressedStream release];
	[_localFileHeader release];

	[super dealloc];
}

- (bool)lowlevelIsAtEndOfStream
{
	return _atEndOfStream;
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer
			  length: (size_t)length
{
	size_t min, ret;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_atEndOfStream)
		return 0;

	if (_hasDataDescriptor) {
		if ([_decompressedStream isAtEndOfStream]) {
			uint32_t CRC32;

			_atEndOfStream = true;

			CRC32 = [_stream readLittleEndianInt32];
			if (CRC32 == 0x08074B50)
				CRC32 = [_stream readLittleEndianInt32];

			if (~_CRC32 != CRC32)
				@throw [OFChecksumFailedException exception];


			/*
			 * FIXME: Check (un)compressed length!
			 * (Note: Both are 64 bit if the entry uses ZIP64!)
			 */

			return 0;
		}

		ret = [_decompressedStream readIntoBuffer: buffer
						   length: length];
	} else {
		if (_size == 0) {
			_atEndOfStream = true;

			if (~_CRC32 != _localFileHeader->_CRC32)
				@throw [OFChecksumFailedException exception];

			return 0;
		}

		min = (length < _size ? length : (size_t)_size);
		ret = [_decompressedStream readIntoBuffer: buffer
						   length: min];
		_size -= ret;
	}

	_CRC32 = of_crc32(_CRC32, buffer, ret);

	return ret;
}

- (void)close
{
	[_stream release];
	_stream = nil;

	[super close];
}
@end







|






|

















|
<
<
|













>

|












|







<
<
<
|
<
|
<
<
<
<
<
|
>

<
|
<
<
|
<
|
<
|
|
|
|
|

<
<
|
|
|
|
<
|
<
<
<
|
<












448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480


481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517



518

519





520
521
522

523


524

525

526
527
528
529
530
531


532
533
534
535

536



537

538
539
540
541
542
543
544
545
546
547
548
549

	return true;
}
@end

@implementation OFZIPArchive_FileStream
-  initWithStream: (OFStream *)stream
	    entry: (OFZIPArchiveEntry *)entry
{
	self = [super init];

	@try {
		_stream = [stream retain];

		switch ([entry compressionMethod]) {
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE:
			_decompressedStream = [stream retain];
			break;
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE:
			_decompressedStream = [[OFInflateStream alloc]
			    initWithStream: stream];
			break;
		case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE64:
			_decompressedStream = [[OFInflate64Stream alloc]
			    initWithStream: stream];
			break;
		default:
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
		}

		_entry = [entry retain];


		_toRead = [entry uncompressedSize];
		_CRC32 = ~0;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[self close];

	[_stream release];
	[_decompressedStream release];
	[_entry release];

	[super dealloc];
}

- (bool)lowlevelIsAtEndOfStream
{
	return _atEndOfStream;
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer
			  length: (size_t)length
{
	size_t ret;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_atEndOfStream)
		return 0;




#if SIZE_MAX >= UINT64_MAX

	if (length > UINT64_MAX)





		@throw [OFOutOfRangeException exception];
#endif


	if ((uint64_t)length > _toRead)


		length = (size_t)_toRead;



	ret = [_decompressedStream readIntoBuffer: buffer
					   length: length];

	if (ret == 0)
		_atEndOfStream = true;



	_toRead -= ret;
	_CRC32 = of_crc32(_CRC32, buffer, ret);

	if (_toRead == 0)

		if (~_CRC32 != [_entry CRC32])



			@throw [OFChecksumFailedException exception];


	return ret;
}

- (void)close
{
	[_stream release];
	_stream = nil;

	[super close];
}
@end

Modified src/OFZIPArchiveEntry.h from [0e65bfdec8] to [708bd90b86].

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
{
	uint16_t _versionMadeBy, _minVersionNeeded, _generalPurposeBitFlag;
	uint16_t _compressionMethod;
	uint16_t _lastModifiedFileTime, _lastModifiedFileDate;
	uint32_t _CRC32;
	uint64_t _compressedSize, _uncompressedSize;
	OFString *_fileName;
	OFData *_extraField;
	OFString *_fileComment;
	uint32_t _startDiskNumber;
	uint16_t _internalAttributes;
	uint32_t _versionSpecificAttributes;
	int64_t _localFileHeaderOffset;
}

/*!







|
|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
{
	uint16_t _versionMadeBy, _minVersionNeeded, _generalPurposeBitFlag;
	uint16_t _compressionMethod;
	uint16_t _lastModifiedFileTime, _lastModifiedFileDate;
	uint32_t _CRC32;
	uint64_t _compressedSize, _uncompressedSize;
	OFString *_fileName;
	OFData *_Nullable _extraField;
	OFString *_Nullable _fileComment;
	uint32_t _startDiskNumber;
	uint16_t _internalAttributes;
	uint32_t _versionSpecificAttributes;
	int64_t _localFileHeaderOffset;
}

/*!

Modified src/block.h from [a2c827d522] to [6fd563cf3c].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#endif
	int flags;
	int reserved;
	void (*invoke)(void *block, ...);
	struct of_block_descriptor_t {
		unsigned long reserved;
		unsigned long size;
		void (*copy_helper)(void *dest, void *src);
		void (*dispose_helper)(void *src);
		const char *signature;
	} *descriptor;
} of_block_literal_t;

#ifdef __cplusplus
extern "C" {
#endif







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#endif
	int flags;
	int reserved;
	void (*invoke)(void *block, ...);
	struct of_block_descriptor_t {
		unsigned long reserved;
		unsigned long size;
		void (*_Nullable copy_helper)(void *dest, void *src);
		void (*_Nullable dispose_helper)(void *src);
		const char *signature;
	} *descriptor;
} of_block_literal_t;

#ifdef __cplusplus
extern "C" {
#endif

Modified src/bridge/NSArray+OFObject.h from [809f57cb1e] to [5da20e887d].

14
15
16
17
18
19
20

21

22
23
24
25
26
27
28
29
30
31

32

 * file.
 */

#import <Foundation/NSArray.h>

#import "NSBridging.h"


NS_ASSUME_NONNULL_BEGIN


/*!
 * @category NSArray (OFObject) \
 *	     NSArray+OFObject.h ObjFW-Bridge/NSArray+OFObject.h
 *
 * @brief Support for bridging NSArrays to OFArrays.
 */
@interface NSArray (OFObject) <NSBridging>
@end


NS_ASSUME_NONNULL_END








>

>










>

>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 * file.
 */

#import <Foundation/NSArray.h>

#import "NSBridging.h"

#ifdef NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_BEGIN
#endif

/*!
 * @category NSArray (OFObject) \
 *	     NSArray+OFObject.h ObjFW-Bridge/NSArray+OFObject.h
 *
 * @brief Support for bridging NSArrays to OFArrays.
 */
@interface NSArray (OFObject) <NSBridging>
@end

#ifdef NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
#endif

Modified src/bridge/NSArray_OFArray.h from [fa0ba160b6] to [4744ea3293].

14
15
16
17
18
19
20

21

22
23
24
25
26
27
28
29
30

31

 * file.
 */

#import <Foundation/NSArray.h>

@class OFArray;


NS_ASSUME_NONNULL_BEGIN


@interface NSArray_OFArray: NSArray
{
	OFArray *_array;
}

- initWithOFArray: (OFArray *)array;
@end


NS_ASSUME_NONNULL_END








>

>









>

>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 * file.
 */

#import <Foundation/NSArray.h>

@class OFArray;

#ifdef NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_BEGIN
#endif

@interface NSArray_OFArray: NSArray
{
	OFArray *_array;
}

- initWithOFArray: (OFArray *)array;
@end

#ifdef NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
#endif

Modified src/bridge/NSArray_OFArray.m from [ab0fe4a97d] to [9048491627].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
			return nil;
		}
	}

	return self;
}

- (id)objectAtIndex: (NSUInteger)index
{
	id object = [_array objectAtIndex: index];

	if ([(OFObject *)object conformsToProtocol: @protocol(OFBridging)])
		return [object NSObject];

	return object;
}








|

|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
			return nil;
		}
	}

	return self;
}

- (id)objectAtIndex: (NSUInteger)idx
{
	id object = [_array objectAtIndex: idx];

	if ([(OFObject *)object conformsToProtocol: @protocol(OFBridging)])
		return [object NSObject];

	return object;
}

Modified src/bridge/NSDictionary+OFObject.h from [d446c3feff] to [2738a1e15f].

14
15
16
17
18
19
20

21

22
23
24
25
26
27
28
29
30
31

32

 * file.
 */

#import <Foundation/NSDictionary.h>

#import "NSBridging.h"


NS_ASSUME_NONNULL_BEGIN


/*!
 * @category NSDictionary (OFObject) \
 *	     NSDictionary+OFObject.h ObjFW-Bridge/NSDictionary+OFObject.h
 *
 * @brief Support for bridging NSDictionaries to OFDictionaries.
 */
@interface NSDictionary (OFObject) <NSBridging>
@end


NS_ASSUME_NONNULL_END








>

>










>

>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 * file.
 */

#import <Foundation/NSDictionary.h>

#import "NSBridging.h"

#ifdef NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_BEGIN
#endif

/*!
 * @category NSDictionary (OFObject) \
 *	     NSDictionary+OFObject.h ObjFW-Bridge/NSDictionary+OFObject.h
 *
 * @brief Support for bridging NSDictionaries to OFDictionaries.
 */
@interface NSDictionary (OFObject) <NSBridging>
@end

#ifdef NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
#endif

Modified src/bridge/NSDictionary_OFDictionary.h from [a63731835d] to [c7bdcee03e].

14
15
16
17
18
19
20

21

22
23
24
25
26
27
28
29
30

31

 * file.
 */

#import <Foundation/NSDictionary.h>

@class OFDictionary;


NS_ASSUME_NONNULL_BEGIN


@interface NSDictionary_OFDictionary: NSDictionary
{
	OFDictionary *_dictionary;
}

- initWithOFDictionary: (OFDictionary *)dictionary;
@end


NS_ASSUME_NONNULL_END








>

>









>

>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 * file.
 */

#import <Foundation/NSDictionary.h>

@class OFDictionary;

#ifdef NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_BEGIN
#endif

@interface NSDictionary_OFDictionary: NSDictionary
{
	OFDictionary *_dictionary;
}

- initWithOFDictionary: (OFDictionary *)dictionary;
@end

#ifdef NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
#endif

Modified src/bridge/NSString+OFObject.h from [e98c3df1ce] to [523c8eea31].

14
15
16
17
18
19
20

21

22
23
24
25
26
27
28
29
30
31
32
33
34
35

36

 * file.
 */

#import <Foundation/NSString.h>

#import "NSBridging.h"


NS_ASSUME_NONNULL_BEGIN


/*!
 * @category NSString (OFObject)
 *	     NSString+OFObject.h ObjFW-Bridge/NSString+OFObject.h
 *
 * @brief Support for bridging NSStrings to OFStrings.
 *
 * Unfortunately, they need to be copied, as NSString is not capable of
 * handling UCS-4 properly (a character of NSString is only 2 bytes, while a
 * character of OFString is 4).
 */
@interface NSString (OFObject) <NSBridging>
@end


NS_ASSUME_NONNULL_END








>

>














>

>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 * file.
 */

#import <Foundation/NSString.h>

#import "NSBridging.h"

#ifdef NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_BEGIN
#endif

/*!
 * @category NSString (OFObject)
 *	     NSString+OFObject.h ObjFW-Bridge/NSString+OFObject.h
 *
 * @brief Support for bridging NSStrings to OFStrings.
 *
 * Unfortunately, they need to be copied, as NSString is not capable of
 * handling UCS-4 properly (a character of NSString is only 2 bytes, while a
 * character of OFString is 4).
 */
@interface NSString (OFObject) <NSBridging>
@end

#ifdef NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
#endif

Modified src/bridge/OFArray_NSArray.m from [94ceef5c3f] to [541b962ef5].

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
		[self release];
		@throw e;
	}

	return self;
}

- (id)objectAtIndex: (size_t)index
{
	id object;

	if (index > NSUIntegerMax)
		@throw [OFOutOfRangeException exception];

	object = [_array objectAtIndex: index];

	if ([(NSObject *)object conformsToProtocol: @protocol(NSBridging)])
		return [object OFObject];

	return object;
}

- (size_t)count
{
	return [_array count];
}
@end







|



|


|












37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
		[self release];
		@throw e;
	}

	return self;
}

- (id)objectAtIndex: (size_t)idx
{
	id object;

	if (idx > NSUIntegerMax)
		@throw [OFOutOfRangeException exception];

	object = [_array objectAtIndex: idx];

	if ([(NSObject *)object conformsToProtocol: @protocol(NSBridging)])
		return [object OFObject];

	return object;
}

- (size_t)count
{
	return [_array count];
}
@end

Modified src/bridge/OFString+NSObject.m from [f1289a59f8] to [d89258eedd].

14
15
16
17
18
19
20


21
22
23
24
25






26
 * file.
 */

#import <Foundation/NSString.h>

#import "OFString+NSObject.h"



@implementation OFString (NSObject)
- (id)NSObject
{
	return [NSString stringWithUTF8String: [self UTF8String]];
}






@end







>
>



|
|
>
>
>
>
>
>

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * file.
 */

#import <Foundation/NSString.h>

#import "OFString+NSObject.h"

#import "OFInitializationFailedException.h"

@implementation OFString (NSObject)
- (id)NSObject
{
	NSString *string = [NSString stringWithUTF8String: [self UTF8String]];

	if (string == nil)
		@throw [OFInitializationFailedException
		    exceptionWithClass: [NSString class]];

	return string;
}
@end

Modified src/encodings/codepage_437.m from [c1aa2005c6] to [8cf0d5a40f].

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
of_unicode_to_codepage_437(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
of_unicode_to_codepage_437(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/codepage_850.m from [59298ea7e4] to [42a9f55d3e].

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
of_unicode_to_codepage_850(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
of_unicode_to_codepage_850(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/codepage_858.m from [d4ab6dcec9] to [a1c541d3cd].

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
of_unicode_to_codepage_858(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
of_unicode_to_codepage_858(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/common.h from [8b3b315d4d] to [321ef98b23].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#define CASE_MISSING_IS_KEEP(nr)				\
	case nr:						\
		if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) {	\
			output[i] = (unsigned char)c;		\
			continue;				\
		}						\
								\
		index = (c & 0xFF) - page##nr##Start;		\
								\
		if (index >= sizeof(page##nr)) {		\
			output[i] = (unsigned char)c;		\
			continue;				\
		}						\
								\
		if (page##nr[index] == 0x00) {			\
			if (lossy) {				\
				output[i] = '?';		\
				continue;			\
			} else					\
				return false;			\
		}						\
								\
		output[i] = page##nr[index];			\
		break;
#define CASE_MISSING_IS_ERROR(nr)					 \
	case 0x##nr:							 \
		if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) {		 \
			if (lossy) {					 \
				output[i] = '?';			 \
				continue;				 \
			} else						 \
				return false;				 \
		}							 \
									 \
		index = (c & 0xFF) - page##nr##Start;			 \
									 \
		if (index >= sizeof(page##nr) || page##nr[index] == 0) { \
			if (lossy) {					 \
				output[i] = '?';			 \
				continue;				 \
			} else						 \
				return false;				 \
		}							 \
									 \
		output[i] = page##nr[index];				 \
		break;







|

|




|







|











|

|







|

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#define CASE_MISSING_IS_KEEP(nr)				\
	case nr:						\
		if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) {	\
			output[i] = (unsigned char)c;		\
			continue;				\
		}						\
								\
		idx = (c & 0xFF) - page##nr##Start;		\
								\
		if (idx >= sizeof(page##nr)) {			\
			output[i] = (unsigned char)c;		\
			continue;				\
		}						\
								\
		if (page##nr[idx] == 0x00) {			\
			if (lossy) {				\
				output[i] = '?';		\
				continue;			\
			} else					\
				return false;			\
		}						\
								\
		output[i] = page##nr[idx];			\
		break;
#define CASE_MISSING_IS_ERROR(nr)					 \
	case 0x##nr:							 \
		if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) {		 \
			if (lossy) {					 \
				output[i] = '?';			 \
				continue;				 \
			} else						 \
				return false;				 \
		}							 \
									 \
		idx = (c & 0xFF) - page##nr##Start;			 \
									 \
		if (idx >= sizeof(page##nr) || page##nr[idx] == 0) { \
			if (lossy) {					 \
				output[i] = '?';			 \
				continue;				 \
			} else						 \
				return false;				 \
		}							 \
									 \
		output[i] = page##nr[idx];				 \
		break;

Modified src/encodings/iso_8859_15.m from [16863c4f02] to [8f6da128e4].

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
of_unicode_to_iso_8859_15(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
of_unicode_to_iso_8859_15(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/iso_8859_2.m from [744cbf950c] to [de487566d1].

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
of_unicode_to_iso_8859_2(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
of_unicode_to_iso_8859_2(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/iso_8859_3.m from [3670e938ce] to [ca6d9c039c].

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
of_unicode_to_iso_8859_3(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
of_unicode_to_iso_8859_3(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/koi8_r.m from [512f05d1ec] to [e77fc0ad5b].

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
of_unicode_to_koi8_r(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
of_unicode_to_koi8_r(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/koi8_u.m from [b72abc7c7a] to [a1d99e8a1a].

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
of_unicode_to_koi8_u(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
of_unicode_to_koi8_u(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/mac_roman.m from [621b6250aa] to [c8c7b33ca3].

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
of_unicode_to_mac_roman(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
of_unicode_to_mac_roman(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/windows_1251.m from [752c057c67] to [c78eb7b263].

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
of_unicode_to_windows_1251(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
of_unicode_to_windows_1251(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/encodings/windows_1252.m from [8416ceeb47] to [a7686520cf].

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
of_unicode_to_windows_1252(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t index;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
of_unicode_to_windows_1252(const of_unichar_t *input, unsigned char *output,
    size_t length, bool lossy)
{
	for (size_t i = 0; i < length; i++) {
		of_unichar_t c = input[i];

		if OF_UNLIKELY (c > 0x7F) {
			uint8_t idx;

			if OF_UNLIKELY (c > 0xFFFF) {
				if (lossy) {
					output[i] = '?';
					continue;
				} else
					return false;

Modified src/exceptions/OFMemoryNotPartOfObjectException.h from [aaf3eabd13] to [ebaae357da].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *	  OFMemoryNotPartOfObjectException.h \
 *	  ObjFW/OFMemoryNotPartOfObjectException.h
 *
 * @brief An exception indicating the given memory is not part of the object.
 */
@interface OFMemoryNotPartOfObjectException: OFException
{
	void *_pointer;
	id _object;
}

/*!
 * A pointer to the memory which is not part of the object.
 */
@property (readonly, nonatomic) void *pointer;

/*!
 * The object which the memory is not part of.
 */
@property (readonly, nonatomic) id object;

+ (instancetype)exception OF_UNAVAILABLE;

/*!
 * @brief Creates a new, autoreleased memory not part of object exception.
 *
 * @param pointer A pointer to the memory that is not part of the object
 * @param object The object which the memory is not part of
 * @return A new, autoreleased memory not part of object exception
 */
+ (instancetype)exceptionWithPointer: (void *)pointer
			      object: (id)object;

- init OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated memory not part of object exception.
 *
 * @param pointer A pointer to the memory that is not part of the object
 * @param object The object which the memory is not part of
 * @return An initialized memory not part of object exception
 */
- initWithPointer: (void *)pointer
	   object: (id)object OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END







|






|















|











|




23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *	  OFMemoryNotPartOfObjectException.h \
 *	  ObjFW/OFMemoryNotPartOfObjectException.h
 *
 * @brief An exception indicating the given memory is not part of the object.
 */
@interface OFMemoryNotPartOfObjectException: OFException
{
	void *_Nullable _pointer;
	id _object;
}

/*!
 * A pointer to the memory which is not part of the object.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *pointer;

/*!
 * The object which the memory is not part of.
 */
@property (readonly, nonatomic) id object;

+ (instancetype)exception OF_UNAVAILABLE;

/*!
 * @brief Creates a new, autoreleased memory not part of object exception.
 *
 * @param pointer A pointer to the memory that is not part of the object
 * @param object The object which the memory is not part of
 * @return A new, autoreleased memory not part of object exception
 */
+ (instancetype)exceptionWithPointer: (nullable void *)pointer
			      object: (id)object;

- init OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated memory not part of object exception.
 *
 * @param pointer A pointer to the memory that is not part of the object
 * @param object The object which the memory is not part of
 * @return An initialized memory not part of object exception
 */
- initWithPointer: (nullable void *)pointer
	   object: (id)object OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Modified src/macros.h from [8a33280748] to [ed1d1a5d46].

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# else
#  /* Hopefully no arch needs more than 16 byte alignment */
#  define OF_BIGGEST_ALIGNMENT 16
# endif
#endif

#ifdef __GNUC__
# define __GCC_VERSION__ (__GNUC__ * 100 + __GNUC_MINOR__)
#else
# define __GCC_VERSION__ 0
#endif

#ifndef __has_feature
# define __has_feature(x) 0
#endif

#ifndef __has_attribute







|

|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# else
#  /* Hopefully no arch needs more than 16 byte alignment */
#  define OF_BIGGEST_ALIGNMENT 16
# endif
#endif

#ifdef __GNUC__
# define OF_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
# define OF_GCC_VERSION 0
#endif

#ifndef __has_feature
# define __has_feature(x) 0
#endif

#ifndef __has_attribute
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

#if __has_feature(objc_kindof)
# define OF_KINDOF(cls) __kindof cls
#else
# define OF_KINDOF(cls) id
#endif

#if defined(__clang__) || __GCC_VERSION__ >= 405
# define OF_UNREACHABLE __builtin_unreachable();
#else
# define OF_UNREACHABLE abort();
#endif

#if defined(__clang__) || __GCC_VERSION__ >= 406
# define OF_SENTINEL __attribute__((__sentinel__))
# define OF_NO_RETURN __attribute__((__noreturn__))
#else
# define OF_SENTINEL
# define OF_NO_RETURN
#endif








|





|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

#if __has_feature(objc_kindof)
# define OF_KINDOF(cls) __kindof cls
#else
# define OF_KINDOF(cls) id
#endif

#if defined(__clang__) || OF_GCC_VERSION >= 405
# define OF_UNREACHABLE __builtin_unreachable();
#else
# define OF_UNREACHABLE abort();
#endif

#if defined(__clang__) || OF_GCC_VERSION >= 406
# define OF_SENTINEL __attribute__((__sentinel__))
# define OF_NO_RETURN __attribute__((__noreturn__))
#else
# define OF_SENTINEL
# define OF_NO_RETURN
#endif

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
		OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >>  8) & 0xFF);	\
		OF_HASH_ADD(hash, otherCopy & 0xFF);		\
	}

static OF_INLINE bool
of_bitset_isset(uint8_t *storage, size_t index)
{
	return storage[index / 8] & (1 << (index % 8));
}

static OF_INLINE void
of_bitset_set(uint8_t *storage, size_t index)
{
	storage[index / 8] |= (1 << (index % 8));
}

static OF_INLINE void
of_bitset_clear(uint8_t *storage, size_t index)
{
	storage[index / 8] &= ~(1 << (index % 8));
}

static OF_INLINE char *
of_strdup(const char *string)
{
	char *copy;
	size_t length = strlen(string);

	if ((copy = (char *)malloc(length + 1)) == NULL)
		return NULL;

	memcpy(copy, string, length + 1);

	return copy;
}

static OF_INLINE void
of_explicit_memset(void *buffer_, int character, size_t length)
{
	volatile unsigned char *buffer = (volatile unsigned char *)buffer_;

	while (buffer < (unsigned char *)buffer_ + length)
		*buffer++ = character;
}








|

|



|

|



|

|


|
|













|







600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
		OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >>  8) & 0xFF);	\
		OF_HASH_ADD(hash, otherCopy & 0xFF);		\
	}

static OF_INLINE bool
of_bitset_isset(uint8_t *_Nonnull storage, size_t idx)
{
	return storage[idx / 8] & (1 << (idx % 8));
}

static OF_INLINE void
of_bitset_set(uint8_t *_Nonnull storage, size_t idx)
{
	storage[idx / 8] |= (1 << (idx % 8));
}

static OF_INLINE void
of_bitset_clear(uint8_t *_Nonnull storage, size_t idx)
{
	storage[idx / 8] &= ~(1 << (idx % 8));
}

static OF_INLINE char *_Nullable
of_strdup(const char *_Nonnull string)
{
	char *copy;
	size_t length = strlen(string);

	if ((copy = (char *)malloc(length + 1)) == NULL)
		return NULL;

	memcpy(copy, string, length + 1);

	return copy;
}

static OF_INLINE void
of_explicit_memset(void *_Nonnull buffer_, int character, size_t length)
{
	volatile unsigned char *buffer = (volatile unsigned char *)buffer_;

	while (buffer < (unsigned char *)buffer_ + length)
		*buffer++ = character;
}

Modified src/of_asprintf.m from [3e2fecec3f] to [e20ce9de33].

556
557
558
559
560
561
562
563
564


565
566
567
568
569
570
571
572
573
			void *pool = objc_autoreleasePoolPush();
			char *tmp2;

			@try {
				OFMutableString *tmpStr = [OFMutableString
				    stringWithUTF8String: tmp
						  length: tmpLen];
				OFString *decimalPoint =
				    [OFLocalization decimalPoint];


				[tmpStr replaceOccurrencesOfString: decimalPoint
							withString: @"."];
				if ([tmpStr UTF8StringLength] > INT_MAX)
					return false;
				tmpLen = (int)[tmpStr UTF8StringLength];
				tmp2 = malloc(tmpLen);
				memcpy(tmp2, [tmpStr UTF8String], tmpLen);
			} @finally {
				free(tmp);







|

>
>
|
|







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
			void *pool = objc_autoreleasePoolPush();
			char *tmp2;

			@try {
				OFMutableString *tmpStr = [OFMutableString
				    stringWithUTF8String: tmp
						  length: tmpLen];
				OFString *point =
				    [OFLocalization decimalPoint];
				if (point != nil)
					[tmpStr
					    replaceOccurrencesOfString: point
							    withString: @"."];
				if ([tmpStr UTF8StringLength] > INT_MAX)
					return false;
				tmpLen = (int)[tmpStr UTF8StringLength];
				tmp2 = malloc(tmpLen);
				memcpy(tmp2, [tmpStr UTF8String], tmpLen);
			} @finally {
				free(tmp);

Modified src/platform.h from [fb66e8de0c] to [7979b37a4b].

67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
# define OF_SPARC64
#elif defined(__sparc__) && !defined(__arch64__)
# define OF_SPARC
#endif

#if defined(__APPLE__)
# include <TargetConditionals.h>
# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE

#  define OF_IOS
# else
#  define OF_MACOS
# endif
#elif defined(__linux__)
# define OF_LINUX
#elif defined(_WIN32)







|
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# define OF_SPARC64
#elif defined(__sparc__) && !defined(__arch64__)
# define OF_SPARC
#endif

#if defined(__APPLE__)
# include <TargetConditionals.h>
# if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
    (defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR)
#  define OF_IOS
# else
#  define OF_MACOS
# endif
#elif defined(__linux__)
# define OF_LINUX
#elif defined(_WIN32)

Modified src/runtime/Makefile from [80fa148287] to [34e6bcc419].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
include ../../extra.mk

SUBDIRS = lookup-asm

SHARED_LIB = ${OBJFW_RT_SHARED_LIB}
STATIC_LIB = ${OBJFW_RT_STATIC_LIB}
MORPHOS_LIB = ${OBJFW_RT_MORPHOS_LIB}
LIB_MAJOR = ${OBJFW_RT_LIB_MAJOR}
LIB_MINOR = ${OBJFW_RT_LIB_MINOR}

SRCS = arc.m			\
       category.m		\
       class.m			\
       dtable.m			\






<







1
2
3
4
5
6

7
8
9
10
11
12
13
include ../../extra.mk

SUBDIRS = lookup-asm

SHARED_LIB = ${OBJFW_RT_SHARED_LIB}
STATIC_LIB = ${OBJFW_RT_STATIC_LIB}

LIB_MAJOR = ${OBJFW_RT_LIB_MAJOR}
LIB_MINOR = ${OBJFW_RT_LIB_MINOR}

SRCS = arc.m			\
       category.m		\
       class.m			\
       dtable.m			\
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
SRCS_THREADS = threading.m	\
	       ../threading.m
INCLUDES = ObjFW-RT.h
includesubdir = ObjFW-RT

OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_A}
LIB_OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_LIB_A}
MORPHOS_LIB_OBJS_EXTRA = morphos-library.o ${LOOKUP_ASM_LOOKUP_ASM_A}

include ../../buildsys.mk

${MORPHOS_LIB}: ppcinline.h
ppcinline.h: ObjFW-RT.fd protos.h
	cvinclude.pl			\
		--root ObjFW_RT		\
		--fd ObjFW-RT.fd	\
		--clib protos.h		\
		--inline $@

CPPFLAGS += -I. -I.. -I../..				\
	    -DOF_COMPILING_OBJFW_RT			\
	    -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR}	\
	    -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR}
LD = ${OBJC}







<



<
<
<
<
<
<
<
<





26
27
28
29
30
31
32

33
34
35








36
37
38
39
40
SRCS_THREADS = threading.m	\
	       ../threading.m
INCLUDES = ObjFW-RT.h
includesubdir = ObjFW-RT

OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_A}
LIB_OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_LIB_A}


include ../../buildsys.mk









CPPFLAGS += -I. -I.. -I../..				\
	    -DOF_COMPILING_OBJFW_RT			\
	    -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR}	\
	    -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR}
LD = ${OBJC}

Modified src/runtime/ObjFW-RT.h from [8577ac8d70] to [490c99bb19].

39
40
41
42
43
44
45



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#if !__has_feature(nullability)
# ifndef _Nonnull
#  define _Nonnull
# endif
# ifndef _Nullable
#  define _Nullable
# endif



#endif

#if !__has_feature(objc_arc) && !defined(__unsafe_unretained)
# define __unsafe_unretained
#endif

#define Nil (Class)0
#define nil (id)0
#define YES (BOOL)1
#define NO  (BOOL)0

typedef struct objc_class *Class;
typedef struct objc_object *id;
typedef const struct objc_selector *SEL;
typedef signed char BOOL;
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
typedef void (*objc_uncaught_exception_handler)(id _Nullable);
typedef void (*objc_enumeration_mutation_handler)(id _Nonnull);

struct objc_class {
	Class _Nonnull isa;
	Class _Nullable superclass;
	const char *_Nonnull name;
	unsigned long version;
	unsigned long info;
	long instance_size;
	struct objc_ivar_list *_Nullable ivars;
	struct objc_method_list *_Nullable methodlist;
	struct objc_dtable *_Nullable dtable;
	Class _Nonnull *_Nullable subclass_list;
	void *_Nullable sibling_class;
	struct objc_protocol_list *_Nullable protocols;
	void *_Nullable gc_object_type;
	unsigned long abi_version;
	int32_t *_Nonnull *_Nullable ivar_offsets;
	struct objc_property_list *_Nullable properties;
};







>
>
>






|
|




















|
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#if !__has_feature(nullability)
# ifndef _Nonnull
#  define _Nonnull
# endif
# ifndef _Nullable
#  define _Nullable
# endif
# ifndef _Null_unspecified
#  define _Null_unspecified
# endif
#endif

#if !__has_feature(objc_arc) && !defined(__unsafe_unretained)
# define __unsafe_unretained
#endif

#define Nil (Class _Null_unspecified)0
#define nil (id _Null_unspecified)0
#define YES (BOOL)1
#define NO  (BOOL)0

typedef struct objc_class *Class;
typedef struct objc_object *id;
typedef const struct objc_selector *SEL;
typedef signed char BOOL;
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
typedef void (*objc_uncaught_exception_handler)(id _Nullable);
typedef void (*objc_enumeration_mutation_handler)(id _Nonnull);

struct objc_class {
	Class _Nonnull isa;
	Class _Nullable superclass;
	const char *_Nonnull name;
	unsigned long version;
	unsigned long info;
	long instance_size;
	struct objc_ivar_list *_Nullable ivars;
	struct objc_method_list *_Nullable methodlist;
	struct objc_dtable *_Nonnull dtable;
	Class _Nullable *_Nullable subclass_list;
	void *_Nullable sibling_class;
	struct objc_protocol_list *_Nullable protocols;
	void *_Nullable gc_object_type;
	unsigned long abi_version;
	int32_t *_Nonnull *_Nullable ivar_offsets;
	struct objc_property_list *_Nullable properties;
};
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

struct objc_protocol_list {
	struct objc_protocol_list *_Nullable next;
	long count;
	Protocol *__unsafe_unretained _Nonnull list[1];
};

#if 1 /* !defined(__MORPHOS__) || defined(OF_COMPILING_OBJFW_RT) */
# ifdef __cplusplus
extern "C" {
# endif
extern SEL _Nonnull sel_registerName(const char *_Nonnull);
extern const char *_Nonnull sel_getName(SEL _Nonnull);
extern bool sel_isEqual(SEL _Nonnull, SEL _Nonnull);
extern Class _Nonnull objc_allocateClassPair(Class _Nullable,
    const char *_Nonnull, size_t);
extern void objc_registerClassPair(Class _Nonnull);
extern unsigned int objc_getClassList(Class _Nonnull *_Nullable, unsigned int);







<
|

|







198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214

struct objc_protocol_list {
	struct objc_protocol_list *_Nullable next;
	long count;
	Protocol *__unsafe_unretained _Nonnull list[1];
};


#ifdef __cplusplus
extern "C" {
#endif
extern SEL _Nonnull sel_registerName(const char *_Nonnull);
extern const char *_Nonnull sel_getName(SEL _Nonnull);
extern bool sel_isEqual(SEL _Nonnull, SEL _Nonnull);
extern Class _Nonnull objc_allocateClassPair(Class _Nullable,
    const char *_Nonnull, size_t);
extern void objc_registerClassPair(Class _Nonnull);
extern unsigned int objc_getClassList(Class _Nonnull *_Nullable, unsigned int);
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    SEL _Nonnull);
extern bool class_addMethod(Class _Nonnull, SEL _Nonnull, IMP _Nonnull,
    const char *_Nullable);
extern IMP _Nullable class_replaceMethod(Class _Nonnull, SEL _Nonnull,
    IMP _Nonnull, const char *_Nullable);
extern Class _Nullable object_getClass(id _Nullable);
extern Class _Nullable object_setClass(id _Nullable, Class _Nonnull);
extern const char *_Nonnull object_getClassName(id _Nullable);
extern const char *_Nonnull protocol_getName(Protocol *_Nonnull);
extern bool protocol_isEqual(Protocol *_Nonnull, Protocol *_Nonnull);
extern bool protocol_conformsToProtocol(Protocol *_Nonnull, Protocol *_Nonnull);
extern void objc_exit(void);
extern _Nullable objc_uncaught_exception_handler
    objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler _Nullable);
extern void objc_setForwardHandler(IMP _Nullable, IMP _Nullable);
extern void objc_setEnumerationMutationHandler(
    objc_enumeration_mutation_handler _Nullable);
extern void objc_zero_weak_references(id _Nonnull);
# ifdef __cplusplus
}
# endif
#else
# define BOOL EXEC_BOOL
# include <ppcinline/macros.h>
# undef BOOL
# ifdef __cplusplus
extern "C" {
# endif
extern struct Library *ObjFWRTBase;
# ifdef __cplusplus
}
# endif
# include "ppcinline.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Used by the compiler, but can also be called manually.
 *
 * They need to be in the glue code for the MorphOS library.
 *
 * These declarations are also required to prevent Clang's implicit
 * declarations which include __declspec(dllimport) on Windows.







|











<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

246


















247
248
249
250
251
252
253
    SEL _Nonnull);
extern bool class_addMethod(Class _Nonnull, SEL _Nonnull, IMP _Nonnull,
    const char *_Nullable);
extern IMP _Nullable class_replaceMethod(Class _Nonnull, SEL _Nonnull,
    IMP _Nonnull, const char *_Nullable);
extern Class _Nullable object_getClass(id _Nullable);
extern Class _Nullable object_setClass(id _Nullable, Class _Nonnull);
extern const char *_Nullable object_getClassName(id _Nullable);
extern const char *_Nonnull protocol_getName(Protocol *_Nonnull);
extern bool protocol_isEqual(Protocol *_Nonnull, Protocol *_Nonnull);
extern bool protocol_conformsToProtocol(Protocol *_Nonnull, Protocol *_Nonnull);
extern void objc_exit(void);
extern _Nullable objc_uncaught_exception_handler
    objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler _Nullable);
extern void objc_setForwardHandler(IMP _Nullable, IMP _Nullable);
extern void objc_setEnumerationMutationHandler(
    objc_enumeration_mutation_handler _Nullable);
extern void objc_zero_weak_references(id _Nonnull);




















/*
 * Used by the compiler, but can also be called manually.
 *
 * They need to be in the glue code for the MorphOS library.
 *
 * These declarations are also required to prevent Clang's implicit
 * declarations which include __declspec(dllimport) on Windows.

Modified src/runtime/hashtable.m from [69b267cc69] to [2844ae174b].

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

	free(table->data);
	table->data = ndata;
	table->size = nsize;
}

static inline bool
index_for_key(struct objc_hashtable *table, const void *key, uint32_t *index)
{
	uint32_t i, hash;

	hash = table->hash(key) & (table->size - 1);

	for (i = hash; i < table->size && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*index = i;
			return true;
		}
	}

	if (i < table->size)
		return false;

	for (i = 0; i < hash && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*index = i;
			return true;
		}
	}

	return false;
}








|










|












|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

	free(table->data);
	table->data = ndata;
	table->size = nsize;
}

static inline bool
index_for_key(struct objc_hashtable *table, const void *key, uint32_t *idx)
{
	uint32_t i, hash;

	hash = table->hash(key) & (table->size - 1);

	for (i = hash; i < table->size && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}

	if (i < table->size)
		return false;

	for (i = 0; i < hash && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}

	return false;
}

Modified src/runtime/lookup-asm/lookup-asm-sparc64-elf.S from [03722104be] to [44cfec8a34].

48
49
50
51
52
53
54
55
56
57
58
59





60
61
62
63
64
65
66
#ifdef OF_SELUID24
	ldx	[%o2 + %o3], %o2
#endif
	ldx	[%o2 + %o4], %o2
	ldx	[%o2 + %o5], %o2

	cmp	%o2, 0
	be,pn	%xcc, \not_found
	 nop

	retl
	 mov	%o2, %o0





.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mov	%o0, %o2







|




>
>
>
>
>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#ifdef OF_SELUID24
	ldx	[%o2 + %o3], %o2
#endif
	ldx	[%o2 + %o4], %o2
	ldx	[%o2 + %o5], %o2

	cmp	%o2, 0
	be,pn	%xcc, 0f
	 nop

	retl
	 mov	%o2, %o0

0:
	mov	%o7, %g1
	call	\not_found
	 mov	%g1, %o7
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mov	%o0, %o2

Deleted src/runtime/morphos-library.m version [90367d03a6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
 *   Jonathan Schleifer <js@heap.zone>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW-RT.h"
#import "macros.h"

#define BOOL EXEC_BOOL
#include <dos/dos.h>
#include <emul/emulregs.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/resident.h>
#include <exec/types.h>
#include <proto/exec.h>
#undef BOOL

struct ObjFWRTBase {
	struct Library library;
	BPTR seg_list;
};

/* Forward declarations for all functions in the func_table */
static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
    struct ExecBase *exec_base);
static struct Library *lib_open(void);
static BPTR lib_close(void);
static BPTR lib_expunge(void);
static void lib_null(void);
void objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status));

static ULONG func_table[] = {
	FUNCARRAY_BEGIN,
	FUNCARRAY_32BIT_NATIVE,
	(ULONG)lib_open,
	(ULONG)lib_close,
	(ULONG)lib_expunge,
	(ULONG)lib_null,
	-1,
	FUNCARRAY_32BIT_SYSTEMV,
	/* Functions for the glue code */
	(ULONG)objc_set_exit,
	/* Used by the compiler - these need glue code */
	(ULONG)__objc_exec_class,
	(ULONG)objc_msg_lookup,
	(ULONG)objc_msg_lookup_stret,
	(ULONG)objc_msg_lookup_super,
	(ULONG)objc_msg_lookup_super_stret,
	(ULONG)objc_lookUpClass,
	(ULONG)objc_getClass,
	(ULONG)objc_getRequiredClass,
	(ULONG)objc_exception_throw,
	(ULONG)objc_sync_enter,
	(ULONG)objc_sync_exit,
	(ULONG)objc_getProperty,
	(ULONG)objc_setProperty,
	(ULONG)objc_getPropertyStruct,
	(ULONG)objc_setPropertyStruct,
	(ULONG)objc_enumerationMutation,
	/* Functions declared in ObjFW-RT.h */
	(ULONG)sel_registerName,
	(ULONG)sel_getName,
	(ULONG)sel_isEqual,
	(ULONG)objc_allocateClassPair,
	(ULONG)objc_registerClassPair,
	(ULONG)objc_getClassList,
	(ULONG)objc_copyClassList,
	(ULONG)class_isMetaClass,
	(ULONG)class_getName,
	(ULONG)class_getSuperclass,
	(ULONG)class_getInstanceSize,
	(ULONG)class_respondsToSelector,
	(ULONG)class_conformsToProtocol,
	(ULONG)class_getMethodImplementation,
	(ULONG)class_getMethodImplementation_stret,
	(ULONG)class_getMethodTypeEncoding,
	(ULONG)class_addMethod,
	(ULONG)class_replaceMethod,
	(ULONG)object_getClass,
	(ULONG)object_setClass,
	(ULONG)object_getClassName,
	(ULONG)protocol_getName,
	(ULONG)protocol_isEqual,
	(ULONG)protocol_conformsToProtocol,
	(ULONG)objc_exit,
	(ULONG)objc_setUncaughtExceptionHandler,
	(ULONG)objc_setForwardHandler,
	(ULONG)objc_setEnumerationMutationHandler,
	(ULONG)objc_zero_weak_references,
	-1,
	FUNCARRAY_END
};

static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
    struct ExecBase *exec_base);

static struct {
	LONG struct_size;
	ULONG *func_table;
	void *data_table;
	struct Library *(*init_func)(struct ObjFWRTBase *base, BPTR seg_list,
	    struct ExecBase *exec_base);
} init_table = {
	.struct_size = sizeof(struct ObjFWRTBase),
	func_table,
	NULL,
	lib_init
};

static struct Resident resident = {
	.rt_MatchWord = RTC_MATCHWORD,
	.rt_MatchTag = &resident,
	.rt_EndSkip = &resident + 1,
	.rt_Flags = RTF_AUTOINIT | RTF_PPC,
	.rt_Version = OBJFW_RT_LIB_MAJOR * 10 + OBJFW_RT_LIB_MINOR,
	.rt_Type = NT_LIBRARY,
	.rt_Pri = 0,
	.rt_Name = (char *)"objfw-rt.library",
	.rt_IdString = (char *)"ObjFW-RT " PACKAGE_VERSION
	    " \xA9 2008-2017 Jonathan Schleifer",
	.rt_Init = &init_table
};

/* Magic required to make this a MorphOS binary */
const ULONG __abox__ = 1;

/* Global variables needed by libnix */
int ThisRequiresConstructorHandling;
struct ExecBase *SysBase;
void *libnix_mempool;

/* Functions passed in from the glue linklib */
static void OF_NO_RETURN_FUNC (*exit_fn)(int status);

void OF_NO_RETURN_FUNC
exit(int status)
{
	exit_fn(status);
}

void
objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status))
{
	exit_fn = exit_fn_;
}

/* Standard library functions */
static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
    struct ExecBase *exec_base)
{
	SysBase = exec_base;

	base->seg_list = seg_list;

	return &base->library;
}

static struct Library *
lib_open(void)
{
	struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6;

	base->library.lib_OpenCnt++;
	base->library.lib_Flags &= ~LIBF_DELEXP;

	return &base->library;
}

static BPTR
expunge(struct ObjFWRTBase *base)
{
	/* Still in use - set delayed expunge flag and refuse to expunge */
	if (base->library.lib_OpenCnt > 0) {
		base->library.lib_Flags |= LIBF_DELEXP;
		return 0;
	}

	Remove(&base->library.lib_Node);
	FreeMem((char *)base - base->library.lib_NegSize,
	    base->library.lib_NegSize + base->library.lib_PosSize);

	return base->seg_list;
}

static BPTR
lib_close(void)
{
	struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6;

	/* Not used anymore and delayed expunge flag set -> expunge */
	if (--base->library.lib_OpenCnt == 0 &&
	    (base->library.lib_Flags & LIBF_DELEXP))
		return expunge(base);

	return 0;
}

static BPTR
lib_expunge(void)
{
	return expunge((struct ObjFWRTBase *)REG_A6);
}

static void
lib_null(void)
{
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































































































































































































































Modified src/socket.h from [1d3c37e76e] to [ea1fed378b].

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_socket_init(void);
extern int of_socket_errno(void);
# ifndef OF_WII
extern int of_getsockname(of_socket_t socket, struct sockaddr *restrict address,
    socklen_t *restrict address_len);
# endif
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|
|






109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_socket_init(void);
extern int of_socket_errno(void);
# ifndef OF_WII
extern int of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,
    socklen_t *restrict addrLen);
# endif
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/socket.m from [c5f416940a] to [ac7909760b].

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

	return 0;
#endif
}

#ifndef OF_WII
int
of_getsockname(of_socket_t socket, struct sockaddr *restrict address,
    socklen_t *restrict address_len)
{
	int ret;

# ifdef OF_HAVE_THREADS
	if (!of_mutex_lock(&mutex))
		@throw [OFLockFailedException exception];

# endif

	ret = getsockname(socket, address, address_len);

# ifdef OF_HAVE_THREADS
	if (!of_mutex_unlock(&mutex))
		@throw [OFUnlockFailedException exception];
# endif

	return ret;
}
#endif







|
|









|









189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

	return 0;
#endif
}

#ifndef OF_WII
int
of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,
    socklen_t *restrict addrLen)
{
	int ret;

# ifdef OF_HAVE_THREADS
	if (!of_mutex_lock(&mutex))
		@throw [OFLockFailedException exception];

# endif

	ret = getsockname(sock, addr, addrLen);

# ifdef OF_HAVE_THREADS
	if (!of_mutex_unlock(&mutex))
		@throw [OFUnlockFailedException exception];
# endif

	return ret;
}
#endif

Modified src/threading.h from [44065a1e75] to [46db014c33].

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# error of_thread_is_current not implemented!
# error of_thread_current not implemented!
#endif

extern bool of_thread_attr_init(of_thread_attr_t *attr);
extern bool of_thread_new(of_thread_t *thread, void (*function)(id), id object,
    const of_thread_attr_t *attr);
extern void of_thread_set_name(of_thread_t thread, const char *name);
extern bool of_thread_join(of_thread_t thread);
extern bool of_thread_detach(of_thread_t thread);
extern void OF_NO_RETURN_FUNC of_thread_exit(void);
extern void of_once(of_once_t *control, void (*func)(void));
extern bool of_tlskey_new(of_tlskey_t *key);
extern bool of_tlskey_free(of_tlskey_t key);
extern bool of_mutex_new(of_mutex_t *mutex);







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# error of_thread_is_current not implemented!
# error of_thread_current not implemented!
#endif

extern bool of_thread_attr_init(of_thread_attr_t *attr);
extern bool of_thread_new(of_thread_t *thread, void (*function)(id), id object,
    const of_thread_attr_t *attr);
extern void of_thread_set_name(const char *name);
extern bool of_thread_join(of_thread_t thread);
extern bool of_thread_detach(of_thread_t thread);
extern void OF_NO_RETURN_FUNC of_thread_exit(void);
extern void of_once(of_once_t *control, void (*func)(void));
extern bool of_tlskey_new(of_tlskey_t *key);
extern bool of_tlskey_free(of_tlskey_t key);
extern bool of_mutex_new(of_mutex_t *mutex);

Modified src/threading_pthread.m from [9d56adf88b] to [7c690c290a].

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
{
	pthread_exit(NULL);

	OF_UNREACHABLE
}

void
of_thread_set_name(of_thread_t thread, const char *name)
{
#if defined(OF_HAIKU)
	rename_thread(get_pthread_thread_id(thread), name);
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
	pthread_set_name_np(pthread_self(), name);
#elif defined(HAVE_PTHREAD_SETNAME_NP)
# if defined(OF_MACOS) || defined(OF_IOS)
	pthread_setname_np(name);
# elif defined(__GLIBC__)
	char buffer[16];







|


|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
{
	pthread_exit(NULL);

	OF_UNREACHABLE
}

void
of_thread_set_name(const char *name)
{
#if defined(OF_HAIKU)
	rename_thread(find_thread(NULL), name);
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
	pthread_set_name_np(pthread_self(), name);
#elif defined(HAVE_PTHREAD_SETNAME_NP)
# if defined(OF_MACOS) || defined(OF_IOS)
	pthread_setname_np(name);
# elif defined(__GLIBC__)
	char buffer[16];

Modified src/threading_winapi.m from [f624bdcb51] to [5f1546849f].

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{
	ExitThread(0);

	OF_UNREACHABLE
}

void
of_thread_set_name(of_thread_t thread, const char *name)
{
}

bool
of_tlskey_new(of_tlskey_t *key)
{
	return ((*key = TlsAlloc()) != TLS_OUT_OF_INDEXES);







|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{
	ExitThread(0);

	OF_UNREACHABLE
}

void
of_thread_set_name(const char *name)
{
}

bool
of_tlskey_new(of_tlskey_t *key)
{
	return ((*key = TlsAlloc()) != TLS_OUT_OF_INDEXES);

Modified tests/OFArrayTests.m from [b0ab3f0686] to [caf218a7ef].

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
- (void)dealloc
{
	[_array release];

	[super dealloc];
}

- (id)objectAtIndex: (size_t)index
{
	return [_array objectAtIndex: index];
}

- (size_t)count
{
	return [_array count];
}
@end

@implementation SimpleMutableArray
+ (void)initialize
{
	if (self == [SimpleMutableArray class])
		[self inheritMethodsFromClass: [SimpleArray class]];
}

- (void)insertObject: (id)object
	     atIndex: (size_t)index
{
	[_array insertObject: object
		     atIndex: index];
}

- (void)replaceObjectAtIndex: (size_t)index
		  withObject: (id)object
{
	[_array replaceObjectAtIndex: index
			  withObject: object];
}

- (void)removeObjectAtIndex: (size_t)index
{
	[_array removeObjectAtIndex: index];
}
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{







|

|
















|


|


|


|



|

|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
- (void)dealloc
{
	[_array release];

	[super dealloc];
}

- (id)objectAtIndex: (size_t)idx
{
	return [_array objectAtIndex: idx];
}

- (size_t)count
{
	return [_array count];
}
@end

@implementation SimpleMutableArray
+ (void)initialize
{
	if (self == [SimpleMutableArray class])
		[self inheritMethodsFromClass: [SimpleArray class]];
}

- (void)insertObject: (id)object
	     atIndex: (size_t)idx
{
	[_array insertObject: object
		     atIndex: idx];
}

- (void)replaceObjectAtIndex: (size_t)idx
		  withObject: (id)object
{
	[_array replaceObjectAtIndex: idx
			  withObject: object];
}

- (void)removeObjectAtIndex: (size_t)idx
{
	[_array removeObjectAtIndex: idx];
}
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[m[0] removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool ok = true;
		__block size_t count = 0;
		OFArray *cmp = a[0];
		OFMutableArray *a2;

		m[0] = [[a[0] mutableCopy] autorelease];
		[m[0] enumerateObjectsUsingBlock:
		    ^ (id obj, size_t idx, bool *stop) {
			    count++;
			    if (![obj isEqual: [cmp objectAtIndex: idx]])
				    ok = false;
		}];

		if (count != [cmp count])
			ok = false;

		TEST(@"Enumeration using blocks", ok)

		ok = false;
		a2 = m[0];
		@try {
			[a2 enumerateObjectsUsingBlock:
			    ^ (id obj, size_t idx, bool *stop) {
				[a2 removeObjectAtIndex: idx];
			}];
		} @catch (OFEnumerationMutationException *e) {
			ok = true;
		} @catch (OFOutOfRangeException *e) {
			/*
			 * Out of bounds access due to enumeration not being
			 * detected.
			 */
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    ok)
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([m[0] replaceObjectsUsingBlock: ^ id (id obj, size_t idx) {
		switch (idx) {
		case 0:
			return @"foo";
		case 1:
			return @"bar";
		}

		return nil;
		}]) && [[m[0] description] isEqual: @"(\n\tfoo,\n\tbar\n)"])

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[[m[0] mappedArrayUsingBlock: ^ id (id obj, size_t idx) {
		switch (idx) {
		case 0:
			return @"foobar";
		case 1:
			return @"qux";
		}

		return nil;
	    }] description] isEqual: @"(\n\tfoobar,\n\tqux\n)"])

	TEST(@"-[filteredArrayUsingBlock:]",
	   [[[m[0] filteredArrayUsingBlock: ^ bool (id obj, size_t idx) {
		return [obj isEqual: @"foo"];
	    }] description] isEqual: @"(\n\tfoo\n)"])

	TEST(@"-[foldUsingBlock:]",
	    [[arrayClass arrayWithObjects: [OFMutableString string], @"foo",
	    @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) {
		[left appendString: right];
		return left;







|






|

|
|



|

|

|



|



|








|



|











|











|
|







349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[m[0] removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool blockOk = true;
		__block size_t count = 0;
		OFArray *cmp = a[0];
		OFMutableArray *a2;

		m[0] = [[a[0] mutableCopy] autorelease];
		[m[0] enumerateObjectsUsingBlock:
		    ^ (id object, size_t idx, bool *stop) {
			    count++;
			    if (![object isEqual: [cmp objectAtIndex: idx]])
				    blockOk = false;
		}];

		if (count != [cmp count])
			blockOk = false;

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		a2 = m[0];
		@try {
			[a2 enumerateObjectsUsingBlock:
			    ^ (id object, size_t idx, bool *stop) {
				[a2 removeObjectAtIndex: idx];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		} @catch (OFOutOfRangeException *e) {
			/*
			 * Out of bounds access due to enumeration not being
			 * detected.
			 */
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOk)
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([m[0] replaceObjectsUsingBlock: ^ id (id object, size_t idx) {
		switch (idx) {
		case 0:
			return @"foo";
		case 1:
			return @"bar";
		}

		return nil;
		}]) && [[m[0] description] isEqual: @"(\n\tfoo,\n\tbar\n)"])

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[[m[0] mappedArrayUsingBlock: ^ id (id object, size_t idx) {
		switch (idx) {
		case 0:
			return @"foobar";
		case 1:
			return @"qux";
		}

		return nil;
	    }] description] isEqual: @"(\n\tfoobar,\n\tqux\n)"])

	TEST(@"-[filteredArrayUsingBlock:]",
	    [[[m[0] filteredArrayUsingBlock: ^ bool (id object, size_t idx) {
		return [object isEqual: @"foo"];
	    }] description] isEqual: @"(\n\tfoo\n)"])

	TEST(@"-[foldUsingBlock:]",
	    [[arrayClass arrayWithObjects: [OFMutableString string], @"foo",
	    @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) {
		[left appendString: right];
		return left;

Modified tests/OFBlockTests.m from [b51076c2c2] to [57afcae22d].

67
68
69
70
71
72
73





74
75
76

77
78
79
80
81
82
83
	void (^m)(void);
	int (^v)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [s isKindOfClass: [OFBlock class]])






	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [g isKindOfClass: [OFBlock class]])


	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (m = [[s copy] autorelease]) &&
	    [m class] == objc_getClass("OFMallocBlock") &&







>
>
>
>
>



>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	void (^m)(void);
	int (^v)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [s isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__)
	/*
	 * Causes a linker error on Windows with Clang when compiling as a
	 * static library. This is a bug in Clang.
	 */
	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [g isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (m = [[s copy] autorelease]) &&
	    [m class] == objc_getClass("OFMallocBlock") &&

Modified tests/OFDictionaryTests.m from [76bc88ef2a] to [ed8d42f32f].

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
		@throw e;
	}

	return self;
}

- initWithObjects: (const id *)objects
	  forKeys: (const id *)keys
	    count: (size_t)count
{
	self = [super init];

	@try {
		_dictionary = [[OFMutableDictionary alloc]
		    initWithObjects: objects
			    forKeys: keys
			      count: count];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







|







|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
		@throw e;
	}

	return self;
}

- initWithObjects: (const id *)objects
	  forKeys: (const id *)keys_
	    count: (size_t)count
{
	self = [super init];

	@try {
		_dictionary = [[OFMutableDictionary alloc]
		    initWithObjects: objects
			    forKeys: keys_
			      count: count];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t i = 0;
		__block bool ok = true;

		[mutDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id obj, bool *stop) {
			if (i > 1 || ![key isEqual: keys[i]]) {
				ok = false;
				*stop = true;
				return;
			}

			[mutDict setObject: [mutDict objectForKey: key]
				    forKey: key];
			i++;
		}];

		TEST(@"Enumeration using blocks", ok)

		ok = false;
		@try {
			[mutDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id obj, bool *stop) {
				[mutDict setObject: @""
					    forKey: @""];
			}];
		} @catch (OFEnumerationMutationException *e) {
			ok = true;
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    ok)

		[mutDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutDict replaceObjectsUsingBlock: ^ id (id key, id obj) {
		if ([key isEqual: keys[0]])
			return @"value_1";
		if ([key isEqual: keys[1]])
			return @"value_2";

		return nil;
	    }]) && [[mutDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutDict mappedDictionaryUsingBlock: ^ id (id key, id obj) {
		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutDict filteredDictionaryUsingBlock: ^ bool (id key, id obj) {

		return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", [mutDict count] == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",







|
|


|
|
|






|


|

|


|




|



|





|










|









|
>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t j = 0;
		__block bool blockOk = true;

		[mutDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id object, bool *stop) {
			if (j > 1 || ![key isEqual: keys[j]]) {
				blockOk = false;
				*stop = true;
				return;
			}

			[mutDict setObject: [mutDict objectForKey: key]
				    forKey: key];
			j++;
		}];

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		@try {
			[mutDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id object, bool *stop) {
				[mutDict setObject: @""
					    forKey: @""];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOk)

		[mutDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutDict replaceObjectsUsingBlock: ^ id (id key, id object) {
		if ([key isEqual: keys[0]])
			return @"value_1";
		if ([key isEqual: keys[1]])
			return @"value_2";

		return nil;
	    }]) && [[mutDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutDict mappedDictionaryUsingBlock: ^ id (id key, id object) {
		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutDict filteredDictionaryUsingBlock:
	    ^ bool (id key, id object) {
		return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", [mutDict count] == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",

Modified tests/OFKernelEventObserverTests.m from [f2b6e225cb] to [6f6df4db2e].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33



34
35
36
37
38
39
40
41
42

#import "OFKernelEventObserver.h"
#import "OFString.h"
#import "OFDate.h"
#import "OFTCPSocket.h"
#import "OFAutoreleasePool.h"

#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS)
# import "OFKernelEventObserver_select.h"
#endif
#if defined(HAVE_POLL_H) || defined(OF_WII)
# import "OFKernelEventObserver_poll.h"
#endif
#ifdef HAVE_EPOLL
# import "OFKernelEventObserver_epoll.h"
#endif



#ifdef HAVE_KQUEUE
# import "OFKernelEventObserver_kqueue.h"
#endif

#import "TestsAppDelegate.h"

#define EXPECTED_EVENTS 3

static OFString *module;







<
<
|
<
|




>
>
>
|
|







18
19
20
21
22
23
24


25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#import "OFKernelEventObserver.h"
#import "OFString.h"
#import "OFDate.h"
#import "OFTCPSocket.h"
#import "OFAutoreleasePool.h"



#ifdef HAVE_KQUEUE

# import "OFKernelEventObserver_kqueue.h"
#endif
#ifdef HAVE_EPOLL
# import "OFKernelEventObserver_epoll.h"
#endif
#ifdef HAVE_POLL
# import "OFKernelEventObserver_poll.h"
#endif
#ifdef HAVE_SELECT
# import "OFKernelEventObserver_select.h"
#endif

#import "TestsAppDelegate.h"

#define EXPECTED_EVENTS 3

static OFString *module;
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
	}
}
@end

@implementation TestsAppDelegate (OFKernelEventObserverTests)
- (void)kernelEventObserverTestsWithClass: (Class)class
{

	ObserverTest *test;

	module = [class className];
	test = [[[ObserverTest alloc]
	    initWithTestsAppDelegate: self] autorelease];

	TEST(@"+[observer]",
	    (test->_observer = [OFKernelEventObserver observer]))
	[test->_observer setDelegate: test];

	TEST(@"-[addObjectForReading:]",
	    R([test->_observer addObjectForReading: test->_server]))

	[test run];
	_fails += test->_fails;


}

- (void)kernelEventObserverTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS)
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_select class]];
#endif

#if defined(HAVE_POLL_H) || defined(OF_WII)
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_poll class]];
#endif

#ifdef HAVE_EPOLL
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_epoll class]];
#endif

#ifdef HAVE_KQUEUE
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_kqueue class]];
#endif

	[pool drain];
}
@end







>






|
<







>
>




<
|
<




|













|
<
<

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226

227

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246


247
	}
}
@end

@implementation TestsAppDelegate (OFKernelEventObserverTests)
- (void)kernelEventObserverTestsWithClass: (Class)class
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	ObserverTest *test;

	module = [class className];
	test = [[[ObserverTest alloc]
	    initWithTestsAppDelegate: self] autorelease];

	TEST(@"+[observer]", (test->_observer = [class observer]))

	[test->_observer setDelegate: test];

	TEST(@"-[addObjectForReading:]",
	    R([test->_observer addObjectForReading: test->_server]))

	[test run];
	_fails += test->_fails;

	[pool drain];
}

- (void)kernelEventObserverTests
{

#ifdef HAVE_SELECT

	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_select class]];
#endif

#ifdef HAVE_POLL
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_poll class]];
#endif

#ifdef HAVE_EPOLL
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_epoll class]];
#endif

#ifdef HAVE_KQUEUE
	[self kernelEventObserverTestsWithClass:
	    [OFKernelEventObserver_kqueue class]];
#endif
}


@end

Modified tests/OFListTests.m from [3c7e2e133b] to [9cc03e5fa4].

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

	[list prependObject: strings[0]];

	loe = [list firstListObject];
	i = 0;
	ok = true;

	for (OFString *obj in list) {
		if (![obj isEqual: loe->object])
			ok = false;

		loe = loe->next;
		i++;
	}

	if ([list count] != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *obj in list) {
			(void)obj;

			[list removeListObject: [list lastListObject]];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[pool drain];
}
@end







|
|













|
|












123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

	[list prependObject: strings[0]];

	loe = [list firstListObject];
	i = 0;
	ok = true;

	for (OFString *object in list) {
		if (![object isEqual: loe->object])
			ok = false;

		loe = loe->next;
		i++;
	}

	if ([list count] != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object in list) {
			(void)object;

			[list removeListObject: [list lastListObject]];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[pool drain];
}
@end

Modified tests/OFObjectTests.m from [bb532d1546] to [ba866e7637].

251
252
253
254
255
256
257
258
259
260
261
262
263
	    [m unsignedIntValue] == 80 &&
	    [m unsignedLongValue] == 90 &&
	    [m unsignedLongLongValue] == 100 &&
	    [m floatValue] == 110 &&
	    [m doubleValue] == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException, [m setValue: nil
					     forKey: @"intValue"])

	[pool drain];
}
@end







|





251
252
253
254
255
256
257
258
259
260
261
262
263
	    [m unsignedIntValue] == 80 &&
	    [m unsignedLongValue] == 90 &&
	    [m unsignedLongLongValue] == 100 &&
	    [m floatValue] == 110 &&
	    [m doubleValue] == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException, [m setValue: (id _Nonnull)nil
					     forKey: @"intValue"])

	[pool drain];
}
@end

Modified tests/OFStringTests.m from [addca37143] to [1b6d7256b5].

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
- (void)dealloc
{
	[_string release];

	[super dealloc];
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	return [_string characterAtIndex: index];
}

- (size_t)length
{
	return [_string length];
}
@end







|

|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
- (void)dealloc
{
	[_string release];

	[super dealloc];
}

- (of_unichar_t)characterAtIndex: (size_t)idx
{
	return [_string characterAtIndex: idx];
}

- (size_t)length
{
	return [_string length];
}
@end

Modified tests/OFXMLParserTests.m from [278894d6bc] to [69fc2ecfb9].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314
315
316
317
318
319

#import "OFInvalidEncodingException.h"
#import "OFMalformedXMLException.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLParser";
static OFXMLParser *parser;
static int i = 0;

enum event_type {
	PROCESSING_INSTRUCTIONS,
	TAG_START,
	TAG_END,
	STRING,
	CDATA,
	COMMENT
};

@implementation TestsAppDelegate (OFXMLParser)

- (void)parserCallbackWithEventType: (enum event_type)et
			       name: (OFString *)name
			     prefix: (OFString *)prefix
			  namespace: (OFString *)ns
			 attributes: (OFArray *)attrs
			     string: (OFString *)string
{
	OFString *msg;

	i++;
	msg = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(msg, et == PROCESSING_INSTRUCTIONS &&
		    [string isEqual: @"xml version='1.0'"])
		break;
	case 2:
		TEST(msg, et == PROCESSING_INSTRUCTIONS &&
		    [string isEqual: @"p?i"])
		break;
	case 3:
		TEST(msg, et == TAG_START && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil && [attrs count] == 0)
		break;
	case 4:
		TEST(msg, et == STRING && [string isEqual: @"\n\n "])
		break;
	case 5:
		TEST(msg, et == CDATA && [string isEqual: @"f<]]]oo]"] &&
		    [parser lineNumber] == 3)
		break;
	case 6:
		TEST(msg, et == TAG_START && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 7:
		TEST(msg, et == TAG_END && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 8:
		TEST(msg, et == STRING && [string isEqual: @"\n "])
		break;
	case 9:
		TEST(msg, et == TAG_START && [name isEqual: @"foobar"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:
		TEST(msg, et == STRING && [string isEqual: @"\n  "])
		break;
	case 11:
		TEST(msg, et == TAG_START && [name isEqual: @"qux"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:
		TEST(msg, et == STRING && [string isEqual: @"\n   "])
		break;
	case 13:
		TEST(msg, et == TAG_START && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"] &&
		    [attrs count] == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:
		TEST(msg, et == STRING && [string isEqual: @"\n    "])
		break;
	case 15:
		TEST(msg, et == TAG_START && [name isEqual: @"blup"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:
		TEST(msg, et == TAG_END && [name isEqual: @"blup"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:
		TEST(msg, et == STRING && [string isEqual: @"\n    "])
		break;
	case 18:
		TEST(msg, et == TAG_START && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"] && [attrs count] == 3 &&
		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"qux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"qux"] &&
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:
		TEST(msg, et == TAG_END && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:
		TEST(msg, et == STRING && [string isEqual: @"\n    "])
		break;
	case 21:
		TEST(msg, et == TAG_START && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"] &&
		    [attrs count] == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"abc"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"abc"] &&
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:
		TEST(msg, et == TAG_END && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:
		TEST(msg, et == STRING && [string isEqual: @"\n   "])
		break;
	case 24:
		TEST(msg, et == TAG_END && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:
		TEST(msg, et == STRING && [string isEqual: @"\n   "])
		break;
	case 26:
		TEST(msg, et == COMMENT && [string isEqual: @" commänt "])
		break;
	case 27:
		TEST(msg, et == STRING && [string isEqual: @"\n  "])
		break;
	case 28:
		TEST(msg, et == TAG_END && [name isEqual: @"qux"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:
		TEST(msg, et == STRING && [string isEqual: @"\n "])
		break;
	case 30:
		TEST(msg, et == TAG_END && [name isEqual: @"foobar"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:
		TEST(msg, et == STRING && [string isEqual: @"\n"])
		break;
	case 32:
		TEST(msg, et == TAG_END && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil);
		break;
	}
}

-		 (void)parser: (OFXMLParser *)parser
  foundProcessingInstructions: (OFString *)pi
{

	[self parserCallbackWithEventType: PROCESSING_INSTRUCTIONS
				     name: nil
				   prefix: nil
				namespace: nil
			       attributes: nil
				   string: pi];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)ns
       attributes: (OFArray *)attrs
{

	[self parserCallbackWithEventType: TAG_START
				     name: name
				   prefix: prefix
				namespace: ns
			       attributes: attrs
				   string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)ns
{

	[self parserCallbackWithEventType: TAG_END
				     name: name
				   prefix: prefix
				namespace: ns
			       attributes: nil
				   string: nil];
}

-    (void)parser: (OFXMLParser *)parser
  foundCharacters: (OFString *)string
{

	[self parserCallbackWithEventType: STRING
				     name: nil
				   prefix: nil
				namespace: nil
			       attributes: nil
				   string: string];
}

- (void)parser: (OFXMLParser *)parser
    foundCDATA: (OFString *)cdata
{

	[self parserCallbackWithEventType: CDATA
				     name: nil
				   prefix: nil
				namespace: nil
			       attributes: nil
				   string: cdata];
}

- (void)parser: (OFXMLParser *)parser
  foundComment: (OFString *)comment
{

	[self parserCallbackWithEventType: COMMENT
				     name: nil
				   prefix: nil
				namespace: nil
			       attributes: nil
				   string: comment];
}

-      (OFString *)parser: (OFXMLParser *)parser
  foundUnknownEntityNamed: (OFString *)entity
{
	if ([entity isEqual: @"foo"])
		return @"foobar";







<












>
|
|
|
|
|
|








|



|



|



|


|



|



|



|


|









|


|










|


|














|


|













|



|


|



















|




|


|


















|



|


|




|


|


|


|



|


|



|


|








>
|
|
|
|
|
|








>
|
|
|
|
|
|







>
|
|
|
|
|
|





>
|
|
|
|
|
|





>
|
|
|
|
|
|





>
|
|
|
|
|
|







26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

#import "OFInvalidEncodingException.h"
#import "OFMalformedXMLException.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLParser";

static int i = 0;

enum event_type {
	PROCESSING_INSTRUCTIONS,
	TAG_START,
	TAG_END,
	STRING,
	CDATA,
	COMMENT
};

@implementation TestsAppDelegate (OFXMLParser)
-   (void)parser: (OFXMLParser *)parser
  didCreateEvent: (enum event_type)type
	    name: (OFString *)name
	  prefix: (OFString *)prefix
       namespace: (OFString *)ns
      attributes: (OFArray *)attrs
	  string: (OFString *)string
{
	OFString *msg;

	i++;
	msg = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(msg, type == PROCESSING_INSTRUCTIONS &&
		    [string isEqual: @"xml version='1.0'"])
		break;
	case 2:
		TEST(msg, type == PROCESSING_INSTRUCTIONS &&
		    [string isEqual: @"p?i"])
		break;
	case 3:
		TEST(msg, type == TAG_START && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil && [attrs count] == 0)
		break;
	case 4:
		TEST(msg, type == STRING && [string isEqual: @"\n\n "])
		break;
	case 5:
		TEST(msg, type == CDATA && [string isEqual: @"f<]]]oo]"] &&
		    [parser lineNumber] == 3)
		break;
	case 6:
		TEST(msg, type == TAG_START && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 7:
		TEST(msg, type == TAG_END && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 8:
		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 9:
		TEST(msg, type == TAG_START && [name isEqual: @"foobar"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:
		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 11:
		TEST(msg, type == TAG_START && [name isEqual: @"qux"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:
		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 13:
		TEST(msg, type == TAG_START && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"] &&
		    [attrs count] == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:
		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 15:
		TEST(msg, type == TAG_START && [name isEqual: @"blup"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    [attrs count] == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:
		TEST(msg, type == TAG_END && [name isEqual: @"blup"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:
		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 18:
		TEST(msg, type == TAG_START && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"] && [attrs count] == 3 &&
		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"qux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"qux"] &&
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:
		TEST(msg, type == TAG_END && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:
		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 21:
		TEST(msg, type == TAG_START && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"] &&
		    [attrs count] == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"abc"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"abc"] &&
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:
		TEST(msg, type == TAG_END && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:
		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 24:
		TEST(msg, type == TAG_END && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:
		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 26:
		TEST(msg, type == COMMENT && [string isEqual: @" commänt "])
		break;
	case 27:
		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 28:
		TEST(msg, type == TAG_END && [name isEqual: @"qux"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:
		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 30:
		TEST(msg, type == TAG_END && [name isEqual: @"foobar"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:
		TEST(msg, type == STRING && [string isEqual: @"\n"])
		break;
	case 32:
		TEST(msg, type == TAG_END && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil);
		break;
	}
}

-		 (void)parser: (OFXMLParser *)parser
  foundProcessingInstructions: (OFString *)pi
{
	[self	    parser: parser
	    didCreateEvent: PROCESSING_INSTRUCTIONS
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: pi];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)ns
       attributes: (OFArray *)attrs
{
	[self	    parser: parser
	    didCreateEvent: TAG_START
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: attrs
		    string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)ns
{
	[self	    parser: parser
	    didCreateEvent: TAG_END
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: nil
		    string: nil];
}

-    (void)parser: (OFXMLParser *)parser
  foundCharacters: (OFString *)string
{
	[self	    parser: parser
	    didCreateEvent: STRING
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: string];
}

- (void)parser: (OFXMLParser *)parser
    foundCDATA: (OFString *)cdata
{
	[self	    parser: parser
	    didCreateEvent: CDATA
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: cdata];
}

- (void)parser: (OFXMLParser *)parser
  foundComment: (OFString *)comment
{
	[self	    parser: parser
	    didCreateEvent: COMMENT
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: comment];
}

-      (OFString *)parser: (OFXMLParser *)parser
  foundUnknownEntityNamed: (OFString *)entity
{
	if ([entity isEqual: @"foo"])
		return @"foobar";
335
336
337
338
339
340
341

342
343
344
345
346
347
348
	    "     bla:foo='blafoo'/>\n"
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";

	size_t j, len;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", R([parser setDelegate: self]))

	/* Simulate a stream where we only get chunks */







>







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
	    "     bla:foo='blafoo'/>\n"
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";
	OFXMLParser *parser;
	size_t j, len;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", R([parser setDelegate: self]))

	/* Simulate a stream where we only get chunks */

Modified utils/ofhttp/OFHTTP.m from [492c8ebbc8] to [511674f2be].

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	}

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}

-    (void)client: (OFHTTPClient *)client
  didCreateSocket: (OF_KINDOF(OFTCPSocket *))socket
	  request: (OFHTTPRequest *)request
{
	if (_insecure && [socket respondsToSelector:
	    @selector(setCertificateVerificationEnabled:)])
		[socket setCertificateVerificationEnabled: false];
}

-	  (bool)client: (OFHTTPClient *)client
  shouldFollowRedirect: (OFURL *)URL
	    statusCode: (int)statusCode
	       request: (OFHTTPRequest *)request
	      response: (OFHTTPResponse *)response







|


|

|







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	}

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}

-    (void)client: (OFHTTPClient *)client
  didCreateSocket: (OF_KINDOF(OFTCPSocket *))sock
	  request: (OFHTTPRequest *)request
{
	if (_insecure && [sock respondsToSelector:
	    @selector(setCertificateVerificationEnabled:)])
		[sock setCertificateVerificationEnabled: false];
}

-	  (bool)client: (OFHTTPClient *)client
  shouldFollowRedirect: (OFURL *)URL
	    statusCode: (int)statusCode
	       request: (OFHTTPRequest *)request
	      response: (OFHTTPResponse *)response
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
		} else
			lengthString =
			    OF_LOCALIZED(@"size_unknown", @"unknown");

		if (_verbose) {
			void *pool = objc_autoreleasePoolPush();
			OFDictionary OF_GENERIC(OFString *, OFString *)
			    *headers = [response headers];
			OFEnumerator *keyEnumerator = [headers keyEnumerator];

			OFEnumerator *objectEnumerator =
			    [headers objectEnumerator];
			OFString *key, *object;

			[of_stdout writeString: @"  "];
			[of_stdout writeLine: OF_LOCALIZED(
			    @"info_name_unaligned",
			    @"Name: %[name]",
			    @"name", fileName)];







|
|
>

|







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
		} else
			lengthString =
			    OF_LOCALIZED(@"size_unknown", @"unknown");

		if (_verbose) {
			void *pool = objc_autoreleasePoolPush();
			OFDictionary OF_GENERIC(OFString *, OFString *)
			    *responseHeaders = [response headers];
			OFEnumerator *keyEnumerator =
			    [responseHeaders keyEnumerator];
			OFEnumerator *objectEnumerator =
			    [responseHeaders objectEnumerator];
			OFString *key, *object;

			[of_stdout writeString: @"  "];
			[of_stdout writeLine: OF_LOCALIZED(
			    @"info_name_unaligned",
			    @"Name: %[name]",
			    @"name", fileName)];

Modified utils/ofhttp/ProgressBar.m from [509373b942] to [55d6da0b1d].

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	    (float)(_resumedFrom + _length) * 100;

	[of_stdout writeString: @"\r  ▕"];

	for (size_t i = 0; i < (size_t)bars; i++)
		[of_stdout writeString: @"█"];
	if (bars < barWidth) {
		float remainder = bars - floorf(bars);

		if (remainder >= 0.875)
			[of_stdout writeString: @"▉"];
		else if (remainder >= 0.75)
			[of_stdout writeString: @"▊"];
		else if (remainder >= 0.625)
			[of_stdout writeString: @"▋"];
		else if (remainder >= 0.5)
			[of_stdout writeString: @"▌"];
		else if (remainder >= 0.375)
			[of_stdout writeString: @"▍"];
		else if (remainder >= 0.25)
			[of_stdout writeString: @"▎"];
		else if (remainder >= 0.125)
			[of_stdout writeString: @"▏"];
		else
			[of_stdout writeString: @" "];

		for (size_t i = 0; i < barWidth - (size_t)bars - 1; i++)
			[of_stdout writeString: @" "];
	}







|

|

|

|

|

|

|

|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	    (float)(_resumedFrom + _length) * 100;

	[of_stdout writeString: @"\r  ▕"];

	for (size_t i = 0; i < (size_t)bars; i++)
		[of_stdout writeString: @"█"];
	if (bars < barWidth) {
		float rem = bars - floorf(bars);

		if (rem >= 0.875)
			[of_stdout writeString: @"▉"];
		else if (rem >= 0.75)
			[of_stdout writeString: @"▊"];
		else if (rem >= 0.625)
			[of_stdout writeString: @"▋"];
		else if (rem >= 0.5)
			[of_stdout writeString: @"▌"];
		else if (rem >= 0.375)
			[of_stdout writeString: @"▍"];
		else if (rem >= 0.25)
			[of_stdout writeString: @"▎"];
		else if (rem >= 0.125)
			[of_stdout writeString: @"▏"];
		else
			[of_stdout writeString: @" "];

		for (size_t i = 0; i < barWidth - (size_t)bars - 1; i++)
			[of_stdout writeString: @" "];
	}